oracle 存儲過程 調用動態sql
CreationTime--2018年8月16日11點25分
Author:Marydon
1.錯誤實現方式
--開始時間拼接' 00:00:00' V_SQL := 'select decode(length(' || V_END || '),10,' || 'concat(' || V_END || ', 00:00:00),' || V_END || ') from dual'; EXECUTE IMMEDIATE V_SQL;
編譯成功,但是存儲過程調用失敗。
2.原因分析
在oracl數據庫中,ddl表示數據庫定義語言,即我們平常使用的sql語句,聲明的sql語句可以直接使用拼接字符串進行拼接;
dml表示數據操縱語言,聲明的sql語句不能再用管道符||來動態拼接變量。
3.正確實現方式
execute immediate屬於dml,dml使用sql的規則如下:
聲明sql語句
字符串拼接變量時,變量要使用占位符來代替,格式為 ":" + "名字",名字隨意
調用sql語句
使用"using"來傳遞變量,代替占位符,格式為 "using var1,var2,..."
V_SQL := 'select decode(length(:v1),10,:v2,:v3) from dual'; EXECUTE IMMEDIATE V_SQL INTO V_START USING V_START,V_START || ' 00:00:00',V_START;
結果展示:
4.測試
入參
出參
5.最簡單的方式
--結束時間拼接' 00:00:00' SELECT DECODE(LENGTH(V_END), 10, V_END || ' 00:00:00', V_END) INTO V_END FROM DUAL;
20200612
6.另外一種方式
第一種字符串拼接的方式其實也是可以執行的,只不過需要借助游標來實現,這里張貼部分代碼
--業務執行 OPEN OUT_CURSOR FOR 'SELECT TO_CHAR(TO_DATE(' || STARTTIME || ', ''YYYY-MM-DD'') + ROWNUM - 1, ''YYYY-MM-DD'') AS REGDATE FROM DUAL CONNECT BY ROWNUM <= TRUNC(TO_DATE(' || ENDTIME || ', ''YYYY-MM-DD'') - TO_DATE(' || STARTTIME || ', ''YYYY-MM-DD'')) + 1';
游標后面可以直接拼接SQL字符串,並將其當做SQL來執行(這是在存儲過程調用的)
結果如下
另外對於單引號的轉義,兩個緊挨的單引號'',就表示一個轉義過的單引號'