sql, plsql 总结

 

  1 /*
  2  *====================================== basic sql ==========================================
  3  */
  4  
  5 -- Merge --
  6 merge into copy_emp as ac
  7 using employees e
  8 on (c.employee_id = employee_id)
  9 when matched then
 10     update set
 11     c.first_name = e.first_name
 12     c.last_name = e.last_name
 13     c.department_id = e.department_id
 14 when not matched then
 15     insert values(e.employee_id, e.first_name, e.last_name, e.department_id)
 16 
 17 -- alter table --
 18 alter table dep80
 19 add(job_id varchar(8))
 20 
 21 alter table dep80
 22 modify(job_id varchar(30))
 23 
 24 alter table dep80
 25 drop(job_id)
 26 
 27 alter table dep80
 28 set unused(job_id)
 29 
 30 -- reaname --
 31 rename dept to detail_dept
 32 
 33 -- truncate --
 34 truncat table detial_dept
 35 
 36 -- comment --
 37 comment on table dept IS 'department information'
 38 comment on dept.deptno IS 'department number'
 39 
 40 -- constraint , not null, unique, primary key, foreign key, check --
 41 create table employees (
 42     employee_id        NUMBER(6),
 43     job_id            VARCHAR2(10) NOT NULL,
 44     
 45     constraint emp_id_pk PRIMARY KEY(employee_id)
 46 )
 47 
 48 alter table employees
 49     add constraint emp_manager_fk FOREIGN KEY(manager_id)
 50     REFERENCES employee(employee_id)
 51 
 52 alter table employees
 53     drop constraint emp_manager_fk [cascade]
 54 
 55 alter table employees
 56     disable constraint emp_manager_fk[cascade]
 57 
 58 alter table employees
 59     enable constraint emp_manager_fk
 60 
 61 alter table employees
 62     drop (column1, column2) [cascade constraints]
 63 
 64 -- view --
 65 create or replace view emp_view as select deptno, dname, loc from dept
 66 drop view emp_view
 67 
 68 -- sequence --
 69 create sequence seq_emp
 70 increment by 1
 71 start with 0
 72 maxvalue 20000000
 73 minvalue 0
 74 nocycle
 75 nocache
 76 
 77 -- index --
 78 create index ind_emp on dept(deptno, dname)
 79 
 80 -- synonym --
 81 create public synonym dept for scott.dept
 82 -- 2种方法: 例如 object 在 hr 下, scott 想要访问 hr 下的 table department.
 83 -- 1. 在 scott 模式下, create synonym department for hr.department
 84 -- 2. 在 hr 模式下, create synonym scott.department for department , 注意这种含义是 hr 用户代替 scott
 85 -- 用户在 scott 模式下创建了别名, scott.department 这个表示是在 scott模式下, 所以在 scott 模式下就直接
 86 -- 有了这样一个别名.
 87 
 88 -- create user --
 89 create user leon_master identified by leon
 90 alter user leon_master identified by master ( 修改密码 )
 91 
 92 -- grant privilege --
 93 grant dba to leon_master
 94 grant create session, create table, create sequence to scott ( to role )
 95 grant manager(role) to leon_master
 96 grant update(deptname, location_id) on departments to scott, manager
 97 
 98 -- role --
 99 create role manager;
