数据库学习笔记

1.       打开一个PL/SQLCommand Window

Select object_name From user_objects Where object_type='TRIGGER';  --所有触发器
Select object_name From user_objects Where object_type='PROCEDURE';  --所有存储过程
Select object_name From user_objects Where object_type='VIEW';  --所有视图
Select object_name From user_objects Where object_type='TABLE'; --所有表
SELECT * FROM user_objects;--查询本用户创建的对象

2.       简单的语句块

a.     

begin
  dbms_output.put_line('hellow world');
end;
/
set serveroutput on;--显示输出结果

b.      

declare
  v_name varchar2(20);
begin
  v_name := 'myname';
  dbms_output.put_line(v_name);
end;

c.      

declare
  v_num number:=0;
begin
  v_num := 2/v_num;
  dbms_output.put_line(v_num);
exception
  when others then
    dbms_output.put_line('error');
end;

3.       变量声明的规则

a.       变量名不能使用保留字,如fromselect

b.       第一个字符必须是字母

c.       最多包含30个字符

d.       不要与数据库的表或者列同名

e.       每一行只能声明一个变量

f.       建议用“v_”开头命名

4.       常用变量类型

a.       binary_integer:整数,主要用来计数而不是用来表示字段类型

b.       number:数字类型

c.       char:定长字符串

d.       varchar2:变长字符串

e.       date:日期

f.       long:长字符串,最长2GB

g.       boolean:布尔类型,可以取值为truefalsenull建议赋初值

5.       变量声明

a.      

declare
  v_temp number(1);
  v_count binary_integer := 0;
  v_sal number(7,2) := 4000.00;
  v_date date:= sysdate;
  v_pi constant number(3,2) := 3.14;
  v_valid boolean := false;
  v_name varchar2(20) not null := 'Myname';
begin
  dbms_output.put_line(v_sal||v_date);
end;
--(不能输出boolean类型)

b. 

--变量声明,使用%type属性
declare
  v_sn s.sn%type;
  v_snn v_sn%type;
begin
  dbms_output.put_line('123');
end;

c.       --record变量类型,类似于java中的类

declare
  type type_record_s is record(v_sn s.sn%type,v_sd s.sd%type,v_sa s.sa%type);
  v_temp type_record_s;
begin
  v_temp.v_sn := 'abc';
  v_temp.v_sd := 'sdabc';
  v_temp.v_sa := 123;
  dbms_output.put_line(v_temp.v_sn||' '||v_temp.v_sd||' '||v_temp.v_sa);
end;

