ORA-00904 无效标识符 -- 动态 Oracle 函数

Posted

技术标签:

【中文标题】ORA-00904 无效标识符 -- 动态 Oracle 函数【英文标题】:ORA-00904 Invalid Identifier -- Dynamic Oracle function 【发布时间】:2016-11-21 17:47:44 【问题描述】:
    create or replace 
    FUNCTION JDT_UDC_Desc
    (
     V_SY IN VARCHAR2,
      V_RT IN VARCHAR2,
      V_KY IN VARCHAR2
    )
    RETURN VARCHAR2
    AS
       V_DL01 VARCHAR2(30);


BEGIN



   EXECUTE IMMEDIATE 'select drdl01 
       from PRODCTL.F0005
              WHERE DRSY = V_SY
     AND DRRT = V_RT
      AND ltrim(rtrim(drky)) =ltrim(rtrim(V_KY))'
INTO V_DL01
using V_SY,V_RT,V_KY;
END;

编译。我点击运行并输入以下值:

 V_SY ='00',
V_RT = '01',
V_KY='04';

我得到以下错误

ORA-00904 V_KY 标识符无效

谁能帮我理解这个错误的原因?

【问题讨论】:

首先,这里似乎没有任何理由使用动态 SQL。您需要使用动态 SQL 的情况应该很少——如果您坚持使用静态 SQL,您的代码将会更高效、更易于维护。 @JustinCave 我希望这个函数使用动态变量而不是静态的。值 V_SY、V_RT 和 V_KY 是动态变量。我知道静态会很好,但需要它用于应用目的 不需要使用动态SQL。如果您要查询的表的名称或您要返回的列仅在运行时已知,您将使用动态 SQL。静态 SQL 完全能够处理在运行时确定绑定变量的值的查询。事实上,在实际应用程序中,99.99% 的静态 SQL 使用的变量/参数的值直到运行时才知道。 @JustinCave 感谢您提供的信息。您能帮我了解如何通过上述查询获得输出,还是有其他选择?我的要求是当我点击运行时我需要输入我的IN参数然后函数应该返回值 @JustinCave select functionname(parameters) from tablename ...... (my parameters will vary each time) 我应该可以通过这个查询得到我的函数输出 【参考方案1】:

您在语句中传递了文字值“V_SY”、“V_RT”和“V_KY”,并将它们解释为列名,因此出现无效标识符错误。您需要使用变量占位符,例如:

 EXECUTE IMMEDIATE 'select drdl01 
          from PRODCTL.F0005
          WHERE DRSY = :1
          AND DRRT = :2
          AND ltrim(rtrim(drky)) =ltrim(rtrim(:3))'
 INTO V_DL01
 using V_SY,V_RT,V_KY;

【讨论】:

我收到错误,找不到此代码的数据。我输入的值是 00, 01, 04 复制并粘贴带有这些值的 select 语句,然后直接在编辑器中运行它们,看看它是否返回任何数据。 select DRDL01 FROM PRODCTL WHERE DRSY = '00' AND DRRT = '01' AND ltrim(rtrim(drky)) = '04' 这返回了 1 条记录 我在函数SELECT drdl01 INTO V_DL01 FROM PRODCTL.F0005 WHERE DRSY = '00' AND DRRT = '01' AND LTRIM(RTRIM(DRKY)) = '04'; RETURN V_DL01; 中尝试了这段代码......该函数有效并给了我1条记录,但我希望这个函数是动态的而不是静态的 好的,所以继续在占位符周围加上单引号,即WHERE DRSY = ':1'等。【参考方案2】:

首先,这里似乎没有任何理由使用动态 SQL。您需要使用动态 SQL 的情况应该很少——您的代码将更高效且更易于维护。

create or replace 
    FUNCTION JDT_UDC_Desc
    (
      V_SY IN VARCHAR2,
      V_RT IN VARCHAR2,
      V_KY IN VARCHAR2
    )
    RETURN VARCHAR2
    AS
       V_DL01 VARCHAR2(30);
    BEGIN
      select drdl01 
        into V_DL01
        from PRODCTL.F0005
       WHERE DRSY = V_SY
         AND DRRT = V_RT
         AND trim(drky) =trim(V_KY);

      return v_dl01;
    END;

其次,如果您为列和表选择有意义的变量名称和有意义的名称,那将非常有帮助。 F0005 不会告诉您该表包含的内容。 v_sydrsy 没有告诉你变量或列应该包含什么。这将使维护此代码变得更加困难。

【讨论】:

这些表不是我创建的。我们只能通过 dblink 访问这个表,比如 tablename@dblink_instance name。我尝试了上面的代码,它给了我错误'ORA-01403:找不到数据'-------------------------------- ---- select DRDL01 FROM PRODCTL WHERE DRSY = '00' AND DRRT = '01' AND ltrim(rtrim(drky)) = '04' 这在我签入编辑器时返回 1 条记录 这个函数在运行时不知何故没有获取 V_SY、V_RT 和 V_KY 的值 @Simi - 你必须比“不知何故不接受价值观”更具体。如果您收到 ORA-01403: no data found 异常,那么该行至少在它正在运行的会话的上下文中不存在。也许有人在尚未插入的不同事务中插入了一行坚定的。这将使该行对插入它的会话可见,但对其他会话不可见。 @Simi - 如果您有两个不同的会话,您可以在一个会话中执行insert,并且在第一个会话提交之前,数据对另一个会话不可见。如果问题不是事务范围之一,那么您需要发布一个完整的测试用例来重现您的问题。例如,有些列可能是char 而不是varchar2 @Simi - 这就是为什么将一个完整的、可重现的测试用例放在一起非常有用。如果您在 10 天前发布了该消息,我敢打赌问题会在几分钟内得到解决。当您没有完整的、可重现的测试用例时,我们无法看到您所看到的内容,我们必须在黑暗中进行大量猜测。

以上是关于ORA-00904 无效标识符 -- 动态 Oracle 函数的主要内容,如果未能解决你的问题,请参考以下文章

为啥我会收到:[Oracle][ODBC][Ora]ORA-00904:标识符无效

Oracle Where First 和 Last Day 返回 ORA-00904:“NOV”:标识符无效

ORA-00904 无效标识符错误

SQL 错误:ORA-00904:“GENDER”:无效标识符 00904。00000 -“%s:无效标识符”

错误报告:SQL 错误:ORA-00904::无效标识符 00904。00000 - “%s:无效标识符”

ORA-00904: 无效标识符 00904. 00000 - "%s: 无效标识符"