Oracle入門(十四 18)之使用動態SQL

2021-08-20 10:06:33 字數 4874 閱讀 6417

資料庫中的所有sql語句都經歷了不同的階段:

•解析:預執行「這可能嗎?」檢查包括語法,物件存在,許可權等

•繫結:獲取語句中引用的任何變數的實際值

•執行:語句被執行。

•提取:結果返回給使用者。

某些階段可能與所有語句無關;例如,提取階段適用於查詢,但不適用於dml。

當pl / sql子程式中包含sql語句時,解析和繫結階段通常是在編譯時完成的,也就是說,當過程,函式或包體是created時。

如果在建立過程時sql語句的文字未知,該怎麼辦? oracle伺服器如何解析它? 它不能。 例如,假設您想要刪除乙個表,但使用者在執行時輸入表名:

create procedure drop_any_table(p_table_name varchar2)

is begin

drop table p_table_name; -- cannot be parsed

end;

您使用動態sql來建立乙個sql語句,其中的文字事先不完全知道。

動態sql:

•構造並儲存為子程式內的字串。

•是否包含具有不同列資料的sql語句,或帶有或不帶有佔位符(繫結變數)的不同條件。

•使資料定義,資料控制或會話控制語句能夠從pl / sql寫入和執行。

pl / sql不支援直接寫在procedure中的ddl語句。 本地動態sql允許您通過在子程式中構建sql並將其儲存為字串來解決此問題。 本地動態sql:

•以pl / sql語言直接為動態sql提供本機支援。

•使資料定義,資料控制或會話控制語句能夠從pl / sql寫入和執行。

•使用本機動態sql語句(execute immediate)或dbms_sql包執行。

•提供執行直到執行時間結構未知的sql語句的能力。

•也可以使用open-for,fetch和close pl / sql語句。

在pl / sql匿名塊或子程式中為原生動態sql使用execute immediate語句:

execute immediate dynamic_string

[into ]

[using [in|out|in out] bind_argument

[, [in|out|in out] bind_argument] ... ];

•into用於單行查詢,並指定檢索列值的變數或記錄。

•using儲存所有繫結引數。 如果未指定,則預設引數模式為in。

•dynamic_string是包含sql語句文字的字元變數或文字。

•define_variable是乙個pl / sql變數,用於儲存選定的列值。

•record是儲存選定行的使用者定義或%rowtype記錄。

•bind_argument是乙個表示式,其值在執行時傳遞給動態sql語句。

•using子句儲存所有繫結引數。 預設引數模式是in。

示例1:使用ddl語句的動態sql

create procedure drop_any_table(p_table_name varchar2) is

begin

execute immediate 'drop table '||p_table_name;

end;

在乙個變數中構造動態語句:

create procedure drop_any_table(p_table_name varchar2) is

v_dynamic_stmt varchar2(50);

begin

v_dynamic_stmt := 'drop table '||p_table_name;

execute immediate v_dynamic_stmt;

end;

begin

drop_any_table('employee_names');

end;

示例2:使用dml語句的動態sql

刪除任何表中的所有行並返回計數:

create function del_rows(p_table_name varchar2)

return number is

begin

execute immediate 'delete from '||p_table_name;

return sql%rowcount;

end;

呼叫該函式:

declare

v_count number;

begin

v_count := del_rows('employee_names');

dbms_output.put_line(v_count|| ' rows deleted.');

end;

示例3:使用dml語句的動態sql

這是乙個將行插入兩列並呼叫過程的示例。

create procedure add_row(p_table_name varchar2,

p_id number, p_name varchar2) is

begin

execute immediate 'insert into '||p_table_name||

' values (p_id, p_name)';

end;

begin

add_row('employee_names', 250, 'chang');

end;

示例4:使用本機動態sql重新編譯pl / sql**

您可以使用下列alter語句重新編譯pl / sql物件而不重新建立它們:

alter procedure procedure-name compile;

alter function function-name compile;

alter package package_name compile specification;

alter package package-name compile body;

本示例建立乙個過程,用於重新編譯在執行時輸入其名稱和型別的pl / sql物件。

create procedure compile_plsql

(p_name varchar2,p_type varchar2,p_options varchar2 := null) is

v_stmt varchar2(200);

begin

v_stmt := 'alter '||p_type||' '||p_name||' compile'

||' '||p_options;

execute immediate v_stmt;

end;

begin compile_plsql('mypack','package','body'); end;

(1)dbms_sql包的一些過程和功能是:

• open_cursor

• parse

• bind_variable

• execute

• fetch_rows

• close_cursor

(2)使用帶有dml語句的dbms_sql

刪除行的示例:

create or replace function del_rows

(p_table_name varchar2) return number is

v_csr_id integer;

v_rows_del number;

begin

v_csr_id := dbms_sql.open_cursor;

dbms_sql.parse(v_csr_id,

'delete from '||p_table_name, dbms_sql.native);

v_rows_del := dbms_sql.execute (v_csr_id);

dbms_sql.close_cursor(v_csr_id);

return v_rows_del;

end;

請將本文前面的內容與del_rows函式進行比較。 它們功能相同,但更簡單?

(3)使用帶有引數化dml語句的dbms_sql

再次,將其與本課前面的add_row過程進行比較。 你寧願寫什麼?

create procedure add_row (p_table_name varchar2,

p_id number, p_name varchar2) is

v_csr_id integer;

v_stmt varchar2(200);

v_rows_added number;

begin

v_stmt := 'insert into '||p_table_name||

' values ('||p_id||','''||p_name||''')';

v_csr_id := dbms_sql.open_cursor;

dbms_sql.parse(v_csr_id,v_stmt, dbms_sql.native);

v_rows_added := dbms_sql.execute(v_csr_id);

dbms_sql.close_cursor(v_csr_id);

end;

原生動態sql

•比dbms_sql更易於使用

•比dbms_sql需要更少的**

•通常執行速度比dbms_sql快,因為執行的語句較少。

Oracle入門(十四 6)之使用標量資料型別

字元資料型別包括char,varchar2和long。declare v emp job varchar2 9 v order no varchar2 6 v product id varchar2 10 v rpt body part long 數字資料型別包括number,pls integer...

Oracle入門(十四B)之PL SQL異常處理

定義 程式執行過程的警告或錯誤成為例外 exception 其他標準的oracle錯誤,可以自定義異常名,將其與指定oracle錯誤關聯,由系統觸發。例子 在pl sql定義部分宣告 some bad error exception pragma exception init some bad er...

Oracle入門(十四H)之良好的程式設計實踐

一 為什麼要學習它 好的程式設計實踐是技巧,可以按照建立最好的 可能。程式設計實踐涵蓋了一切從 更多可以用更快的速度建立 效能。軟體工程團隊通常會遵循風格指導讓團隊中的每個人使用相同的技術。這使它更容易閱讀和修改編寫的 其他。已經學會了幾種好的程式設計習慣 這個課程 轉化 不要依賴隱式資料型別轉換,...