plsql动态的sql
12 動態(tài)SQL語句和動態(tài)PLSQL語句
?SQL語句 --? 靜態(tài)的SQL語句、動態(tài)的SQL語句
?靜態(tài)的SQL語句? --? 在編譯的時(shí)候已經(jīng)確定的SQL,語法和語義引用也是在編譯的時(shí)候確定下來的?? ?
?動態(tài)的SQL語句? --? 由字符串組成,在運(yùn)行的時(shí)候編譯和執(zhí)行
12.1 動態(tài)SQL語句
(1) 動態(tài)SQL的簡單案例
案例1: 動態(tài)創(chuàng)建表示例
?
declare
? dyn_tab_name varchar2(30):='temp';
? dyn_string varchar2(150);
begin
? dyn_string:='create table '||dyn_tab_name||' (col number not null)';
? execute immediate dyn_string;??????????????????? --動態(tài)運(yùn)行,在匿名塊里面調(diào)用DDL,要加execute immediate
end;
SQL> desc temp;
Name Type?? Nullable Default Comments
---- ------ -------- ------- --------
COL? NUMBER????????????????????????? ?
?
改寫為存儲過程:
create or replace procedure p21 is
? dyn_tab_name varchar2(30):='temp';
? dyn_string varchar2(150);
begin
? dyn_string:='create taeble '||dyn_tab_name||' (col number not null)'; --有語法錯誤的,但是編譯的時(shí)候不會報(bào)錯
? execute immediate dyn_string;????????????? ?
end;
SQL> exec p21;????????????? --在執(zhí)行的時(shí)候報(bào)錯
BEGIN p21; END;
*
ERROR at line 1:
ORA-00901: invalid CREATE command
ORA-06512: at "PLSQL.P21", line 6
ORA-06512: at line 1
create or replace procedure p21 is
? dyn_tab_name varchar2(30):='temp';
? dyn_string varchar2(150);
begin
? dyn_string:='create table '||dyn_tab_name||' (col number not null)';
? execute immediate dyn_string;????????????? ?
end;
SQL> exec p21;
BEGIN p21; END;
*
ERROR at line 1:
ORA-01031: insufficient privileges????????????? --權(quán)限不足
ORA-06512: at "PLSQL.P21", line 6
ORA-06512: at line 1
create or replace procedure p21 authid current_user is????????? --正確的寫法
?--在存儲過程中出現(xiàn)動態(tài)SQL的時(shí)候,需要在SP的頭部加上authid current_user顯式授權(quán)語句,將執(zhí)行的權(quán)限授給當(dāng)前的用戶
? dyn_tab_name varchar2(30):='temp1';
? dyn_string varchar2(150);
begin
? dyn_string:='create table '||dyn_tab_name||' (col number not null)';
? execute immediate dyn_string;????????????? ?
end;
SQL> exec p21;
PL/SQL procedure successfully completed.
SQL> desc temp1;
?Name?? ??? ??? ??? ??? ??? Null???? Type
?----------------------------------------- -------- ----------------------------
?COL?? ??? ??? ??? ??? ??? NOT NULL NUMBER
總結(jié):在存儲過程中使用動態(tài)SQL語句,如果SQL語句語法有問題,在編譯的時(shí)候不會報(bào)錯,只有在調(diào)用SP的時(shí)候才會報(bào)錯
? 在存儲過程中出現(xiàn)動態(tài)SQL的時(shí)候,需要在SP的頭部加上authid current_user顯式授權(quán)語句,將執(zhí)行的權(quán)限授給當(dāng)前的用戶
?
案例2:動態(tài)創(chuàng)建表
create or replace procedure create_dyn_table(i_region_name in varchar2,retcd out number,errmsg out varchar2) authid current_user is
? dyn_tab_name varchar2(200);
? dyn_string varchar2(2000);
begin
? dyn_string:='';
? dyn_tab_name:='ORDERS_FOR_'||replace(i_region_name,' ','');?? --去掉空格
? dyn_string:='create table '||dyn_tab_name||' (order_id number(10) primary key,order_date date not null,total_qty number,total_price number(15,2))';
? execute immediate dyn_string;
? retcd:=0;
? errmsg:='successful!';
exception when others then
? retcd:=sqlcode;
? errmsg:=sqlerrm;
end;
測試:
declare
? v_sqlcode number;
? v_sqlerrm varchar2(100);
begin
? create_dyn_table('? u? k? ',v_sqlcode,v_sqlerrm);
? dbms_output.put_line(v_sqlerrm);
end;
select * from orders_for_uk;
案例3:通過動態(tài)SQL給表添加外鍵
create or replace procedure create_dyn_table2(i_region_name in varchar2,retcd out number,errmsg out varchar2) authid current_user is
? dyn_tab_name varchar2(200);
? dyn_string varchar2(2000);
begin
? dyn_tab_name:='ORDERS_ITEMS_FOR_'||replace(i_region_name,' ','');
? dyn_string:='create table '||dyn_tab_name||' (order_id number(10) not null,item_id varchar2(20) not null,unit_pirce number(15,2),quantity number)';
? execute immediate dyn_string;
? dyn_string:='alter table '||dyn_tab_name||' add constraint '||' FK_OIFOR_'||replace(i_region_name,' ','')||' foreign key(order_id) references orders_for_'||replace(i_region_name,' ','')||'(order_id)';
? execute immediate dyn_string;
? retcd:=0;
? errmsg:='successful!';
exception when others then
? retcd:=sqlcode;
? errmsg:=sqlerrm;
end;
測試:
declare
? v_sqlcode number;
? v_sqlerrm varchar2(100);
begin
? create_dyn_table2('? u? k? ',v_sqlcode,v_sqlerrm);
? dbms_output.put_line(v_sqlerrm);
end;
select * from orders_items_for_uk;
select * from user_constraints where table_name='ORDERS_ITEMS_FOR_UK';
案例4:按照地區(qū)配置表,創(chuàng)建每個銷售區(qū)域訂單表跟訂單明細(xì)表
地區(qū)配置表:
insert into region_tab values(1,'region1');
insert into region_tab values(2,'region2');
insert into region_tab values(3,'region3');
insert into region_tab values(4,'region4');
commit;
select * from region_tab;
region_tab? ->? orders_for_
??????????? ->? orders_items_for_
有四個銷售區(qū)域,每個銷售區(qū)域需要有訂單表跟訂單明細(xì)表,表的結(jié)構(gòu)都是一樣的
create or replace procedure create_dyn_for_all(retcd out number,errmsg out varchar2) authid current_user is
? cursor csr_region is select * from region_tab;
begin
? for idx in csr_region loop
??? create_dyn_table(idx.region_name,retcd,errmsg);
??? if retcd <> 0 then
????? exit;
??? end if;
??? create_dyn_table2(idx.region_name,retcd,errmsg);
??? if retcd <> 0 then
????? exit;
??? end if;
? end loop;
exception when others then
? retcd:=sqlcode;
? errmsg:=sqlerrm;
end;
測試:
declare
? v_sqlcode number;
? v_sqlerrm varchar2(100);
begin
? create_dyn_for_all(v_sqlcode,v_sqlerrm);
? dbms_output.put_line(v_sqlerrm);
end;
select * from user_tables where table_name like 'ORDERS%';????? --查看到新創(chuàng)建了8個表
(2) 動態(tài)創(chuàng)建表
? 設(shè)計(jì)方式--根據(jù)配置表動態(tài)實(shí)現(xiàn)功能,只需要維護(hù)外面的配置表的內(nèi)容,將功能封裝
? 需求:字段名和表名都用配置表來配置,實(shí)現(xiàn)動態(tài)創(chuàng)建表的過程
? 步驟:
? A 創(chuàng)建表1:配置表名
create table table_config(
tab_id number primary key,
table_name varchar2(20) not null,
crt_flag varchar2(2)
);
?
?B 插入初始化數(shù)據(jù):
insert into table_config values(1,'A','0');
insert into table_config values(2,'B','0');
commit;
?C 創(chuàng)建表2:配置字段的表
create table column_config(
col_id number not null,
tab_id number not null,
col_name varchar2(20),
col_type varchar2(20),
col_length number,
col_pre number
);
添加主外鍵:
alter table column_config add constraint PK_COL_CFG primary key(col_id,tab_id);
alter table column_config add constraint FK_COL_CFG foreign key(tab_id) references table_config(tab_id);
?
?D 初始化字段表
insert into column_config values(1,1,'A1','varchar2',20,null);
insert into column_config values(2,1,'A2','char',3,null);
insert into column_config values(3,1,'A3','number',12,null);
insert into column_config values(4,1,'A4','number',11,4);
insert into column_config values(5,1,'A5','date',null,null);
insert into column_config values(6,2,'B1','varchar2',22,null);
insert into column_config values(7,2,'B2','char',13,null);
insert into column_config values(8,2,'B3','number',20,null);
insert into column_config values(9,2,'B4','date',null,null);
insert into column_config values(10,2,'B5','number',12,2);
commit;
E 編寫功能模塊
模塊1:讀取字段配置表進(jìn)行字段類型串的拼接
?
create or replace function dyn_type(i_type in varchar2,i_length in number,i_pre in number) return varchar2 is
? v_dyn_type varchar2(1000);
begin
? if i_type='varchar2' then
??? v_dyn_type:=i_type||'('||i_length||')';
? elsif i_type='char' then
??? v_dyn_type:=i_type||'('||i_length||')'; ?
? elsif i_type='date' then
??? v_dyn_type:=i_type;
? elsif i_type='number' then
??? if i_length is not null and i_pre is not null then
????? v_dyn_type:=i_type||'('||i_length||','||i_pre||')';
??? elsif i_length is not null and i_pre is null then
????? v_dyn_type:=i_type||'('||i_length||')';
??? elsif i_length is null and i_pre is null then
????? v_dyn_type:=i_type;
??? end if;
? end if;
? return v_dyn_type;
exception when others then
? return '';
end;
模塊2:拼接創(chuàng)建表語句中類型模塊
create or replace procedure dyn_crt_tab(i_tab_name in varchar2,i_crt_string out varchar2,retcd out number,errmsg out varchar2) authid current_user is
? cursor csr_tab is select h.tab_id,h.table_name,o.col_type,o.col_name,o.col_length,o.col_pre
????????????????????? from column_config o,table_config h
???????????????????? where o.tab_id=h.tab_id
?????????????????????? and h.table_name=i_tab_name;
? csr_rec csr_tab%rowtype;
? dyn_col_type varchar2(100);
? dyn_tab_p varchar2(4000);
begin
? open csr_tab;
? dyn_tab_p:='';
? loop
??? fetch csr_tab into csr_rec;
??? exit when (csr_tab%notfound);
??? dyn_col_type:=dyn_type(csr_rec.col_type,csr_rec.col_length,csr_rec.col_pre)||',';?? --調(diào)用拼接字段的函數(shù)
??? dyn_tab_p:=dyn_tab_p||csr_rec.col_name||' '||dyn_col_type;
? end loop;
??? dyn_tab_p:=substr(dyn_tab_p,1,instr(dyn_tab_p,',',-1,1)-1);? --將最后一個','去掉
??? i_crt_string:=dyn_tab_p;
? close csr_tab;
? retcd:=0;
? errmsg:='successful!';
exception when others then
? retcd:=sqlcode;
? errmsg:=sqlerrm;
end;
模塊3:執(zhí)行模塊
create or replace procedure dyn_crt(retcd out number,errmsg out varchar2) authid current_user is
? cursor csr_tab is select h.tab_id,h.table_name
????????????????????? from table_config h
???????????????????? where h.crt_flag='0';
? csr_rec csr_tab%rowtype;
? dyn_string varchar2(4000);
? v_crt_table varchar2(4000);
? v_sqlcode number;
? v_sqlerrm varchar2(200);
begin
? open csr_tab;
? dyn_string:='';
? loop
??? fetch csr_tab into csr_rec;
??? exit when(csr_tab%notfound);
??? dyn_crt_tab(csr_rec.table_name,v_crt_table,v_sqlcode,v_sqlerrm);??????????????? --調(diào)用表拼接的存儲過程
??? dyn_string:='create table '||csr_rec.table_name||'('||v_crt_table||')';??? ?
??? execute immediate dyn_string;
??? update table_config set crt_flag='1' where tab_id=csr_rec.tab_id;
??? commit;
? end loop;
? close csr_tab;
? retcd:=0;
? errmsg:='successful!';
exception when others then
? retcd:=sqlcode;
? errmsg:=sqlerrm;
end;
測試:
declare
? v_sqlcode number;
? v_sqlerrm varchar2(200);
begin
? dyn_crt(v_sqlcode,v_sqlerrm);
? dbms_output.put_line(v_sqlerrm);
end;
SQL> desc a
?Name?? ??? ??? ??? ??? ??? Null???? Type
?----------------------------------------- -------- ----------------------------
?A1?? ??? ??? ??? ??? ??? ???? VARCHAR2(20)
?A2?? ??? ??? ??? ??? ??? ???? CHAR(3)
?A3?? ??? ??? ??? ??? ??? ???? NUMBER(12)
?A4?? ??? ??? ??? ??? ??? ???? NUMBER(11,4)
?A5?? ??? ??? ??? ??? ??? ???? DATE
SQL> desc b
?Name?? ??? ??? ??? ??? ??? Null???? Type
?----------------------------------------- -------- ----------------------------
?B1?? ??? ??? ??? ??? ??? ???? VARCHAR2(22)
?B2?? ??? ??? ??? ??? ??? ???? CHAR(13)
?B3?? ??? ??? ??? ??? ??? ???? NUMBER(20)
?B4?? ??? ??? ??? ??? ??? ???? DATE
?B5?? ??? ??? ??? ??? ??? ???? NUMBER(12,2)
練習(xí):
?
?A 將上面3個子程序封裝在一個package中存儲,其中函數(shù)還有另外一個存儲作為私有對象。
?在包頭加上authid current_user
?存儲過程中authid current_user去掉
?B 開發(fā)一個動態(tài)drop表的SP封裝在上面創(chuàng)建的包中,要求,在table_config表上添加一個字段,drop_flag varchar2(2)
??? 刪除標(biāo)記,如果為1,表示要刪除,如果為0表示保留,將所有標(biāo)記為1的表刪除掉,如果刪除的時(shí)候發(fā)現(xiàn)已經(jīng)被刪除了,則要捕獲異常將數(shù)據(jù)插入到我們之前創(chuàng)建異常監(jiān)控表中,與此同時(shí)創(chuàng)建標(biāo)記crt_flag置為0
??? alter table table_config add drop_flag varchar2(2);
?C 開發(fā)動態(tài)刪除和添加字段的模塊,需要在字段配置表上添加刪除和添加的標(biāo)記字段。
?
??? alter table column_config add add_flag varchar2(2);
??? alter table column_config add del_flag varchar2(2);
包頭:
create or replace package dyn_pkg authid current_user is
? procedure dyn_crt(retcd out number,errmsg out varchar2);
? procedure dyn_drop(retcd out number, errmsg out varchar2);
? procedure dyn_add(retcd out number, errmsg out varchar2);
? procedure dyn_del(retcd out number, errmsg out varchar2);
end dyn_pkg;
包體:
create or replace package body dyn_pkg is
?function dyn_type(i_type in varchar2,i_length in number,i_pre in number)
??? return varchar2 is
??? v_dyn_type varchar2(1000);
? begin
??? if i_type='VARCHAR2' then
????? v_dyn_type:=i_type||'('||i_length||')';
??? elsif i_type='CHAR' then
????? v_dyn_type:=i_type||'('||i_length||')';
??? elsif i_type='DATE' then
????? v_dyn_type:=i_type;
??? elsif i_type='NUMBER' then
????? if i_length is not null and i_pre is not null then
??????? v_dyn_type:=i_type||'('||i_length||','||i_pre||')';
????? elsif i_length is not null and i_pre is? null then
??????? v_dyn_type:=i_type||'('||i_length||')';
????? elsif i_length is? null and i_pre is? null then
??????? v_dyn_type:=i_type;
????? end if;
??? end if;
??? return v_dyn_type;
? exception when others then
??? return '';
? end;
?procedure dyn_crt_tab(i_tab_name in varchar2,i_crt_string out varchar2,retcd out number,errmsg out varchar2) is
??? cursor csr_tab is select h.tab_id,h.table_name,o.col_type,o.col_name,o.col_length,o.col_pre
?????????????? from column_config o,table_config h
????????????? where o.tab_id=h.tab_id
??????????????? and h.table_name=i_tab_name;
??? csr_rec csr_tab%rowtype;
??? dyn_col_type varchar2(100);
??? dyn_tab_p varchar2(4000);
? begin
??? open csr_tab;
??? dyn_tab_p:='';
??? loop
????? fetch csr_tab into csr_rec;
????? exit when(csr_tab%notfound);
????? dyn_col_type:=dyn_type(csr_rec.col_type,csr_rec.col_length,csr_rec.col_pre)||',';?? --調(diào)用拼接字段的函數(shù)
????? dyn_tab_p:=dyn_tab_p||csr_rec.col_name||' '||dyn_col_type;
??? end loop;
??? dyn_tab_p:=substr(dyn_tab_p,1,instr(dyn_tab_p,',',-1,1)-1);??? --將最后一個‘,’去掉
??? i_crt_string:=dyn_tab_p;
??? close csr_tab;
??? retcd:=0;
??? errmsg:='successful!';
? exception when others then
??? retcd:=sqlcode;
??? errmsg:=sqlerrm;
? end;
?procedure dyn_crt(retcd out number,errmsg out varchar2) is
??? cursor csr_tab is select h.tab_id,h.table_name
???????????????? from table_config h
??????????????? where h.crt_flag='0';
??? csr_rec csr_tab%rowtype;
??? dyn_string varchar2(4000);
??? v_crt_table varchar2(4000);
??? v_retcd number;
??? v_errmsg varchar2(150);
? begin
??? open csr_tab;
??? dyn_string:='';
??? loop
????? fetch csr_tab into csr_rec;
????? exit when(csr_tab%notfound);
????? dyn_crt_tab(csr_rec.table_name,v_crt_table,v_retcd,v_errmsg);??? --調(diào)用表拼接的函數(shù)
????? dyn_string:='create table '||csr_rec.table_name||'('||v_crt_table||')';
????? execute immediate dyn_string;
????? update table_config set crt_flag='1' where tab_id=csr_rec.tab_id;
????? commit;
??? end loop;
??? close csr_tab;
??? retcd:=0;
??? errmsg:='successful!';
? exception when others then
??? retcd:=sqlcode;
??? errmsg:=sqlerrm;
? end;
? procedure dyn_drop(retcd out number, errmsg out varchar2) is
?? ??? ?cursor csr_drop is
?? ??? ???? select table_name, tab_id
?? ??? ?????? from table_config
?? ??? ????? where drop_flag = '1';
?? ??? ?csr_rec csr_drop%rowtype;
?? ??? ?dyn_drop_config varchar2(100);
?? ??? ?sqlnotfound exception;
?? ??? ?pragma exception_init(sqlnotfound,-942);
?? ??? ?v_sqlcode number;
?? ??? ?v_sqlerrm varchar2(100);
?? ???? begin
?? ??? ?open csr_drop;
?? ??? ?dyn_drop_config := '';
?? ??? ?loop
?? ??? ???? fetch csr_drop
?? ??? ???????? into csr_rec;
?? ??? ???? exit when(csr_drop%notfound);
?? ??? ???? dyn_drop_config := 'drop table ' || csr_rec.table_name;
?? ??? ???? execute immediate dyn_drop_config;
?? ??? ?end loop;
?? ??? ?close csr_drop;
?? ??? ?retcd? := 0;
?? ??? ?errmsg := 'successful';
?? ???? exception
?? ??? ?when sqlnotfound then
?? ??? ?v_sqlcode:=sqlcode;
?? ??? ?v_sqlerrm:=sqlerrm;
?? ??? ???? insert into exception_monitor?? ??? ???? values
?? ??? ???????? (csr_rec.table_name,
?? ??? ????????? csr_rec.tab_id,
?? ??? ????????? upper('dyn_drop'),
?? ??? ????????? upper('sqlnotfound'),
?? ??? ????????? v_sqlcode,
?? ??? ????????? v_sqlerrm,
?? ??? ????????? sysdate);
?? ??? ???? update table_config
?? ??? ??????? set drop_flag = '0'
?? ??? ????? where tab_id = csr_rec.tab_id;
?? ??? ?when others then
?? ??? ???? retcd? := sqlcode;
?? ??? ???? errmsg := sqlerrm;
?? ???? end;
? procedure dyn_add(retcd out number, errmsg out varchar2) is
?? ??? ?cursor csr_add is
?? ??? ???? select t.table_name,
?? ??? ??????????? t.tab_id,
?? ??? ??????????? c.col_id,
?? ??? ??????????? c.col_name,
?? ??? ??????????? c.col_type,
?? ??? ??????????? c.col_length,
?? ??? ??????????? c.col_pre
包頭:
create or replace package dyn_pkg authid current_user is
? procedure dyn_crt(retcd out number,errmsg out varchar2);
? procedure dyn_drop(retcd out number, errmsg out varchar2);
? procedure dyn_add(retcd out number, errmsg out varchar2);
? procedure dyn_del(retcd out number, errmsg out varchar2);
end dyn_pkg;
包體:
create or replace package body dyn_pkg is
?function dyn_type(i_type in varchar2,i_length in number,i_pre in number)
??? return varchar2 is
??? v_dyn_type varchar2(1000);
? begin
??? if i_type='VARCHAR2' then
????? v_dyn_type:=i_type||'('||i_length||')';
??? elsif i_type='CHAR' then
????? v_dyn_type:=i_type||'('||i_length||')';
??? elsif i_type='DATE' then
????? v_dyn_type:=i_type;
??? elsif i_type='NUMBER' then
????? if i_length is not null and i_pre is not null then
??????? v_dyn_type:=i_type||'('||i_length||','||i_pre||')';
????? elsif i_length is not null and i_pre is? null then
??????? v_dyn_type:=i_type||'('||i_length||')';
????? elsif i_length is? null and i_pre is? null then
??????? v_dyn_type:=i_type;
????? end if;
??? end if;
??? return v_dyn_type;
? exception when others then
??? return '';
? end;
?procedure dyn_crt_tab(i_tab_name in varchar2,i_crt_string out varchar2,retcd out number,errmsg out varchar2) is
??? cursor csr_tab is select h.tab_id,h.table_name,o.col_type,o.col_name,o.col_length,o.col_pre
?????????????? from column_config o,table_config h
????????????? where o.tab_id=h.tab_id
??????????????? and h.table_name=i_tab_name;
??? csr_rec csr_tab%rowtype;
??? dyn_col_type varchar2(100);
??? dyn_tab_p varchar2(4000);
? begin
??? open csr_tab;
??? dyn_tab_p:='';
??? loop
????? fetch csr_tab into csr_rec;
????? exit when(csr_tab%notfound);
????? dyn_col_type:=dyn_type(csr_rec.col_type,csr_rec.col_length,csr_rec.col_pre)||',';?? --調(diào)用拼接字段的函數(shù)
????? dyn_tab_p:=dyn_tab_p||csr_rec.col_name||' '||dyn_col_type;
??? end loop;
??? dyn_tab_p:=substr(dyn_tab_p,1,instr(dyn_tab_p,',',-1,1)-1);??? --將最后一個‘,’去掉
??? i_crt_string:=dyn_tab_p;
??? close csr_tab;
??? retcd:=0;
??? errmsg:='successful!';
? exception when others then
??? retcd:=sqlcode;
??? errmsg:=sqlerrm;
? end;
?procedure dyn_crt(retcd out number,errmsg out varchar2) is
??? cursor csr_tab is select h.tab_id,h.table_name
???????????????? from table_config h
??????????????? where h.crt_flag='0';
??? csr_rec csr_tab%rowtype;
??? dyn_string varchar2(4000);
??? v_crt_table varchar2(4000);
??? v_retcd number;
??? v_errmsg varchar2(150);
? begin
??? open csr_tab;
??? dyn_string:='';
??? loop
????? fetch csr_tab into csr_rec;
????? exit when(csr_tab%notfound);
????? dyn_crt_tab(csr_rec.table_name,v_crt_table,v_retcd,v_errmsg);??? --調(diào)用表拼接的函數(shù)
????? dyn_string:='create table '||csr_rec.table_name||'('||v_crt_table||')';
????? execute immediate dyn_string;
????? update table_config set crt_flag='1' where tab_id=csr_rec.tab_id;
????? commit;
??? end loop;
??? close csr_tab;
??? retcd:=0;
??? errmsg:='successful!';
? exception when others then
??? retcd:=sqlcode;
??? errmsg:=sqlerrm;
? end;
? procedure dyn_drop(retcd out number, errmsg out varchar2) is
?? ??? ?cursor csr_drop is
?? ??? ???? select table_name, tab_id
?? ??? ?????? from table_config
?? ??? ????? where drop_flag = '1';
?? ??? ?csr_rec csr_drop%rowtype;
?? ??? ?dyn_drop_config varchar2(100);
?? ??? ?sqlnotfound exception;
?? ??? ?pragma exception_init(sqlnotfound,-942);
?? ??? ?v_sqlcode number;
?? ??? ?v_sqlerrm varchar2(100);
?? ???? begin
?? ??? ?open csr_drop;
?? ??? ?dyn_drop_config := '';
?? ??? ?loop
?? ??? ???? fetch csr_drop
?? ??? ???????? into csr_rec;
?? ??? ???? exit when(csr_drop%notfound);
?? ??? ???? dyn_drop_config := 'drop table ' || csr_rec.table_name;
?? ??? ???? execute immediate dyn_drop_config;
?? ??? ?end loop;
?? ??? ?close csr_drop;
?? ??? ?retcd? := 0;
?? ??? ?errmsg := 'successful';
?? ???? exception
?? ??? ?when sqlnotfound then
?? ??? ?v_sqlcode:=sqlcode;
?? ??? ?v_sqlerrm:=sqlerrm;
?? ??? ???? insert into exception_monitor?? ??? ???? values
?? ??? ???????? (csr_rec.table_name,
?? ??? ????????? csr_rec.tab_id,
?? ??? ????????? upper('dyn_drop'),
?? ??? ????????? upper('sqlnotfound'),
?? ??? ????????? v_sqlcode,
?? ??? ????????? v_sqlerrm,
?? ??? ????????? sysdate);
?? ??? ???? update table_config
?? ??? ??????? set drop_flag = '0'
?? ??? ????? where tab_id = csr_rec.tab_id;
?? ??? ?when others then
?? ??? ???? retcd? := sqlcode;
?? ??? ???? errmsg := sqlerrm;
?? ???? end;
? procedure dyn_add(retcd out number, errmsg out varchar2) is
?? ??? ?cursor csr_add is
?? ??? ???? select t.table_name,
?? ??? ??????????? t.tab_id,
?? ??? ??????????? c.col_id,
?? ??? ??????????? c.col_name,
?? ??? ??????????? c.col_type,
?? ??? ??????????? c.col_length,
?? ??? ??????????? c.col_pre
?? ??? ?????? from table_config t, column_config c
?? ??? ????? where t.tab_id = c.tab_id
?? ??? ??????? and c.add_flag = '1';
?? ??? ?csr_rec csr_add%rowtype;
?? ??? ?dyn_col_type?? varchar2(200);
?? ??? ?dyn_add_string varchar2(4000);
?? ???? begin
?? ??? ?open csr_add;
?? ??? ?dyn_add_string := '';
?? ??? ?loop
?? ??? ???? fetch csr_add
?? ??? ???????? into csr_rec;
?? ??? ???? exit when(csr_add%notfound);
?? ??? ???? dyn_col_type?? := dyn_type(csr_rec.col_type,
?? ??? ??????????????????????????????? csr_rec.col_length,
?? ??? ??????????????????????????????? csr_rec.col_pre);
?? ??? ???? dyn_add_string := 'alter table ' || csr_rec.table_name ||
?? ??? ?????????????????????? ' add ' || csr_rec.col_name || ' ' ||
?? ??? ?????????????????????? dyn_col_type;
?? ??? ???? execute immediate dyn_add_string;
?? ??? ???? update column_config set add_flag='0' where tab_id=csr_rec.tab_id and col_id=csr_rec.col_id;
?? ??? ?end loop;
?? ??? ?close csr_add;
?? ??? ?retcd? := 0;
?? ??? ?errmsg := 'successful!';
?? ???? exception
?? ??? ?when others then
?? ??? ???? retcd? := sqlcode;
?? ??? ???? errmsg := sqlerrm;
?? ???? end;
? procedure dyn_del(retcd out number, errmsg out varchar2) is
?? ??? ?cursor csr_del is
?? ??? ???? select t.table_name, c.col_name ,t.tab_id , c.col_id
?? ??? ?????? from table_config t, column_config c
?? ??? ????? where t.tab_id = c.tab_id
?? ??? ??????? and c.del_flag = '1';
?? ??? ?dyn_del_string varchar2(4000);
?? ??? ?csr_rec csr_del%rowtype;
?? ???? begin
?? ??? ?open csr_del;
?? ??? ?dyn_del_string := '';
?? ??? ?loop
?? ??? ???? fetch csr_del
?? ??? ???????? into csr_rec;
?? ??? ???? exit when(csr_del%notfound);
?? ??? ???? dyn_del_string := 'alter table ' || csr_rec.table_name ||
?? ??? ?????????????????????? ' drop column ' || csr_rec.col_name;
?? ??? ???? execute immediate dyn_del_string;
?? ??? ???? update column_config set del_flag='0' where tab_id=csr_rec.tab_id and col_id=csr_rec.col_id;
?? ??? ?end loop;
?? ??? ?close csr_del;
?? ??? ?retcd? := 0;
?? ??? ?errmsg := 'successful!';
?? ???? exception
?? ??? ?when others then
?? ??? ???? retcd? := sqlcode;
?? ??? ???? errmsg := sqlerrm;
?? ???? end;
end dyn_pkg;
?? ??? ?????? from table_config t, column_config c
?? ??? ????? where t.tab_id = c.tab_id
?? ??? ??????? and c.add_flag = '1';
?? ??? ?csr_rec csr_add%rowtype;
?? ??? ?dyn_col_type?? varchar2(200);
?? ??? ?dyn_add_string varchar2(4000);
?? ???? begin
?? ??? ?open csr_add;
?? ??? ?dyn_add_string := '';
?? ??? ?loop
?? ??? ???? fetch csr_add
?? ??? ???????? into csr_rec;
?? ??? ???? exit when(csr_add%notfound);
?? ??? ???? dyn_col_type?? := dyn_type(csr_rec.col_type,
?? ??? ??????????????????????????????? csr_rec.col_length,
?? ??? ??????????????????????????????? csr_rec.col_pre);
?? ??? ???? dyn_add_string := 'alter table ' || csr_rec.table_name ||
?? ??? ?????????????????????? ' add ' || csr_rec.col_name || ' ' ||
?? ??? ?????????????????????? dyn_col_type;
?? ??? ???? execute immediate dyn_add_string;
?? ??? ???? update column_config set add_flag='0' where tab_id=csr_rec.tab_id and col_id=csr_rec.col_id;
?? ??? ?end loop;
?? ??? ?close csr_add;
?? ??? ?retcd? := 0;
?? ??? ?errmsg := 'successful!';
?? ???? exception
?? ??? ?when others then
?? ??? ???? retcd? := sqlcode;
?? ??? ???? errmsg := sqlerrm;
?? ???? end;
??? procedure dyn_del(retcd out number, errmsg out varchar2) is
?? ??? ?cursor csr_del is
?? ??? ???? select t.table_name, c.col_name ,t.tab_id , c.col_id
?? ??? ?????? from table_config t, column_config c
?? ??? ????? where t.tab_id = c.tab_id
?? ??? ??????? and c.del_flag = '1';
?? ??? ?dyn_del_string varchar2(4000);
?? ??? ?csr_rec csr_del%rowtype;
?? ???? begin
?? ??? ?open csr_del;
?? ??? ?dyn_del_string := '';
?? ??? ?loop
?? ??? ???? fetch csr_del
?? ??? ???????? into csr_rec;
?? ??? ???? exit when(csr_del%notfound);
?? ??? ???? dyn_del_string := 'alter table ' || csr_rec.table_name ||
?? ??? ?????????????????????? ' drop column ' || csr_rec.col_name;
?? ??? ???? execute immediate dyn_del_string;
?? ??? ???? update column_config set del_flag='0' where tab_id=csr_rec.tab_id and col_id=csr_rec.col_id;
?? ??? ?end loop;
?? ??? ?close csr_del;
?? ??? ?retcd? := 0;
?? ??? ?errmsg := 'successful!';
?? ???? exception
?? ??? ?when others then
?? ??? ???? retcd? := sqlcode;
?? ??? ???? errmsg := sqlerrm;
?? ???? end;
end dyn_pkg;
###########################################################################################
12.2 動態(tài)PLSQL語句
(1) 動態(tài)單行select語句
A 錄入訂單表和訂單明細(xì)表的初始化數(shù)據(jù)
insert into orders_for_region1 values(1,sysdate,null,null);
insert into orders_items_for_region1 values(1,'A001',20,13);
insert into orders_items_for_region1 values(1,'A001',23,10);
insert into orders_items_for_region1 values(1,'A001',11,5);
commit;
?
B 創(chuàng)建SP,更新訂單表的值
create or replace procedure update_dyn_table(i_region_name in varchar2,i_order_id in number,retcd out number,errmsg out varchar2) authid current_user is
? dyn_upd_string varchar2(2000);
? dyn_query_string varchar2(1000);
? dyn_tab_name1 varchar2(30);
? dyn_tab_name2 varchar2(30);
? v_total_price number;
? v_total_quantity number;
begin
? dyn_tab_name1:='ORDERS_FOR_'||replace(i_region_name,' ','');
? dyn_tab_name2:='ORDERS_ITEMS_FOR_'||replace(i_region_name,' ','');
? dyn_query_string:='select sum(quantity),sum(quantity*unit_pirce) from '||dyn_tab_name2||' where order_id=:input_order_id';?? --:input_order_id表示綁定變量
? execute immediate dyn_query_string into v_total_quantity,v_total_price using i_order_id;
? dyn_upd_string:='update '||dyn_tab_name1||' set total_qty=:v_total_qty,total_price=:v_total_price where order_id=:input_order_id';
? execute immediate dyn_upd_string using v_total_quantity,v_total_price,i_order_id;
? retcd:=0;
? errmsg:='successful!';
exception when others then
? retcd:=sqlcode;
? errmsg:=sqlerrm;
end;
測試:
declare
? v_sqlcode number;
? v_sqlerrm varchar2(200);
begin
? update_dyn_table('region1',1,v_sqlcode,v_sqlerrm);
? dbms_output.put_line(v_sqlerrm);
end;
查詢:
select * from orders_for_region1;
注意:
?A 動態(tài)PLSQL語句中,select語句需要用into來接收參數(shù)值
?B 綁定變量在動態(tài)PLSQL中,用冒號前置的方式來定義,不需要聲明
?C 執(zhí)行的時(shí)候,綁定變量需要用using關(guān)鍵字來賦值
(2) 動態(tài)多行的select語句
?A 初始化數(shù)據(jù)
insert into orders_for_region1 values(2,sysdate,null,null);
insert into orders_items_for_region1 values(2,'A001',30,13);
insert into orders_items_for_region1 values(2,'A001',33,10);
insert into orders_items_for_region1 values(2,'A001',11,7);
insert into orders_for_region1 values(3,sysdate,null,null);
insert into orders_items_for_region1 values(3,'A001',50,13);
insert into orders_items_for_region1 values(3,'A001',63,7);
insert into orders_items_for_region1 values(3,'A001',21,5);
insert into orders_for_region1 values(4,sysdate,null,null);
insert into orders_items_for_region1 values(4,'A001',30,13);
insert into orders_items_for_region1 values(4,'A001',35,10);
insert into orders_items_for_region1 values(4,'A001',12,5);
commit;
?B 編寫SP實(shí)現(xiàn)多行的更新
create or replace procedure update_dyn_all_table(i_region_name in varchar2,retcd out number,errmsg out varchar2) authid current_user is
? dyn_upd_string varchar2(1000);
? dyn_query_string varchar2(1000);
? dyn_tab_name varchar2(30);
? v_total_price number;
? v_total_quantity number;
? type csr_dyn is ref cursor;
? csr_dyn1 csr_dyn;
? v_order_id number;
begin
? dyn_tab_name:='ORDERS_ITEMS_FOR_'||replace(i_region_name,' ','');
? dyn_query_string:='select distinct order_id from '||dyn_tab_name;
? open csr_dyn1 for dyn_query_string;?? --動態(tài)的方式打開游標(biāo)
? loop
??? fetch csr_dyn1 into v_order_id;
??? exit when(csr_dyn1%notfound);
??? update_dyn_table(i_region_name,v_order_id,retcd,errmsg);
??? if retcd <> 0 then
????? exit;
??? end if;
? end loop;
? close csr_dyn1;
? retcd:=0;
? errmsg:='successful!';
exception when others then
? retcd:=sqlcode;
? errmsg:=sqlerrm;
end;
測試:
declare
? v_sqlcode number;
? v_sqlerrm varchar2(200);
begin
? update_dyn_all_table('region1',v_sqlcode,v_sqlerrm);
? dbms_output.put_line(v_sqlerrm);
end;
驗(yàn)證:
select * from orders_for_region1;
目前為止只是處理了一個銷售區(qū)域,總共有四個銷售區(qū)域,怎樣處理四個銷售區(qū)域用一個SP
A 初始化
insert into orders_for_region1 values(1,sysdate,null,null);
insert into orders_items_for_region1 values(1,'A001',30,13);
insert into orders_items_for_region1 values(1,'A001',33,10);
insert into orders_items_for_region1 values(1,'A001',11,7);
insert into orders_for_region1 values(2,sysdate,null,null);
insert into orders_items_for_region1 values(2,'A001',30,13);
insert into orders_items_for_region1 values(2,'A001',33,10);
insert into orders_items_for_region1 values(2,'A001',11,7);
insert into orders_for_region1 values(3,sysdate,null,null);
insert into orders_items_for_region1 values(3,'A001',50,13);
insert into orders_items_for_region1 values(3,'A001',63,7);
insert into orders_items_for_region1 values(3,'A001',21,5);
insert into orders_for_region1 values(4,sysdate,null,null);
insert into orders_items_for_region1 values(4,'A001',30,13);
insert into orders_items_for_region1 values(4,'A001',35,10);
insert into orders_items_for_region1 values(4,'A001',12,5);
commit;
insert into orders_for_region2 values(1,sysdate,null,null);
insert into orders_items_for_region2 values(1,'A001',30,13);
insert into orders_items_for_region2 values(1,'A001',33,10);
insert into orders_items_for_region2 values(1,'A001',11,7);
insert into orders_for_region2 values(2,sysdate,null,null);
insert into orders_items_for_region2 values(2,'A001',30,13);
insert into orders_items_for_region2 values(2,'A001',33,10);
insert into orders_items_for_region2 values(2,'A001',11,7);
insert into orders_for_region2 values(3,sysdate,null,null);
insert into orders_items_for_region2 values(3,'A001',50,13);
insert into orders_items_for_region2 values(3,'A001',63,7);
insert into orders_items_for_region2 values(3,'A001',21,5);
insert into orders_for_region2 values(4,sysdate,null,null);
insert into orders_items_for_region2 values(4,'A001',30,13);
insert into orders_items_for_region2 values(4,'A001',35,10);
insert into orders_items_for_region2 values(4,'A001',12,5);
commit;
insert into orders_for_region3 values(1,sysdate,null,null);
insert into orders_items_for_region3 values(1,'A001',30,13);
insert into orders_items_for_region3 values(1,'A001',33,10);
insert into orders_items_for_region3 values(1,'A001',11,7);
insert into orders_for_region3 values(2,sysdate,null,null);
insert into orders_items_for_region3 values(2,'A001',30,13);
insert into orders_items_for_region3 values(2,'A001',33,10);
insert into orders_items_for_region3 values(2,'A001',11,7);
insert into orders_for_region3 values(3,sysdate,null,null);
insert into orders_items_for_region3 values(3,'A001',50,13);
insert into orders_items_for_region3 values(3,'A001',63,7);
insert into orders_items_for_region3 values(3,'A001',21,5);
insert into orders_for_region3 values(4,sysdate,null,null);
insert into orders_items_for_region3 values(4,'A001',30,13);
insert into orders_items_for_region3 values(4,'A001',35,10);
insert into orders_items_for_region3 values(4,'A001',12,5);
commit;
insert into orders_for_region4 values(1,sysdate,null,null);
insert into orders_items_for_region4 values(1,'A001',30,13);
insert into orders_items_for_region4 values(1,'A001',33,10);
insert into orders_items_for_region4 values(1,'A001',11,7);
insert into orders_for_region4 values(2,sysdate,null,null);
insert into orders_items_for_region4 values(2,'A001',30,13);
insert into orders_items_for_region4 values(2,'A001',33,10);
insert into orders_items_for_region4 values(2,'A001',11,7);
insert into orders_for_region4 values(3,sysdate,null,null);
insert into orders_items_for_region4 values(3,'A001',50,13);
insert into orders_items_for_region4 values(3,'A001',63,7);
insert into orders_items_for_region4 values(3,'A001',21,5);
insert into orders_for_region4 values(4,sysdate,null,null);
insert into orders_items_for_region4 values(4,'A001',30,13);
insert into orders_items_for_region4 values(4,'A001',35,10);
insert into orders_items_for_region4 values(4,'A001',12,5);
commit;
B 創(chuàng)建SP實(shí)現(xiàn)多個區(qū)域的銷售數(shù)據(jù)的計(jì)算。region_tab
create or replace procedure update_dyn_global(retcd out number,errmsg out varchar2) authid current_user is
? cursor csr_region is select region_name from region_tab;
begin
? for idx in csr_region loop
???? update_dyn_all_table(idx.region_name,retcd,errmsg);
???? if retcd <> 0 then
?????? exit;
???? end if;
? end loop;
? retcd:=0;
? errmsg:='successful!';
exception when others then
? retcd:=sqlcode;
? errmsg:=sqlerrm;
end;
測試:
declare
? v_sqlcode number;
? v_sqlerrm varchar2(200);
begin
? update_dyn_global(v_sqlcode,v_sqlerrm);
? dbms_output.put_line(v_sqlerrm);
end;
驗(yàn)證:
select * from orders_for_region1;
select * from orders_for_region2;
select * from orders_for_region3;
select * from orders_for_region4;
在存儲過程中使用動態(tài)PLSQL調(diào)用存儲過程,封裝在SP中
create or replace procedure update_dyn_global2(retcd out number,errmsg out varchar2) authid current_user is
begin
? execute immediate 'begin update_dyn_global(:1,:2);end;' using out retcd,out errmsg;
? --動態(tài)PLSQL語句中調(diào)用存儲過程
? retcd:=0;
? errmsg:='successful!';
exception when others then
? retcd:=sqlcode;
? errmsg:=sqlerrm;
end;
練習(xí):
將上面的三個SP封裝在一個package中,全部做成公有對象
SCOTT用戶下
?A 創(chuàng)建一個表emp_salary_grd : 三個列:員工號 empno 、工資等級 sal_level、年薪 sal_anl? (sal*12+comm)
?B 創(chuàng)建一個SP,用動態(tài)PLSQL的方式將這個表的數(shù)據(jù)裝載
?C 用動態(tài)PSLQL方式調(diào)用上面創(chuàng)建的SP
設(shè)計(jì)一個SP,將PLSQL用戶下所有的觸發(fā)器禁用掉,用動態(tài)SQL方式
###########################################################################################
轉(zhuǎn)載于:https://blog.51cto.com/fengsonglin/1615262
總結(jié)
以上是生活随笔為你收集整理的plsql动态的sql的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 快速排序C实现(阿里巴巴 2012年全国
- 下一篇: 玩转智能路由器-WRTnode开发板[接