pl/sql小结

  1 /*
  2  * PL/SQL - 
  3  *  是Oracle数据库特定的数据库编程语法.
  4  * 所有的数据库存储过程/函数/触发器开发,都是数据库特定的语法.
  5  * 第一代: 机器语言
  6  * 第二代: 面向过程的语言
  7  * 第三代: 面向对象的语言
  8  * 第四代语言: 面向结果的语言. 语言编写完毕后,只要求结果正确.
  9  * 
 10  * PL/SQL是在Oracle数据库管理系统中开发的语法.
 11  * 是将有逻辑的SQL语句,固化在Oracle的DBMS中,可以重复调用的方式.
 12  * 如: to_date()  to_char()  replace()  substring()  max()  min()  avg()  upper()
 13  */
 14 
 15 /*
 16  * Oracle数据库为了提高执行效率.默认是关闭手工输出流的.
 17  * 开启手工输出:
 18  * set serveroutput on;
 19  * 关闭手工输出:
 20  * set serveroutput off;
 21  */
 22 -- hello world
 23 /*
 24  * 执行存储过程/函数的方式
 25  * 1. execute - 执行
 26  * 2. call - 调用, call命令可能有缓存. 结果输出不是每次都能看到的.
 27  *  必须刷新缓存或缓存空间不足的时候,才能看到结果
 28  * 3. 匿名代码块, 只能执行唯一一次的存储过程/函数.
 29  */
 30 execute dbms_output.put_line('hello world');
 31 call dbms_output.put_line('hello world with call');
 32 begin
 33     dbms_output.put_line('hello world with block');
 34 end;
 35 /
 36 
 37 /*
 38  * 匿名代码块结构及常用语法
 39  * declare 
 40  *     定义变量
 41  *     变量定义语法
 42  *     变量名 变量类型;
 43  *     变量定义并初始化语法  , := 赋值, = 比较等值  , > < >= <= != <>
 44  *     变量名 变量类型 := 变量数据;
 45  * begin
 46  *     定义代码逻辑
 47  *     变量赋值 -   变量名 := 值;
 48  *     执行语法 -   语法;
 49  * end;
 50  */
 51 -- 循环 loop
 52 -- 1. loop循环, 天生就是无限循环
 53 declare
 54     v_i number := 1;
 55 begin
 56     loop -- 开始循环
 57         dbms_output.put_line(v_i);
 58         v_i := v_i + 1;
 59         exit when v_i > 10; -- 当条件满足的时候,执行exit命令. 
 60     end loop; -- 结束循环
 61 end ;
 62 /
 63 
 64 -- while loop循环
 65 declare
 66     v_i number := 1;
 67 begin
 68     while v_i < 11 loop -- 当条件满足的时候,循环
 69         dbms_output.put_line(v_i);
 70         v_i := v_i + 1;
 71     end loop; -- 结束循环
 72 end ;
 73 /
 74 
 75 -- for循环
 76 begin
 77     for v_i in reverse 1..10 loop -- 当变量v_i在范围1到10之间的时候,循环. for循环数据自增1
 78         dbms_output.put_line(v_i);
 79     end loop;
 80 end ;
 81 /
 82 
 83 /*
 84  * PL/SQL中的CRUD
 85  */
 86 -- insert
 87 declare
 88     v_id number := 2;
 89     str varchar(32) := 'bbb';
 90     age number := 30;
 91 begin
 92     -- insert into tb_temp(id, v_str, v_age) values(1, 'aaa', 20);
 93     insert into tb_temp(id, v_str, v_age) values(v_id, str, age);
 94     commit;
 95 end ;
 96 /
 97 
 98 -- update
 99 begin
