2009-09-14 46 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, '%') || '%'