100 grant create session, create table, create sequence to manager;
101 
102 -- revoke --
103 revoke create session from scott
104 revoke update(deptname, location_id) on department from scott, manager
105 
106 -- database link --
107 create public database link mes20
108 connect to <被链接数据库用户名> identified by <被链接数据库密码>
109 using 'ASDF'
110 
111 /*
112 tnsnames >>>
113 ASDF, ASDF2 =
114   (DESCRIPTION =
115     (ADDRESS = (PROTOCOL = TCP)(HOST = 109.106.13.25)(PORT = 1521))
116     (ADDRESS = (PROTOCOL = TCP)(HOST = 109.106.13.22)(PORT = 1521))
117     (ADDRESS = (PROTOCOL = TCP)(HOST = 109.106.13.26)(PORT = 1521))
118     (CONNECT_DATA =
119       (SERVER = DEDICATED)
120       (SERVICE_NAME = ASDF)
121     )
122   )
123 */
124 -- relation sub query --
125 select column1, column2
126 FORM table1 outer
127 where column1 operator ( select column1 from table2 where expr1 = outer.exp2);
128 
129 select column1, column2
130 from table1 outer
131 where exists ( select column1 from table2 where expr1 = outer.exp2);
132 
133 update table1 als_1
134 set column = ( select expression from table2 als_2 where als_1.column = als_2.column);
135 
136 delete from table1 als_1
137 where column operator ( select expression from table2 als_2 where als_1.column = als_2.column);
138 
139 -- Hierarchical retrieve --
140 
141 select substr(sys_connect_by_path(ENAME,'->'), 3) EMPLOYEE from EMP
142 connect by prior EMPNO = MGR
143 start with ename = '小董'
144 
145 -- 首先这个查询有一个 connect by prior EMPNO=MGR, 这是一个连接条件, 从 start with 开始找到第一行数据,
146 -- 然后根据连接条件来进行. 向后遍历. 翻译过来就是, 先从小董开始, 然后小董的 empno 作为父层次 = manager
147 -- 向后依次遍历.
148 
149 /*
150  * =========================================== plsql =========================================
151  */
152  
153 -- 系统绑定变量 可以直接在 sqlplus 环境中定义
154 variable g_salary NUMBER 
155 -- 注意此变量不同于一般意义的plsql变量, 这个是在环境中定义的类似环境变量
156 
157 -- PL/SQL 定义变量
158 declare    v_depno number(2) not null := 100;
159 declare c_comn constant number := 1400;
160 declare v_location varchar(20) := 'hello world';
161 declare v_name employees.lastname%TYPE;
162 declare v_balance number(10,2);
163 declare v_min_balance v_balance%TYPE :=10; -- 参照上一个定义 v_balance
164 -- declare v_home = q'[tom's home]' -- 注意是以双引号内的形式, 实际环境中, 不需要双引号
165 declare l_right_now DATE NOT NULL DEFAULT SYSDATE;
166 
167 
168 -- 在 PL/SQL 中 sql 部分不需要冒号 :
169 declare v_bonus NUMBER(6);
170 begin
171     select salary * 0.01
172     INTO v_bouns
173     FROM employees
174     WHERE emp_id = '200912';
175 end;
176 
177 -- 游标 --
178 declare cursor cursor_name IS
179     select_statement;
180 open cursor_name
181 fetch cursor_name into variable1, varibal2
182 close cursor_name 
183 -- 以上4步骤, 分别为定义游标, 打开游标, 取出游标, 关闭游标
184 
185 -- 游标属性 --
186 cursor_name%isopen
187 cursor_name%notfound
188 cursor_name%found
189 cursor_name%rowcount
190 
191 -- 隐式游标举例 --
192 Function book_title (isbn_in IN books.isbn%TYPE)
193 return books.title%type
194 IS
195     return_value    book.title%type;
196 BEGIN
197     SELECT     title
198     into    return_value
199     from    books
200    where    isbn = isbn_in;
201    
202     return    return_value;
203     
204     exception
205         when no_date_found
206         then
207             return null;
208         when too_many_rows
209         then
210             errpkg.record_and_stop ('Data integrity error for:' || isbn_in);
211             raise;        
212 END;
213 
214 -- 显示游标举例 --
215 Function jealousy_level (
216     NAME_IN    IN    friends.NAME%TYPE)    RETURN    NUMBER
217 AS
218     cursor jealousy_cur
219     IS
220         select location from friends
221         where name = UPPER(name_in);
222         
223     jealousy_rec    jealousy_cur%ROWTYPE;    
224     retval    NUMBER;
225 BEGIN
226     OPEN jealousy_cur;
227     
228     fetch jealousy_cur into    jealousy_rec;
229     
230     IF jealousy_cur%found then
231         if jealousy_rec.location = 'PUERTO RICO' THEN
232             retval := 10;
233         elsif jealousy_rec.location = 'CHICAGO' THEN
234             retval := 1;
235         end if;
236     end if;
237     
238     close jealousy_cur;
239     
240     return retval;
241 EXCEPTION
242     when others then
243         if jealousy_cur%isopen then
244             close jealousy_cur;
245         end if;            
246 END;
247 
248 -- 游标变量 --
249 TYPE cursor_type_name IS REF CURSOR [RETURN return type];
250 
251 TYPE company_curtype IS REF CURSOR RETURN company%ROWTYPE;  -- 强类型
252 
253 TYPE generic_curtype IS REF CURSOR;                            -- 弱类型
254 
255 -- 从 oracle 9i 开始, 数据库已经替我们定义好了一个弱类型, 直接用就可以了
256 declare my_cursor SYS_RECURSOR;
257 
258 -- 声明游标变量的方法
259 cursor_name cursor_type_name;
260 
261 -- 打开游标变量
262 open cursor_name FOR select_statement;
263 -- 从游标变量获取数据, 同静态游标一样
264 FETCH cursor_variable_name INTO record_name;
265 FETCH cursor_variable_name INTO varibale_name, variable_name...;
266     
267 
268 -- 游标表达式
269 CURSOR( subquery )    
270     
271 -- 参数化 游标 --  参数的类型只能是 in 类型
272 declare
273     v_department    classes.department%type;
274     v_course        classes.course%type;
275     
276     cursor    c_classes is
277     select * from classes
278     where department = v_department
279     and course = v_course;
280 
281 declare
282     cursor c_classes(p_department classes.department%type, p_course classes.course%type) is
283     select * from classes
284     where department = v_department
285     and course = v_course;
286 open c_classes('HIS', 101);
287 
288 -- 游标中的 for update 语句, 加锁, 默认的游标是不会加锁的 --
289 -- 如果此时该表已经被加锁, 那么这个游标将无限期的被挂起, 直到该表所已经解开, 而 NOWAIT 语句表示不等挂起
290 -- 如果发现这个表已经被加锁, 直接会提示一个错误, 个人感觉 NOWAIT 好一点
291 
292 declare
293     v_NumCredits    classes.num_credites%type;
294     
295     cursor c_RegisteredStudents IS
296     select * from students
297     where id in ( select student_id
298                     from registered_students
299                     where department = ’HIS‘
300                     and course = 101)
301     for update of current_credits;  -- one column
302     
303 begin
304     for v_studentInfo in c_RegisteredStudents
305     loop
306         select num_credits
307         into v_NumCredits
308         from classes
309         where department = 'HIS'
310         and course = 101;
311         
312         update students
313             set current_credits = current_credits + v_NumCredits
314             where current of c_RegisteredStudents  -- 修改当前行的 column 值
315     end loop;
316 end;
317 
318 -- 注意 commit; 操作会释放锁, 所以如果你将 commit 写在 for 循环里的话, 那么再没有完成的情况下就释放锁,
319 -- 会出现错误提示 ORA-1002: fetch out of sequence
320 
321 declare
322     cursor c_AllStudents IS
323     select * from students
324     for update;        -- 注意, 这只有 for update, 所以所有的列都被加锁
325     
326     v_StudentInfo    c_AllStudents%ROWTYPE;
327 begin
328     open    c_AllStudents;
329     FETCH c_allStudents INTO v_StudentInfo;
330     -- 如果这时候使用 commit; 那么后边的记录就没有办法进行了, 所以推荐 close cursor 以后再 commit;
331 end;
332 
333 -- 当然, 如果你非想在 for 循环里使用 commit, 做法是, 现将游标全部提取出来, 然后通过 for 循环进行修改
334 declare
335     v_NumCredits    classes.num_credites%type;
336     
337     cursor c_RegisteredStudents IS
338     select * from students
339     where id in ( select student_id
340                     from registered_students
341                     where department = ’HIS‘
342                     and course = 101)
343     for update of current_credits;  -- one column
344     
345 begin
346     for v_studentInfo in c_RegisteredStudents
347     loop
348         select num_credits
349         into v_NumCredits
350         from classes
351         where department = 'HIS'
352         and course = 101;
353         
354         update students
355             set current_credits = current_credits + v_NumCredits
356             where current of c_RegisteredStudents  -- 修改当前行的 column 值
357         commit;  -- 注意此时已经通过 for 循环将所有游标提取到 v_studentInfo里, 并且不能使用
358                  -- where current of
359     end loop;
360 end;
361 
362 -- If statement --
363 IF salary >= 10000 AND salary <=20000
364 THEN
365     give_bonus(employee_id, 1500);
366 ELSIF salary > 20000 AND salary <= 40000
367 THEN
368     give_bonus(employee_id, 10000);
369 ELSIF salary > 40000
370 THEN
371     give_bouns(employee_id, 400);
372 END IF;
373 
374 -- case statement --
375 CASE employee_type
376 WHEN 'S' THEN
377     award_salary_bonus(employee_id);
378 WHEN 'H' THEN
379     award_hourly_bonus(employee_id);
380 WHEN 'C' THEN
381     award_commissioned_bonus(employee_id);
382 ELSE
383     RAISE invalid_employee_type;
384 END CASE;
385 
386 CASE TRUE
387 WHEN salary >= 10000 AND salary <= 20000 THEN
388     give_bouns(employee_id, 1500);
389 WHEN salary > 20000 AND salary < 40000 THEN
390     give_bouns(employee_id, 1000);
391 ELSE
392     give_bouns(employee_id, 0);
393 END CASE;
394 
395 -- loop --
396 
397 -- basic loop --
398 PROCEDURE display_multiple_years (
399     start_year_in IN PLS_INTEGER,
400     end_year_in IN PLS_INTEGER
401 )
402 IS
403     l_current_year PLS_INTEGER := start_year_in;
404 BEGIN
405     LOOP
406         EXIT WHEN l_current_year > end_year_in;
407         display_total_sales(l_current_year);
408         l_current_year := l_current_year + 1;
409     END LOOP;
410 END display_muliple_years;
411 
412 -- for loop --
413 procedure display_multiple_years( start_year_in IN PLS_INTEGER, end_year_in IN PLS_INTEGER)
414 IS
415 BEGIN
416     FOR l_current_year IN start_year_in .. end_year_in
417     LOOP
418         display_total_sales(l_current_year);
419     END LOOP;
420 END display_multiple_years;
421 
422 procedure display_multiple_years( start_year_in IN PLS_INTEGER, end_year_in IN PLS_INTEGER)
423 IS
424 BEGIN
425     FOR l_current_year IN (
426         select * from sales_date
427         where year between start_year_in and end_year_in)
428     LOOP
429         display_total_sales(l_current_year);
430     END LOOP;
431 END display_multiple_years;
432 
433 -- 游标参考 for loop --
434 
435 -- 一般形式的游标 --
436 declare 
437     cursor occupancy_cur IS
438     select pet_id, room_number
439     from occupancy where occupid_dt = trunc(sysdate);
440     
441     occupancy_rec occupancy_cur%rowtype;
442     
443 begin
444     open occupancy_cur;
445     loop
446         fetch occupancy_cur into occupancy_rec;
447         exit when occupancy_cur%notfound;
448         update_bill(occupancy_rec.pet_id, occupancy_rec.room_id);
449     end loop;
450     close occupancy_cur;
451 end;
452 
453 -- For loop 形式游标 --
454 declare 
455     cursor occupancy_cur IS
456     select pet_id, room_number
457     from occupancy where occupid_dt = trunc(sysdate);
458 begin
459     for occupancy_rac in occupacy_cur        -- occupancy 不用定义
460     loop
461         update_bill(occupancy_rec.pet_id, occupancy_rec.room_id);
462     end loop;
463 end;
464 
465 -- while loop --
466 procedure display_multiple_years( start_year_in IN PLS_INTEGER, end_year_in IN PLS_INTEGER)
467 IS
468     l_current_year PLS_INTEGER := start_year_in;
469 BEGIN
470     while (l_current_year <= end_year_in)
471     LOOP
472         display_total_sales(l_current_year);
473         l_current_year := l_current_year + 1;
474     END LOOP;
475 END display_multiple_years;
476 
477 -- --------------------------Exception ------------------------------------------------------------
478 -- EXCEPTION --
479 -- 1.抛出异常, 用户错误, 系统错误, 内存泄露等等问题都会抛出异常
480 --   抛出方式, raise exception_name, raise package_name.exception_name, raise;
481 --     raise_application_error 也可以抛出异常, 并且可以写自己bussiness的逻辑信息
482 procedure raise_by_language(code_in IN PLS_INTEGER)
483 IS
484     l_message error_table.error_string%TYPE;
485 BEGIN
486         SELECT error_string
487         INTO    l_message
488         FROM    error_table
489         where    error_number = code_in
490         and     string_language = USERNV('LANG');
491         
492         RAISE_APPLICATION_ERROR(code_in, l_message);    -- 抛出异常
493 END;
494 -- 2. 捕获异常
495 --      异常种类, oracle定义好有名字的异常, 一共20个, 没名字的异常, 还有就是用户定义异常
496 --      捕获异常后, 程序不会返回到抛出异常处, 执行完捕获异常, 看是向下还是停止.
497 --       当处理没有命名的异常时, 可以通过以下语句来定义名称
498 declare
499     e_emps_remaining    EXCEPTION
500     PRAGMA    EXCEPTION_INIT(e_emps_remaining, -2292);
501 begin
502     -- do something
503     exception
504         when e_emps_remaining then
505             statement1
506 end;
507 -- 3. 内置函数
508 SQLCODE -- 返回一个错误代码, 如果没有错误, 返回 0
509 SQLERRM -- 返回错误代码对应的官方错误信息
510 DBMS_UTILITY.FORMAT_ERROR_BACKTRACK -- 10g 以后开始饮用, 返回一个格式化文本串(可以返回抛出异常行号)
511 -- ---------------------------------End Exception -------------------------------------------------
512 
513 -- --------------------- 动态 sql -----------------------------------------------------------------
514 
515 
516 
517 -- ---------------------- End 动态 sql ------------------------------------------------------------
518 
519     

 

posted @ 2013-12-03 17:25  神之一招  阅读(2336)  评论(0编辑  收藏  举报