100     update tb_temp
101     set v_str = 'ccc', v_age = 40
102     where id = 1;
103     commit;
104 end ;
105 /
106 
107 -- delete
108 begin
109     delete from tb_temp where id = 2;
110     commit;
111 end ;
112 /
113 
114 -- select, 要求将查询结果保存在变量中. 因为PL/SQL没有自动输出. 查询结果无保存单元.
115 -- 限制为只能查询一条数据
116 declare
117     v_id number;
118     str varchar2(32);
119     age number;
120 begin
121     select id, v_str, v_age into v_id, str, age from tb_temp;
122     dbms_output.put_line('id = ' || v_id || ', str = ' || str || ', age = ' || age);
123 end ;
124 /
125 
126 -- cursor 游标, 用于处理查询的PL/SQL语法结构.
127 -- 类似java中的ResultSet. 在Oracle中是用来定位查询语句结果内存的一个引用.
128 /*
129  * 游标定义方式
130  *  cursor 游标命名 is 查询语法;
131  * 游标属性
132  *  游标命名%found -- 最近一次fetch是否有结果, 无结果返回false,有结果返回true
133  *  游标命名%notfound -- 最近一次fetch是否有结果, 有结果返回false,无结果返回true
134  *  游标命名%isopen -- 是否开启. 已开启返回true
135  */
136 declare
137     cursor c_temp is select * from tb_temp;
138 begin
139     for v_temp in c_temp loop -- 变量v_temp的类型就是游标中的一行数据的类型.
140         dbms_output.put_line(v_temp.id || ' , ' || v_temp.v_str || ' , ' || v_temp.v_age);
141     end loop;
142 end ;
143 /
144 
145 declare
146     cursor c_temp is select * from tb_temp;
147     v_temp tb_temp%rowtype; -- 变量v_temp和表格tb_temp中的一行数据的类型一样
148 begin
149     -- 开启游标
150     open c_temp;
151     
152     -- 循环游标
153     loop
154         fetch c_temp into v_temp; -- 迭代游标中的一行数据到变量v_temp中.
155         exit when c_temp%notfound; -- %notfound是游标的属性,代表最近一次fetch是否有新的数据.
156         dbms_output.put_line(v_temp.id || ' , ' || v_temp.v_str || ' , ' || v_temp.v_age);
157     end loop;
158     
159     -- 关闭游标
160     close c_temp;
161 end ;
162 /
163 
164 declare
165     cursor c_temp is select * from tb_temp;
166     v_temp tb_temp%rowtype; -- 变量v_temp和表格tb_temp中的一行数据的类型一样
167 begin
168     -- 开启游标
169     open c_temp;
170         
171     fetch c_temp into v_temp; -- 迭代游标中的一行数据到变量v_temp中.
172     
173     -- 循环游标
174     while c_temp%found loop
175         dbms_output.put_line(v_temp.id || ' , ' || v_temp.v_str || ' , ' || v_temp.v_age);
176         fetch c_temp into v_temp; -- 迭代游标中的一行数据到变量v_temp中.
177     end loop;
178     
179     -- 关闭游标
180     close c_temp;
181 end ;
182 /
183 
184 /*
185  * 判断语法
186  * if xxx then
187  * end if;
188  * if xxx then
189  * end if;
190  * if xxx then
191  * elsif xxx then
192  * else
193  * end if;
194  */
195 declare
196     v_i number := 0;
197 begin
198     -- v_i > 0 输出正数, <0 输出负数, == 0输出零
199     if v_i > 0 then
200         dbms_output.put_line('正数');
201     elsif v_i < 0 then
202         dbms_output.put_line('负数');
203     else
204         dbms_output.put_line('零');
205     end if;
206 end ;
207 /
208 
209 /*
210  * 存储过程 - procedure
211  * 创建存储过程,语法和创建表类似
212  * 存储定义逻辑和匿名代码块类似
213  * 没有返回值.
214  */
215 -- 定义
216 create procedure print(v_str varchar2) -- ()中定义参数, 参数只定义类型,不定义长度.
217 as -- 代替declare, as或is关键字不可少.
218 begin
219     dbms_output.put_line(v_str);
220 end;
221 /
222 
223 -- 定义+重置
224 create or replace procedure print(v_str varchar2) -- ()中定义参数, 参数只定义类型,不定义长度.
225 as -- 代替declare, as或is关键字不可少.
226 begin
227     dbms_output.put_line(v_str);
228 end;
229 /
230 
231 /*
232  * 查看存储过程定义的编译错误: show errors;
233  * 
234  * 存储过程中的参数
235  * 在存储过程中,参数除有类型外,还有传递方向.
236  * 方向分为三种
237  * 1. 输入参数 - 默认参数方向, 代表参数数据只能读,不能写. 定义语法 : 参数名 [in] 参数类型
238  * 2. 输出参数 - 可以作为返回值的参数. 可写. 特性为, 第一次在存储过程中使用参数,格式化. 在使用的时候有要求
239  *   要求是,传入的输出参数必须是一个可复制的变量.不能是常量. 定义语法: 参数名 out 参数类型
240  * 3. 输入输出参数 - 可读可写. 不会格式化.语法: 参数名 in out 参数类型. 最不常用的参数方向.
241  *   数据库是一个弱类型的数据存储管理工具. 容易造成参数转化错误
242  */
243 
244 create or replace procedure helloWorld(v_name in out varchar2)
245 as
246 begin
247     v_name := 'hello ' || v_name;
248     print(v_name);
249 end ;
250 /
251 
252 create or replace procedure helloWorld(v_name out varchar2)
253 as
254 begin
255     v_name := 'hello ' || v_name;
256     print(v_name);
257 end ;
258 /
259 
260 declare
261     v_name date := sysdate;
262 begin
263     print('调用helloWorld之前: ' || v_name);
264     helloWorld(v_name);
265     print('调用helloWorld之后: ' || v_name);
266 end ;
267 /
268 
269 declare
270     v_name varchar2(32) := 'world';
271 begin
272     print('调用helloWorld之前: ' || v_name);
273     helloWorld(v_name);
274     print('调用helloWorld之后: ' || v_name);
275 end ;
276 /
277 
278 create or replace procedure print(v_str in varchar2) -- ()中定义参数, 参数只定义类型,不定义长度.
279 as -- 代替declare, as或is关键字不可少.
280 begin
281     -- v_str := 'hello ' || v_str;
282     dbms_output.put_line(v_str);
283 end;
284 /
285 
286 
287 /*
288  * 函数 function
289  * 和存储过程之间的区别有:
290  * 1. 关键字不同
291  * 2. 有返回值
292  * 3. 调用函数和调用存储过程方式不同.
293  *    调用函数可以在SQL语法的DQL语句中使用.存储过程不能在DQL语句中使用.
294  *    函数调用的时候,可以使用变量接收函数的返回值. 存储过程不能.
295  */
296 create or replace function f_test(v_str varchar2)
297 return varchar2
298 as
299 begin
300     return 'hello ' || v_str;
301 end ;
302 /
303 
304 declare
305     v_str varchar2(32);
306 begin
307     -- v_str := f_test('zhangsan');
308     -- print(v_str);
309     print(f_test('lisi'));
310 end ;
311 /
312 
313 /*
314  * 触发器, trigger. 不推荐使用. 影响数据库管理系统的执行效率
315  * 触发器都是为表格提供的. 类似java中的监听器. 当某条件满足的时候,自动执行.
316  * 对表格的CUD操作.
317  * 通常触发器用于表中数据的保护.
318  * 如: ERP系统中的用户数据保护. 用户为系统持有者. 如: 京东.京东用户是京东的员工. 
319  */
320     
321 create or replace trigger ti_test1 before update on tb_temp
322 for each row -- 行级触发器. 当表中每行数据有CUD操作时触发.
323 when (old.id < 100) -- 当更新数据的id小于100的时候,触发器执行.
324 begin
325     dbms_output.put_line('before update触发器执行');
326     
327     -- :old : 旧的数据.在更新和删除的时候存在.
328     dbms_output.put_line(:old.id || ' , ' || :old.v_str || ' , ' || :old.v_age);
329     
330     -- :new : 新的数据.在新增和更新的时候存在.
331     dbms_output.put_line(:new.id || ' , ' || :new.v_str || ' , ' || :new.v_age);
332 end ;
333 /
334 
335 create or replace trigger ti_test2 after update on tb_temp
336 begin
337     dbms_output.put_line('after update触发器执行');
338 end ;
339 /
340 
341 
342 -- 网络查询JDBC中的CallableStatement  call xxxx();
343 
344 
345 
346 
347 
348 
349 
350 
351 
352 
353 create table tb_temp(
354     id number(8) primary key,
355     v_str varchar2(32),
356     v_age number(3)
357 );
原文地址:https://www.cnblogs.com/zzuzhenlei/p/7569698.html