2009-09-14 45 views
31

这是我第一次处理Oracle,并且我很难理解为什么我收到此错误。Oracle“ORA-01008:未绑定所有变量”错误(带参数)

我使用的是Oracle的ODT.NET W/C#与查询的WHERE子句在下面的代码:

WHERE table.Variable1 = :VarA 
    AND (:VarB IS NULL OR table.Variable2 LIKE '%' || :VarB || '%') 
    AND (:VarC IS NULL OR table.Variable3 LIKE :VarC || '%') 

和我添加的参数值,像这样:

cmd.Parameters.Add("VarA", "24"); 
cmd.Parameters.Add("VarB", "test"); 
cmd.Parameters.Add("VarC", "1234"); 

当我运行此查询,服务器返回:

ORA-01008: not all variables bound 

如果我注释掉任何的“AND(....”行,查询补偿成功地成功。

如果我只用两个参数查询,而不是用三个查询,为什么查询会顺利运行?我收到甚至没有任何意义的错误

+0

您能够使用DBMS_OUTPUT在执行之前打印出来的SQL语句? – 2009-09-14 15:47:52

回答

42

oracle的ODP.Net提供程序使用按位置绑定作为默认值。将行为更改为按名称绑定。将属性BindByName设置为true。比你可以忽略参数的双重定义。

using(OracleCommand cmd = con.CreateCommand()) { 
    ... 
    cmd.BindByName = true; 
    ... 
} 
+0

更有意义...我昨天重新安排了参数,并意识到它是由变量的位置绑定的,而不是名称(这是不好的);没有意识到有一个选项可以改变这个 – John 2009-09-15 12:02:43

+0

这是很好的Christian13467!我不知道,因此我的经验与本地.Net Oracle数据提供程序从8i到10g。感谢这个答案。 – 2009-09-15 17:57:22

+1

优秀的解决方案。比复制参数好得多。 @约翰 - 你应该真的考虑接受这个答案,如果我可以 - 超过13000人已经看到你的问题,他们应该首先看到更好的选择。(抱歉托尼) – Kobi 2011-09-18 09:25:33

23

这似乎愚蠢,但我认为,当你使用相同的绑定变量两次,你必须设置两次:

cmd.Parameters.Add("VarA", "24"); 
cmd.Parameters.Add("VarB", "test"); 
cmd.Parameters.Add("VarB", "test"); 
cmd.Parameters.Add("VarC", "1234"); 
cmd.Parameters.Add("VarC", "1234"); 

当然,这是与真正的原住民PL/SQL中的动态SQL:

SQL> begin 
    2  execute immediate 'select * from emp where ename=:name and ename=:name' 
    3  using 'KING'; 
    4 end; 
    5/
begin 
* 
ERROR at line 1: 
ORA-01008: not all variables bound 


SQL> begin 
    2  execute immediate 'select * from emp where ename=:name and ename=:name' 
    3  using 'KING', 'KING'; 
    4 end; 
    5/

PL/SQL procedure successfully completed. 
+0

这工作......不能相信它会在那个庄园中行动,但它的工作,所以我会把它!谢谢! – John 2009-09-14 15:59:29

+1

不仅需要多次指定它们,还必须按它们在查询中出现的顺序进行添加。 – 2011-03-18 17:53:39

+0

我并不意味着捎带到一个非常古老的帖子......但是有谁知道这是否(如果多次使用,必须多次添加参数)仍然是这种情况?我正在处理一个奇怪的场景,其中某些东西适用于本地,但在生产中由用户运行时失败。现在已经退出了这个变化,但是为什么'01008'错误只显示给用户,却有些茫然。 – 2015-06-17 21:21:28

2

您还可以考虑通过改变你的SQL消除对您的SQL复制的参数名称需要

table.Variable2 LIKE '%' || :VarB || '%' 

,然后让你的客户对VarB的任何值提供“%”而不是空值。在某些方面,我认为这更自然。

你也可以更改SQL来

table.Variable2 LIKE '%' || IfNull(:VarB, '%') || '%'