d.       --使用%rowtype声明record变量(直接对应表中的所有字段

declare
  v_tmp s%rowtype;
begin
  v_tmp.sn := 'abc';
  v_tmp.sd := 'sdabc';
  v_tmp.sa := 123;
  dbms_output.put_line(v_tmp.sn||' '||v_tmp.sd||' '||v_tmp.sa);
end;

e.       --Table变量类型(类似于java的数组)(type_table_表名_字段名)(table中类型)(数组下标的类型)

declare
  type type_table_s_sid is table of s.sid%type index by binary_integer;
  v_sids type_table_s_sid;
begin
  v_sids(0) := 1234;
  v_sids(-1) := 2345;
  v_sids(-2) := 3456;
  dbms_output.put_line(v_sids(0)||' '||v_sids(-1)||' '||v_sids(-2));
end;

6.  plsql查询语句:必须返回一条数据,有且只有一条数据

a. 

declare
  v_sn s.sn%type;
  v_sd s.sd%type;
begin
  SELECT sn,sd into v_sn,v_sd FROM s WHERE sid = '1';
  dbms_output.put_line(v_sn||' '||v_sd);
exception
  when others then
    dbms_output.put_line('error');
end;

b.       --使用%rowtype声明变量(直接对应表中的所有字段

DECLARE
  v_temp s%ROWTYPE;
BEGIN
  SELECT * into v_temp FROM s WHERE sid = '2011001';
  dbms_output.put_line(v_temp.sn||' '||v_temp.sd);
exception
  when others then
    dbms_output.put_line('error');
end;

7.       plsql插入语句

DECLARE
  v_sid s.sid%TYPE := 2011111;
  v_sn s.sn%TYPE := 'abcd';
  v_sd s.sd%TYPE := 'ABCD';
  v_sa s.sa%TYPE := 98;
BEGIN
  INSERT INTO s VALUES(v_sid,v_sn,v_sd,v_sa);
  COMMIT;
end;

8.       plsql更新语句(SQL%ROWCOUNT,sql是刚执行的sql,rowcount是受到影响的记录数

DECLARE
  v_sid s.sid%TYPE := 2011111;
  v_count NUMBER;
BEGIN
  --UPDATE s SET SID = 2011011 WHERE SID = v_sid;
  --SELECT SID INTO v_sid FROM s WHERE SID = 2011111;
  SELECT COUNT(*) INTO v_count FROM s;
  dbms_output.put_line(SQL%ROWCOUNT||'条记录被影响');
  --COMMIT;
end;

9.       执行DDL语句

BEGIN
  EXECUTE IMMEDIATE 'create table t (nnn varchar2(20) default ''aaa'')';
END;

10.   if语句

DECLARE
  v_sa s.sa%TYPE;
BEGIN
  SELECT sa INTO v_sa FROM s WHERE SID = 2011009;
  IF(v_sa < 60)THEN
    dbms_output.put_line('unpass');
  ELSIF(v_sa < 90)THEN
    dbms_output.put_line('good');
  ELSE
    dbms_output.put_line('nice');
  END IF;
END;

 

11. 循环语句

a.      

DECLARE
  i BINARY_INTEGER := 1;
BEGIN
  LOOP
    dbms_output.put_line(i);
    i := i + 1;
    EXIT WHEN (i>=11);--(可以不用括号)
  END LOOP;
END;

b.      

DECLARE
  i BINARY_INTEGER := 1;
BEGIN
  WHILE i<11 LOOP
    dbms_output.put_line(i);
    i := i + 1;
  END LOOP;
END;

c.      

BEGIN
  FOR k IN 1..10 LOOP
    dbms_output.put_line(k);
  END LOOP;
  FOR k IN REVERSE 1..10 LOOP
    dbms_output.put_line(k);
  END LOOP;
END;

12. 错误处理

a.  常见的异常

b. 

--创建错误日志表
CREATE TABLE errorlog(
  ID NUMBER PRIMARY KEY,
  errorcode NUMBER,
  errormsg VARCHAR2(1024),
  errortime DATE
);
--创建序列
CREATE SEQUENCE seq_errorlog_id START WITH 1 INCREMENT BY 1;
--生成错误日志
declare
  v_num number:=0;
  v_errorcode NUMBER;
  v_errormsg VARCHAR2(1024);
begin
  v_num := 2/v_num;
  dbms_output.put_line(v_num);
exception
  when others THEN
    ROLLBACK;
    v_errorcode := SQLCODE;
    v_errormsg := SQLERRM;
    INSERT INTO errorlog VALUES(seq_errorlog_id.nextval,v_errorcode,v_errormsg,SYSDATE);
    COMMIT;
end;

13. 游标

a.  --do-while循环

DECLARE
  CURSOR cur IS SELECT * FROM s;
  v_s cur%ROWTYPE;
BEGIN
  OPEN cur;
    LOOP
      FETCH cur INTO v_s;
      EXIT WHEN (cur%NOTFOUND);
      dbms_output.put_line(v_s.sn);
    END LOOP;
  CLOSE cur;
END;

b.       --while循环

DECLARE
  CURSOR cur IS SELECT * FROM s;
  v_s cur%ROWTYPE;
BEGIN
  OPEN cur;
    FETCH cur INTO v_s;
    WHILE(cur%FOUND) LOOP
      dbms_output.put_line(v_s.sn);
      FETCH cur INTO v_s;
    END LOOP;
  CLOSE cur;
END;

 

c.       --for循环

DECLARE
  CURSOR cur IS SELECT * FROM s;
BEGIN
  FOR v_s IN cur LOOP
    dbms_output.put_line(v_s.sn);
  END LOOP;
END;

 

d.  带参数的游标

DECLARE
  CURSOR cur(v_sn s.sn%TYPE,v_sa s.sa%TYPE) IS 
    SELECT sn,sa FROM s WHERE sn = v_sn AND sa = v_sa;
BEGIN
  FOR v_s IN cur('warren',95) LOOP
    dbms_output.put_line(v_s.sn);
  END LOOP;
END;

 

e.  可以更新的游标

DECLARE
  CURSOR cur IS SELECT * FROM s FOR UPDATE;
BEGIN
  FOR v_s IN cur LOOP
    IF(v_s.sa = 90) THEN
      UPDATE s SET sa = 91 WHERE CURRENT OF cur;
    ELSIF (v_s.sa = 95) THEN
      dbms_output.put_line(v_s.sn);
    END IF;
  END LOOP;
  COMMIT;
END;

14. 存储过程(有名字的plsql语句块)

a.      

CREATE OR REPLACE PROCEDURE usp_cursor_forupdate IS--(替换declare即可)
  CURSOR cur IS SELECT * FROM s FOR UPDATE;
BEGIN
  FOR v_s IN cur LOOP
    IF(v_s.sa = 90) THEN
      UPDATE s SET sa = 91 WHERE CURRENT OF cur;
    ELSIF (v_s.sa = 95) THEN
      dbms_output.put_line(v_s.sn);
    END IF;
  END LOOP;
  COMMIT;
END;

 

b.  带参数的存储过程

CREATE OR REPLACE PROCEDURE usp_p
(v_a IN NUMBER, v_b NUMBER ,v_ret OUT NUMBER, v_temp IN OUT NUMBER)
IS
BEGIN
  IF(v_a > v_b) THEN
    v_ret := v_a;
  ELSE
    v_ret := v_b;
  END IF;
  v_temp := v_temp + 1;
END;
/
调用存储过程
DECLARE
  v_a1 NUMBER := 3;
  v_b NUMBER := 4;
  v_ret NUMBER;
  v_temp NUMBER := 5;
BEGIN
  usp_p(v_a1,v_b,v_ret,v_temp);
  dbms_output.put_line(v_ret);
  dbms_output.put_line(v_temp);
END;

 

15.   函数

CREATE OR REPLACE FUNCTION sa_count
  (v_sa NUMBER)
  RETURN NUMBER
IS
BEGIN
  IF(v_sa < 92) THEN
    RETURN 60;
  ELSIF(v_sa < 95) THEN
    RETURN 80;
  ELSE
    RETURN 90;
  END IF;
END;

 

16. 触发器

CREATE TABLE s_log
(
  username VARCHAR2(20),
  action VARCHAR2(10),
  actiontime DATE
);
    
CREATE OR REPLACE TRIGGER trig
  AFTER INSERT OR DELETE OR UPDATE ON s FOR EACH ROW
BEGIN
  IF inserting THEN
    INSERT INTO s_log VALUES(USER,'insert',SYSDATE);
  ELSIF updating THEN
    INSERT INTO s_log VALUES(USER,'update',SYSDATE);
  ELSIF deleting THEN
    INSERT INTO s_log VALUES(USER,'delete',SYSDATE);
  END IF;
END;
--触发器的副作用,很少用的情况:
UPDATE dept SET deptno = 99 WHERE deptno = 10; 
--违反完整约束条件
    
CREATE OR REPLACE TRIGGER trig
  AFTER UPDATE ON dept
  FOR EACH ROW
BEGIN
  UPDATE emp SET deptno = :new.deptno WHERE deptno = :old.deptno;
END;

--当使用update的时候,执行完后,先检查触发器,然后再检查约束条件(即能不能执行该语句)
UPDATE dept SET deptno = 99 WHERE deptno = 10; 
--错误:违反完整约束条件
    
CREATE OR REPLACE TRIGGER trig
  AFTER UPDATE ON dept
  FOR EACH ROW
BEGIN
  UPDATE emp SET deptno = :new.deptno WHERE deptno = :old.deptno;
END;

 

17. 树状结构的存储与展示

a.      

CREATE TABLE article
(
  ID NUMBER PRIMARY KEY,
  CONT VARCHAR2(4000),
  pid NUMBER,
  isleaf NUMBER(1),--0代表非叶子节点,1代表叶子节点
  alevel NUMBER(2)
);
    
INSERT INTO article VALUES(1,'蚂蚁大战大象',0,0,0);
INSERT INTO article VALUES(2,'大象被打趴下了',1,0,1);
INSERT INTO article VALUES(3,'蚂蚁也不好过',2,1,2);
INSERT INTO article VALUES(4,'瞎说',2,0,2);
INSERT INTO article VALUES(5,'没有瞎说',4,1,3);
INSERT INTO article VALUES(6,'怎么可能',1,0,1);
INSERT INTO article VALUES(7,'怎么没有可能',6,1,2);
INSERT INTO article VALUES(8,'可能性是很大的',6,1,2);
INSERT INTO article VALUES(9,'大象进医院了',2,0,2);
INSERT INTO article VALUES(10,'护士是蚂蚁',9,1,3);
COMMIT;

 

b.       树状结构展示(递归调用存储过程

CREATE OR REPLACE PROCEDURE usp_p(v_pid article.pid%TYPE,v_level BINARY_INTEGER) IS
  CURSOR cur IS SELECT * FROM article WHERE pid = v_pid;
  v_preStr VARCHAR2(1024) := '';
BEGIN
  FOR i IN 1..v_level LOOP
    v_preStr := v_preStr||'****';
  END LOOP;
    
  FOR v_article IN cur LOOP
    dbms_output.put_line(v_preStr||v_article.cont);
    IF(v_article.isleaf = 0)THEN
      usp_p(v_article.id,v_level + 1);
    END IF;
  END LOOP;
END;
    
exec usp_p(0,0);
    
结果:
蚂蚁大战大象
****大象被打趴下了
********蚂蚁也不好过
********瞎说
************没有瞎说
********大象进医院了
************护士是蚂蚁
****怎么可能
********怎么没有可能
********可能性是很大的

18.用到的数据库表 s

create table S
(
  sid NUMBER(10) not null,
  sn  VARCHAR2(20),
  sd  VARCHAR2(30),
  sa  NUMBER(3)
);
insert into S (sid, sn, sd, sa)
values (2011001, 'jim', 'DL', 90);
insert into S (sid, sn, sd, sa)
values (2011002, 'tom', 'DL', 90);
insert into S (sid, sn, sd, sa)
values (2011003, 'jerry', 'DL', 92);
insert into S (sid, sn, sd, sa)
values (2011004, 'lucy', 'HTC', 93);
insert into S (sid, sn, sd, sa)
values (2011005, 'bill', 'HTC', 94);
insert into S (sid, sn, sd, sa)
values (2011006, 'warren', 'HTC', 95);
insert into S (sid, sn, sd, sa)
values (2011007, 'james', 'LG', 96);
insert into S (sid, sn, sd, sa)
values (2011008, 'cart', 'LG', 97);
insert into S (sid, sn, sd, sa)
values (2011009, 'lee', 'LG', 98);
insert into S (sid, sn, sd, sa)
values (2011010, 'kobe', 'APPLE', 99);
insert into S (sid, sn, sd, sa)
values (2011111, 'abcd', 'ABCD', 98);
commit;

 

你可能感兴趣的:(oracle,数据库,触发器,function,plsql)