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 ;