1 --动态SQL
2 create or replace function get_table_count
3 (table_name in varchar2) return pls_integer
4 is
5 sql_query varchar2(32767):='select count(*) from '||table_name;
6 l_return pls_integer;
7 begin
8 execute immediate sql_query into l_return;
9 return l_return;
10 end;
11 begin
12 dbms_output.put_line('表的行数是'||get_table_count('emp'));
13 end;
14 create table ddl_demo(id number,amt number);
15 select * from ddl_demo;
16 --执行动态PL/SQL语句
17 declare
18 plsql_block varchar2(500);
19 begin
20 plsql_block:='DECLARE I INTEGER:=10;
21 BEGIN
22 EXECUTE IMMEDIATE ''truncate table ddl_demo'';
23 for j in 1..i loop
24 insert into ddl_demo values(j,j*100);
25 end loop;
26 end;';
27 execute immediate plsql_block;
28 commit;
29 end;
30 --使用绑定变量
31 /* 重复使用相同的执行计划,避免了重复进行硬解析占用CPU资源
32 绑定变量实际上就是用于替代SQL语句中常量的替代变量*/
33
34 declare
35 v_empno number:=7997;
36 v_ename emp.ename%type:='吕四娘';
37 v_job emp.job%type:='剑客';
38 v_deptno emp.deptno%type :=20;
39 v_tbl_name varchar2(50) :='emp';
40 v_sql_str varchar2(1000);
41 begin
42 v_sql_str :='insert into '||v_tbl_name ||
43 '(empno,ename,job,deptno) values(:1,:2,:3,:4)';
44 execute immediate v_sql_str
45 using v_empno, v_ename,v_job,v_deptno;
46 end;
47 --使用returning into子句获取返回值
48 declare
49 v_empno number(4):=7369;
50 v_percent number(4,2):=0.12;
51 v_salary number(10,2);
52 sql_stmt varchar2(500);
53 begin
54 sql_stmt:='update emp set sal=sal*(1+:percent) '
55 ||' where empno=:empno returning sal
56 into :salary';
57 execute immediate sql_stmt using
58 v_percent,v_empno
59 returning into v_salary;
60 dbms_output.put_line('调整后的工资为:'||v_salary);
61 end;
62 --使用into子句
63 declare
64 sql_stmt varchar2(100);
65 v_deptno number(4):=20;
66 v_empno number(4):=7369;
67 v_dname varchar2(20);
68 v_loc varchar2(20);
69 emp_row emp%rowtype;
70 begin
71 sql_stmt:='select dname,loc from dept where deptno
72 =:deptno';
73 execute immediate sql_stmt into v_dname,v_loc using
74 v_deptno;
75 sql_stmt:='select * from emp where empno=:empno';
76 execute immediate sql_stmt into emp_row using v_empno;
77 dbms_output.put_line('查询的部门名称为:'||v_dname);
78 dbms_output.put_line('查询的员工编号为:'||emp_row.ename);
79 end;
80 create sequence deptno_seq
81 start with 1 increment by 1
82 create sequence deptno_seq
83 start with 1 increment by 1
84 --使用in out模式的参数
85 create or replace procedure create_dept(
86 deptno in out number, dname in varchar2, loc in varchar2
87 ) as
88 begin
89 if deptno is null then
90 select deptno_seq.nextval into deptno from dual;
91 end if;
92 insert into dept values(deptno,dname,loc);
93 end;
94 declare
95 plsql_block varchar2(500);
96 v_deptno number(2);
97 v_dname varchar2(14):='网络部';
98 v_loc varchar2(13) :='也门';
99 begin
100 plsql_block :='begin create_dept(:a,:b,:c);end;';
101 execute immediate plsql_block
102 using in out v_deptno,v_dname,v_loc;
103 dbms_output.put_line('新建部门的编号为:'||v_deptno);
104 end;
105
106 openfor 语句 ,fetch语句
107 --使用 fetch语句提取游标数据
108 declare
109 type empcurtyp is ref cursor; --定义一个弱游标类型
110 v_emp_cursor empcurtyp; --定义一个游标变量
111 emp_record emp%rowtype; --定义保存游标数据的记录类型
112 v_stmt_str varchar2(200);
113 v_e_job emp.job%type:='CLERK';
114 begin
115 --定义动态select语句和绑定占位符
116 v_stmt_str :='select * from scott.emp where job=:j';
117 --使用动态sql语句打开游标变量,用using子句指定变量
118 open v_emp_cursor for v_stmt_str using v_e_job;
119 loop
120 fetch v_emp_cursor into emp_record;
121 exit when v_emp_cursor%notfound;
122 dbms_output.put_line('员工工号:'||emp_record.empno||' '||
123 '员工姓名'||emp_record.ename);
124 end loop;
125 close v_emp_cursor;
126 end;
127
128 批量bulk语句
129 --使用BULK collect into子句处理多行查询
130 declare
131 type ename_table_type is table of varchar2(20)
132 index by binary_integer;
133 type empno_table_type is table of number(24)
134 index by binary_integer;
135 ename_tab ename_table_type; --定义保存多行返回值的索引表
136 empno_tab empno_table_type;
137 v_deptno number(4) :=20; --定义部门编号绑定变量
138 sql_stmt varchar2(500);
139 begin
140 sql_stmt:='select empno,ename from emp
141 '||' where deptno =:1';
142 execute immediate sql_stmt
143 bulk collect into empno_tab,ename_tab
144 using v_deptno;
145 for i in 1..ename_tab.count loop
146 dbms_output.put_line('员工编号'||empno_tab(i)
147 ||'员工名称:'||ename_tab(i));
148 end loop;
149 end;
150
151
152 --使用return bulk collect into子句获取多行更新列
153 declare
154 type ename_table_type is table of varchar2(25) index by
155 binary_integer;
156 type sal_table_type is table of number(10,2) index by
157 binary_integer;
158 ename_tab ename_table_type;
159 sal_tab sal_table_type;
160 v_deptno number(4) :=20;
161 v_percent number(4,2):=0.12;
162 sql_stmt varchar2(500);
163 begin
164 sql_stmt:='update emp set sal=sal*(1+:percent)'
165 ||' where deptno=:deptno returning ename,sal
166 into :ename,:salary';
167 execute immediate sql_stmt using v_percent,v_deptno
168 returning bulk collect into ename_tab,sal_tab;
169
170 for i in 1..ename_tab.count loop
171 dbms_output.put_line('员工'||ename_tab(i)
172 ||'调新后的薪资:'||sal_tab(i) );
173 end loop;
174 end;
175
176 批量fetch语句
177 --使用批量fetch语句获取多行查询结果
178 declare
179 type ename_table_type is table of varchar2(20) index by binary_integer;
180 type empno_table_type is table of number(24) index by binary_integer;
181 type emp_cur_type is ref cursor; --定义游标变量
182 ename_tab ename_table_type;
183 empno_tab empno_table_type;
184 emp_cur emp_cur_type;
185 v_deptno number(4) :=20;
186 begin
187 OPEN emp_cur for
188 'select empno, ename from emp'||
189 'where deptno=:1' using v_deptno;
190 fetch emp_cur bulk collect into empno_tab,ename_tab;
191 close emp_cur;
192 for i in 1..ename_tab.COUNT loop
193 dbms_output.put_line('员工编号'||empno_tab(i)
194 ||'员工名称'||ename_tab(i));
195 end loop;
196 end;
197
198 批量forall语句
199 --使用FORALL语句更新多个员工薪资
200 declare
201 type ename_table_type is table of varchar2(25)
202 index by binary_integer;
203 type sal_table_type is table of number(10,2)
204 index by binary_integer;
205 type empno_table_type is table of number(4);
206
207 ename_tab ename_table_type;
208 sal_tab sal_table_type;
209 empno_tab empno_table_type;
210 v_percent number(4,2) :=0.12;
211 sql_stmt varchar2(500);
212 begin
213 empno_tab:=empno_table_type(7369,7499,7521,7566);
214 sql_stmt:='update emp set sal=sal*(1+:percent) '
215 ||' where empno=:empno returning ename,sal
216 into :ename,:salary';
217 forall i in 1..empno_tab.count --使用Forall语句批量输入参数
218 execute immediate sql_stmt using v_percent,empno_tab(i)
219 returning bulk collect into ename_tab,sal_tab;
220 for i in 1..ename_tab.count loop
221 dbms_output.put_line('员工'||ename_tab(i)||'调薪后的薪资:'
222 ||sal_tab(i));
223 end loop;
224 end;
225
226
227 using语句绑定
228 1绑定比链接具有更快的性能
229 2绑定变量更容易编写和维护
230 3避免隐式类型转换
231 4 避免代码注入,绑定变量避免sql注入是攻击
232 --执行PLSQL动态语句时重复绑定占位符处理
233 declare
234 col_in varchar2(10):='sal';
235 start_in date;
236 end_in date;
237 val_in number;
238 dml_str varchar2(32767):='begin
239 update emp set ' || col_in||'=:val
240 where hiredate between:lodate and
241 :hidate and :val is not null;
242 end;';
243 begin
244 execute immediate dml_str
245 using val_in,start_in,end_in;
246 end;
247
248 --在执行动态SQL时使用异常处理机制
249 create or replace procedure ddl_execution(ddl_string in varchar2)
250 authid current_user is --使用调用者权限
251 begin
252 execute immediate ddl_string;
253 exception
254 when others
255 then
256 dbms_output.put_line(
257 '动态SQL语句错误:' || dbms_utility.format_error_stack);
258 dbms_output.put_line(
259 ' 执行的SQL语句为:"'||ddl_string ||'"');
260 raise;
261 end ddl_execution;
262
263 --命令行
264 set serveroutput on;
265 exec ddl_execution('alter table emp_test add emp_sal number null');
266
267 update emp set sal=1.21 where empno=7369;
268
269
270 select xid as "事务id",XIDUSN as "UNDO",XIDSLOT AS "事务槽",
271 xidsqn as "seq",status as "事务状态" from v$transaction;
272
273 --设置事务属性
274 set transaction read only;--只读事务,此事务中不能进行任何i增删改查
275 set transaction read write --建立读写事务
276 set transaction isolation level serializable;--设置序列隔离级别
277 set transaction isolation read committed; --设置读提交隔离级别
278
279 set transaction isolation level serializable;
280 update emp set sal=8500 where empno=7369;
281 --另外起一个sqlplus窗口,会话1没有提交回滚,会话2倍阻塞
282 update emp set sal=9000 where empno=7369;
283 --使用动态SQL语句实现数据处理
284 declare
285 v_sqlstr varchar2(200); --保存SQL语句的变量
286 v_id int; --保存临时字段值的变量
287 v_name varchar2(100);
288 begin
289 begin
290 v_sqlstr:='drop table temptable';
291 execute immediate v_sqlstr;
292 exception
293 when others
294 then
295 null;
296 end;
297 /* v_sqlstr :='create table temptable (id int not null primary key,
298 tmpname varchar2(100))';
299 execute immediate v_sqlstr;*/
300 v_sqlstr:='insert into temptable values(10,''临时名称1'')';
301 execute immediate v_sqlstr;
302 v_sqlstr:= 'select * from temptable where id=:tempId';
303 execute immediate v_sqlstr into v_id,v_name using &l;
304 dbms_output.put_line(v_id || ' '||v_name);
305 end;
306 select * from temptable ;