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参数然后函数应该返回值 @JustinCaveselect 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_sy
和 drsy
没有告诉你变量或列应该包含什么。这将使维护此代码变得更加困难。
【讨论】:
这些表不是我创建的。我们只能通过 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”:标识符无效
SQL 错误:ORA-00904:“GENDER”:无效标识符 00904。00000 -“%s:无效标识符”