代码之家  ›  专栏  ›  技术社区  ›  gsharp

pl/sql存储过程:参数名与列名相同

  •  23
  • gsharp  · 技术社区  · 15 年前

    我有一个这样的存储过程

    procedure P_IssueUpdate
    (
        Id in integer,
        ModifiedDate in date,
        Solution in varchar2
    ) AS
    BEGIN
    update T_Issue
    Set
      ModifiedDate = ModifiedDate,
      Solution = Solution
    where id = id;
    END P_IssueUpdate;
    

    我的问题是参数名与表列名相同。 是否有方法指示SQL“=”后面的值应该是参数而不是列?

    谢谢你的帮助

    4 回复  |  直到 15 年前
        1
  •  39
  •   Tony Andrews    15 年前

    您可以使用以下过程的名称作为参数和变量名称的前缀:

    SQL> declare
      2     procedure p (empno number) is
      3        ename varchar2(10);
      4     begin
      5        select ename
      6        into p.ename
      7        from emp
      8        where empno = p.empno;
      9        dbms_output.put_line(p.ename);
     10     end;
     11  begin
     12     p (7839);
     13  end;
     14  /
    KING
    
    PL/SQL procedure successfully completed.
    
        2
  •  6
  •   Vincent Malgrat    15 年前

    你所描述的叫做 variable shadowing . 它可以用任何语言发生。您得到了很好的解决方案,但常见的解决方案是设计一个命名方案,这样它就永远不会发生。

    例如,命名没有前缀的列,并让变量具有取决于其范围的前缀。( P_ 对于参数, L_ 对于局部变量, G_ 对于全局包变量等)。这将有一个额外的好处,通过提供额外的信息使代码更具可读性。

        3
  •  4
  •   gsharp    15 年前

    我找到了解决办法。它通过完全限定参数来工作:

    procedure P_IssueUpdate
    (
        Id in integer,
        ModifiedDate in date,
        Solution in varchar2
    ) AS
    BEGIN
    update T_Issue
    Set
      ModifiedDate = P_IssueUpdate.ModifiedDate,
      Solution = P_IssueUpdate.Solution
    where id = P_IssueUpdate.id;
    END P_IssueUpdate;
    
        4
  •  3
  •   Jim    15 年前

    Re-Vincent关于前缀的回答——这个解决方案一直有效,直到有人修改了表并添加了一个名恰好与参数名冲突的列。不是每个人都要检查每一行代码,以确保他们的表修改不会与变量或参数名冲突。Oracle的建议是限定SQL查询中的每个参数或变量名。

    如果您使用的是匿名块(在过程之外),则可以用这种方式命名块并限定变量:

    <<MY_BLOCK>>
    declare
       X   sys.USER_TABLES%rowtype;
       Y   sys.USER_TABLES.TABLE_NAME%type := 'some_table_name';
    begin
       select UT.*
       into   MY_BLOCK.X
       from   sys.USER_TABLES UT
       where  UT.TABLE_NAME = MY_BLOCK.Y;
    end MY_BLOCK;