Oracle 在这些情况下,编译器忽略NOCOPY

Oracle 在这些情况下,编译器忽略NOCOPY,oracle,plsql,parameter-passing,Oracle,Plsql,Parameter Passing,我读到了关于进进出出和NOCOPY的文章。然后我遇到了NOCOPY用例,但我无法得到它。有人能举例说明这些吗?提前谢谢 实际参数必须隐式转换为形式参数的数据类型 declare n varchar2(3) := '23'; begin tst(n); dbms_output.put_line(n); end; / 实际参数是集合的元素 declare nt sys.odcinumberlist := sys.odcinumberlist(17,23,69); begin t

我读到了关于进进出出和NOCOPY的文章。然后我遇到了NOCOPY用例,但我无法得到它。有人能举例说明这些吗?提前谢谢

  • 实际参数必须隐式转换为形式参数的数据类型

  • declare
      n varchar2(3) := '23';
    begin
      tst(n);
      dbms_output.put_line(n);
    end;
    /
    
  • 实际参数是集合的元素

  • declare
      nt sys.odcinumberlist := sys.odcinumberlist(17,23,69);
    begin
      tst(nt(2));
      dbms_output.put_line(to_char(nt(2)));
    end;
    /
    
  • 实际参数是带有
    NOT NULL
    约束的标量变量

  • declare
      n number not null := 23;
    begin
      tst(n);
      dbms_output.put_line(to_char(n));
    end;
    /
    
    declare
      n number(5,2) := 23;
    begin
      tst(n);
      dbms_output.put_line(to_char(n));
    end;
    /
    
  • 实际参数是具有范围、大小、比例或精度约束的标量数值变量

  • declare
      n number not null := 23;
    begin
      tst(n);
      dbms_output.put_line(to_char(n));
    end;
    /
    
    declare
      n number(5,2) := 23;
    begin
      tst(n);
      dbms_output.put_line(to_char(n));
    end;
    /
    
  • 实际参数和形式参数都是记录,其中一个或两个参数是用
    %ROWTYPE
    %TYPE
    声明的,相应字段上的约束不同

  • declare
      type r34 is record (id number, dt date);
      r r34;
    begin
      r.id := 23;
      r.dt := to_date(null); --trunc(sysdate);
      tst2(r);
      dbms_output.put_line(to_char(r.id));
    end;
    /
    
    begin
      for j in ( select * from t34) loop
        tst3(j);
        dbms_output.put_line(to_char(j.id));
      end loop;   
    end;
    /
    
  • 实际参数和形式参数是记录,实际参数被声明(隐式)为循环语句的游标索引,相应字段上的约束不同

  • declare
      type r34 is record (id number, dt date);
      r r34;
    begin
      r.id := 23;
      r.dt := to_date(null); --trunc(sysdate);
      tst2(r);
      dbms_output.put_line(to_char(r.id));
    end;
    /
    
    begin
      for j in ( select * from t34) loop
        tst3(j);
        dbms_output.put_line(to_char(j.id));
      end loop;   
    end;
    /
    
  • 子程序通过数据库链接或作为外部子程序调用

  • declare
      n number := 23;
    begin
      tst@remote_db(n);
      dbms_output.put_line(to_char(n));
    end;
    /
    

    基本原则是,只要我们传递的值可以按提供的那样使用,而不需要转换,并且可以由被调用的程序寻址,PL/SQL就会遵守NOCOPY指令。您列出的场景是情况并非如此的情况。我必须承认有几个例子让我思考,所以这是一个值得的练习

    前四个例子称之为玩具程序

    创建或替换程序tst2(p1 in out nocopy t34%行类型)无效
    开始
    p1.id:=42;
    结束;
    /
    
    案例1:实际参数必须隐式转换为形式参数的数据类型

    declare
      n varchar2(3) := '23';
    begin
      tst(n);
      dbms_output.put_line(n);
    end;
    /
    
    案例2:实际参数是集合的元素

    declare
      nt sys.odcinumberlist := sys.odcinumberlist(17,23,69);
    begin
      tst(nt(2));
      dbms_output.put_line(to_char(nt(2)));
    end;
    /
    
    案例3:实际参数是带有NOTNULL约束的标量变量

    declare
      n number not null := 23;
    begin
      tst(n);
      dbms_output.put_line(to_char(n));
    end;
    /
    
    declare
      n number(5,2) := 23;
    begin
      tst(n);
      dbms_output.put_line(to_char(n));
    end;
    /
    
    案例4:实际参数是具有范围、大小、比例或精度约束的标量数值变量

    declare
      n number not null := 23;
    begin
      tst(n);
      dbms_output.put_line(to_char(n));
    end;
    /
    
    declare
      n number(5,2) := 23;
    begin
      tst(n);
      dbms_output.put_line(to_char(n));
    end;
    /
    
    下一个示例使用此表

    create table t34 (id number not null, col1 date not null)
    /
    
    …和玩具程序:

    create or replace procedure tst2 (p1 in out nocopy t34%rowtype) is
    begin
      p1.id := 42;
    end;
    /
    
    create or replace procedure tst3 (p1 in out nocopy pkg.r34) is
    begin
      p1.id := p1.id + 10;
    end;
    /
    
    案例5:实际参数和形式参数都是记录,其中一个或两个参数是用%ROWTYPE或%TYPE声明的,相应字段上的约束不同

    declare
      type r34 is record (id number, dt date);
      r r34;
    begin
      r.id := 23;
      r.dt := to_date(null); --trunc(sysdate);
      tst2(r);
      dbms_output.put_line(to_char(r.id));
    end;
    /
    
    begin
      for j in ( select * from t34) loop
        tst3(j);
        dbms_output.put_line(to_char(j.id));
      end loop;   
    end;
    /
    
    下一个示例使用此包规范

    create or replace package pkg is
      type r34 is record (id number, dt date);
    end;
    /
    
    …和玩具程序:

    create or replace procedure tst2 (p1 in out nocopy t34%rowtype) is
    begin
      p1.id := 42;
    end;
    /
    
    create or replace procedure tst3 (p1 in out nocopy pkg.r34) is
    begin
      p1.id := p1.id + 10;
    end;
    /
    
    案例6:实际参数和形式参数是记录,实际参数被声明(隐式)为循环语句游标的索引,相应字段上的约束不同

    declare
      type r34 is record (id number, dt date);
      r r34;
    begin
      r.id := 23;
      r.dt := to_date(null); --trunc(sysdate);
      tst2(r);
      dbms_output.put_line(to_char(r.id));
    end;
    /
    
    begin
      for j in ( select * from t34) loop
        tst3(j);
        dbms_output.put_line(to_char(j.id));
      end loop;   
    end;
    /
    
    最后一个示例使用第一个过程的远程版本

    案例7:通过数据库链接或作为外部子程序调用子程序

    declare
      n number := 23;
    begin
      tst@remote_db(n);
      dbms_output.put_line(to_char(n));
    end;
    /
    
    有前六个案例的工作演示