2011-10-19 25 views
38

我有一個問題,關於在PL/SQL中的動態SQL語句中可以使用哪些綁定變量。在PL/SQL中使用綁定變量和動態SELECT INTO子句

例如,我知道,這是有效的:

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER 
IS 
    v_query_str VARCHAR2(1000); 
    v_num_of_employees NUMBER; 
BEGIN 
    v_query_str := 'SELECT COUNT(*) FROM emp_' 
       || p_loc 
       || ' WHERE job = :bind_job';       
    EXECUTE IMMEDIATE v_query_str 
    INTO v_num_of_employees 
    USING p_job; 
    RETURN v_num_of_employees; 
END; 
/

我在想,如果你能在SELECT語句中使用綁定變量,這樣

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER 
IS 
    v_query_str VARCHAR2(1000); 
    v_num_of_employees NUMBER; 
BEGIN 
    v_query_str := 'SELECT COUNT(*) INTO :into_bind FROM emp_' 
       || p_loc 
       || ' WHERE job = :bind_job';       
    EXECUTE IMMEDIATE v_query_str 
    USING out v_num_of_employees, p_job; 
    RETURN v_num_of_employees; 
END; 
/

注意我用了一個SELECT INTO語句作爲我的動態字符串,並在INTO子句中使用綁定變量。

我目前正在旅行,幾天後在家中將無法訪問我的電腦,但這已經讓我有點嘮叨了。嘗試閱讀PL/SQL參考,但他們沒有像這樣的選擇的例子。

謝謝

+0

相關:http://stackoverflow.com/q/25489002/1461424 – Krumia

回答

24

不,你不能以這種方式使用綁定變量。在您的第二個示例中,v_query_str中的:into_bind只是一個佔位符,其值爲變量v_num_of_employees。你的SELECT INTO語句會變成這樣:

SELECT COUNT(*) INTO FROM emp_... 

因爲v_num_of_employeesnullEXECUTE IMMEDIATE

您的第一個示例提供了將返回值綁定到變量的正確方法。

編輯

樓主已經編輯了,我指在我的答案使用OUT參數模式v_num_of_employees而不是默認IN模式的第二個代碼塊。這種修改使這兩個示例在功能上等同。

+0

哦,這是有道理的,':into_bind'將被替換,當它實際運行。在我寫的第一個例子中,它是否仍然在INTO子句中使用綁定變量?我想嘗試第二種方式的原因是因爲它使用綁定變量。 – BYS2

+2

@ BYS2:是的,你可以使用'OUT'參數模式。不過,爲了清楚起見,我更喜歡'EXECUTE IMMEDIATE INTO'。 – user272735

+0

噢好吧,很酷,所以也適用!好吧,謝謝:) – BYS2

18

將select語句放入動態PL/SQL塊中。

CREATE OR REPLACE FUNCTION get_num_of_employees (p_loc VARCHAR2, p_job VARCHAR2) 
RETURN NUMBER 
IS 
    v_query_str VARCHAR2(1000); 
    v_num_of_employees NUMBER; 
BEGIN 
    v_query_str := 'begin SELECT COUNT(*) INTO :into_bind FROM emp_' 
       || p_loc 
       || ' WHERE job = :bind_job; end;'; 
    EXECUTE IMMEDIATE v_query_str 
    USING out v_num_of_employees, p_job; 
    RETURN v_num_of_employees; 
END; 
/
+0

啊,我明白了,謝謝!在附註中,你有什麼想法哪個更好?將SELECT INTO封裝在像你一樣的塊中,或像我在第一個例子中那樣使用EXECUTE IMMEDIATE語句的INTO子句.Do都使用綁定變量?效率有什麼不同? – BYS2

+1

我同意其他人的觀點,第一種方法(動態SQL)比第二種方法(動態PL/SQL)要好得多。 動態PL/SQL非常罕見,幾乎沒有必要。基於一些簡單的測試,我沒有看到兩者之間有任何性能差異,但我預計在某些情況下動態PL/SQL方法會稍微慢一些。動態PL/SQL方法實際上生成3個綁定變量:2爲PL/SQL塊(儘管它們都不在V $ SQL_BIND_CAPTURE中捕獲),1爲SQL查詢。這樣的怪癖可能會使調整和調試變得非常困難。 –

+0

噢好吧,非常感謝您的建議!因爲從技術上講,這不是我的問題,但我無所謂,所以這是很好的知道:D – BYS2

24

在我看來,一個動態的PL/SQL塊有點模糊。雖然非常靈活,但也很難調整,很難調試,很難弄清楚發生了什麼。 我投票給你的第一選擇,

EXECUTE IMMEDIATE v_query_str INTO v_num_of_employees USING p_job; 

兩個使用綁定變量,但首先,對我來說,更多的是redeable比@jonearles選項可調。

+0

好的,謝謝你的信息,因爲兩者都使用綁定varialbes,第一個選項似乎是最好的! – BYS2

+1

@ BYS2:我也最喜歡這個語法。對性能不瞭解。 – user272735

0

綁定變量可以在帶有「in」子句的Oracle SQL查詢中使用。

適用於10g;我不知道其他版本。

綁定變量最多爲4000個字符的varchar。

示例:綁定包含逗號分隔值列表的變量,例如,

:bindvar = 1,2,3,4,5

select * from mytable 
    where myfield in 
    (
     SELECT regexp_substr(:bindvar,'[^,]+', 1, level) items 
     FROM dual 
     CONNECT BY regexp_substr(:bindvar, '[^,]+', 1, level) is not null 
    ); 

(相同信息,因爲我在這裏公佈:How do you specify IN clause in a dynamic query using a variable?

-2

SELECT INTO功能僅適用於PL/SQL塊,當你使用Execute immediate,oracle將v_query_str解釋爲一個SQL查詢字符串,因此您不能使用.will將關鍵字丟失Exception。例2中的 ,我們使用begin end;所以它變成了pl/sql塊和它的合法性。

相關問題