用戶、角色、權限、表空間
create tablespace test1_tablespace datafile ‘test1file.dbf’ size 10m;
create temporary tablespace temptest1_tablespace tempfile ‘temp1file.dbf’ size 10m;
創建永久表空間和臨時表空間,並指定表空間名字,指定文件名稱,大小(如不指定位置即放在默認位置)
select file_name from dba_data_files where tablespace_name=’test1_tablespace’;
select file_name from dba_temp_files where tablespace_name=’temptest1_tablespace’;
查看上面剛創建的永久表空間和臨時表空間的文件所在位置(dba_data_files、dba_temp_files)
connect sys/oracle@orcl as sysdba 鏈接使用系統管理用戶sys密碼oracle,並以sysdba身份鏈接實例orcl(sysdba數據庫管理員權限,sysoper數據庫操作員權限,另外不寫實例的話會鏈接默認實例)
create user yan identified by test default tablespace test1_tablespace temporary tablespace temptest1_tablespace;
創建用戶yan密碼test,設置默認表空間test1_tablespace、臨時表空間temptest1_tablespace
select username from dba_users; 從dba_users表中查詢username
grant connect to yan; 授權connect操作給用戶yan
connect yan/test 鏈接使用用戶yan密碼test
alter user yan identified by test123; 修改yan用戶密碼為test123
alter user yan account lock; 鎖定用戶yan(解鎖就是unlock,當然要切換到有權限的用戶下去執行此類命令)
drop user yan cascade; 刪除用戶yan及其創建的數據(cascade參數是連同其創建的東西全部刪除)
CONNECT(連接角色) 只可以登錄ORACLE,不可以創建實體,不可以創建數據庫結構
RESOURCE(資源角色) 可以創建實體,不可以創建數據庫結構
DBA(數據庫管理員角色) 擁有全部權限,最高權限,只有DBA才可以創建數據庫結構
grant connect to user01;
grant resource to user01;
grant dba to user01;
創建自定義的角色
create role 角色名;
例子:create role manager;
賦予權限、回收權限
grant 權限 to 角色或用戶 (grant A to B)
例子:grant create table,create view to manager; 創建表、創建視圖權限給角色manager
grant manager to user01,user02; 角色manager賦予給用戶user01、user02
revoke 權限或角色 from 角色或用戶 (revoke A from B)
例子:revoke manager from user01; 回收用戶user01的角色manager權限
revoke create table,create sequence from manager; 回收角色manager的創建表、創建序列權限
select * from system_privilege_map
create session 創建會話 create sequence 創建序列 create table 創建表 create user 創建用戶 alter user 更改用戶drop user 刪除用戶 create view 創建視圖
授權對象權限、回收對象權限
對象權限有select、update、insert、delete、all......
grant 對象權限 on 對象 to 用戶或角色 (如對象on user01.school)
revoke 對象權限 on 對象 from 用戶或角色 (如對象on user01.work)
數據字典 dba_tablespace、user_tablespace
select tablespace_name from dba_tablespace;
select tablespace_name from user_tablespace;
數據字典 dba_users、user_users
select default_tablespace,temporary_tablespace from dba_users where username=’system’
alter user 用戶名 default tablespace或temporary tablespace 表空間名
alter user user01 default tablespace test1_tablespace temporary tablespace temptest1_tablespace
修改表空間狀態
alter tablespace 表空間名 online或offline或read only或read write
修改表空間數據文件
alter tablespace 表空間名 add datafile’filename.dbf’ size 10M; 此為增加數據文件
alter tablespace 表空間名 drop datafile’filename.dbf’; 此為刪除數據文件(不能刪除第一個創建的數據文件,除非刪除整個表空間)
刪除表空間
drop tablespace 表空間名 (只刪除表空間,不刪除對應數據文件)
drop tablespace 表空間名 including contents (刪除表空間及對應數據文件)
表管理
DDL 數據定義語言
DML 數據操作語言
DCL 數據控制語言
TCL 事務控制語言
DDL常用語句:
create table 創建表 create index 創建索引 drop table 刪除表 drop index 刪除索引 truncate 刪除表所有行 alter table 更改表結構,增加、修改、刪除列 alter table add constraint 在已有表中增加約束
DML常用語句:
insert 添加數據 update 修改數據 delete 刪除數據 select 查詢數據
DCL常用語句:
grant 授予權限 revoke 撤銷權限 lock 鎖定
TCL常用語句:
commit 提交事務 rollback 回退事務 savepoint 設置保存點
創建表語法結構:
create table 表名 ( 列名 列數據類型 , 列名 列數據類型 ... ...);
數據類型:字符類型、數值類型、日期時間類型、LOB類型
字符類型有 char、varchar2
數值類型 number[(p[,s])] p表示精度,s表示小數點位數
如 number(5,0)最多可存儲5位數整數 number(5,2)最大可存儲999.99的浮點數
日期類型有 date
LOB類型有CLOB、BLOB
例子:create table student( sid number(8,0),name varchar2(20),sex char(2),birthday date,address varchar2(50) );
約束是oracle提供的自動保持數據完整性的一種方法,它通過限制字段中的數據、記錄中數據和表之間的數據來保證數據的完整性。
約束語法結構:[constraint 約束名] <約束類型>
主鍵約束、唯一性約束、默認約束、非空約束、檢查約束、外部鍵約束
主鍵約束 primary key 它是唯一確定表中每一條記錄的標識符,其值不能為NULL,也不能重復。表中主鍵只能有一個,但可以由多個列組成。
create table student(
sid number(8,0),
name varchar2(20),
sex char(2),
birthday date,
address varchar2(50),
constraint sid_pk primary key(sid) );
修改表添加主鍵約束
alter table student add constraint sid_pk primary key(sid);
非空約束用於確保列不能為NULL,它是列級約束。
列級約束:column [CONSTRAINT constraint_name] constraint_type 列級約束必須跟在列的定義后面
表級約束:column,… …
[CONSTRAINT constraint_name] constraint_type
(column,… …), 表級約束不與列一起,而是單獨定義的
create table student(
sid number(8,0),
name varchar2(20) not null, 列級約束
sex char(2) constraint nn_sex not null, 列級約束
birthday date,
address varchar2(50),
constraint sid_pk primary key(sid) ); 表級約束
修改表添加約束格式:
ALTER TABLE table_name ADD [CONSTRAINT constraint_name] constraint_type (column);
而非空約束要使用MODIFY語句 ALTER TABLE table_name MODIFY (column datatype NOT NULL);
刪除約束方式可以禁用或者徹底刪除
DISABLE|ENABLE CONSTRAINT constraint_name;
DROP CONSTRAINT constraint_name;
DROP PRIMARY KEY 為何這個可以這樣寫,因為表中只有一個呀,寫不寫約束名都知道的
ALTER TABLE table_name MODIFY column_name datatype NULL;
唯一約束用於指定一個或者多個列的組合值具有唯一性,以防止在列中輸入重復值。
create table student(
sid number(8,0) unique, 列級約束
name varchar2(20),
sex char(2),
birthday date,
address varchar2(50),
constraint uk_sid unique(sid)); 表級約束
修改表添加唯一約束 alter table student add constraint uk_sid unique(sid);
檢查約束對輸入列或者整個表中的值設置檢查條件,以限制輸入值,保證數據完整性。
create table student(
sid number(8,0),
name varchar2(20),
sex char(2) check(sex=’男’ or sex=’女’), 列級約束
birthday date,
address varchar2(50),
constraint sid_pk primary key(sid) );
create table student(
sid number(8,0),
name varchar2(20),
sex char(2),
birthday date,
address varchar2(50),
constraint ck_sex check(sex=’男’ or sex=’女’)); 表級約束
修改表添加檢查約束 alter table student add constraint ck_sex check(sex=’男’ or sex=’女’);
外鍵約束是用於建立和加強兩個表數據之間的鏈接的一列或多列。它是唯一涉及兩個表關系的約束
列級約束:
CREATE TABLE 從表
(column_name datatype REFERENCES
主表(column_name) [ON DELETE CASCADE],… …);
表級約束:
CONSTRAINT constraint_name FOREIGN KEY (column_name)
REFERENCES 主表(column_name) [ON DELETE CASCADE]
設置外鍵約束時主表的字段必須是主鍵列(或唯一列),主從表中相應字段必須是同一數據類型,從表中外鍵字段的值必須來自主表中的相應字段的值(或為NULL)
例子:
主表 create table department ( depid varchar2(10) primary key, depname varchar2(30) );
從表 create table student (sid number(8,0), name varchar2(20), sex char(2), birthday date, address varchar2(50),
depid varchar2(10) references department(depid) ); 列級約束,其中從表列名稱可以和主表名稱不一樣
主表 create table department ( depid varchar2(10) primary key, depname varchar2(30) );
從表 create table student (sid number(8,0), name varchar2(20), sex char(2), birthday date, address varchar2(50),
depid varchar2(10), constraint fk_depid foreign key(depid)
references department(depid) on delete cascade ); 表級約束,同樣從表定義的列可以和主表名稱不一樣
添加列語句結構:
ALTER TABLE 表名 ADD 新增列名 數據類型
ALTER TABLE student ADD tel varchar2(11)
修改列語句結構:
ALTER TABLE 表名 MODIFY 列名 新數據類型
ALTER TABLE student MODIFY tel number(11,0)
修改列名語句結構:
ALTER TABLE 表名 RENAME COLUMN 列名 TO 新列名
ALTER TABLE student RENAME COLNMN sex TO gender
刪除表語句
TRUNCATE TABLE 表名 (用於刪除表全部數據,但表結構還在,這種刪除方式也叫截斷表)
DROP TABLE 表名 (刪除表結構)
添加信息語句結構:
INSERT INTO 表名[(列1,列2,… …)] VALUES(值1,值2,… …)
INSERT INTO student (sid,name,sex) VALUES(18733,’周小仙’,’男’)
查詢信息語句結構:
SELECT * column_name FROM 表名
SELECT * FROM student SELECT sid,name,sex FROM student
修改信息語句結構:
UPDATE table SET column = value [WHERE condition]
UPDATE student SET tel = ‘15899999999’ WHERE sid = 18733
刪除信息語句結構:
DELETE FROM table [WHERE condition]
DELETE FROM student WHERE sid = 18733
事務可以看作是由數據庫的若干操作組成的一個單元,這些操作要么都完成,要么都取消,從而保證數據滿足一致性的要求。
事務組成可以是一條或者多條DML,或一條DDL,或一條DCL
DML語句需要使用COMMIT提交事務或使用ROLLBACK回滾事務
DDL和DCL是自動提交事務的
使用事務的原因主要是為保證數據的安全有效,這里需要提到“表鎖”
基本查詢
語法格式:
SELECT * {[DISTINCT] column_name | expression [alias],… …} FROM table_name [WHERE condition]
其中expression指表達式,alias指列的別名,condition指查詢條件
查詢有特定列查詢、全部列查詢、排除重復行、日期列的查詢、條件查詢(過濾數據,涉及運算符使用、范圍查詢、模糊查詢、空值判斷、邏輯運算符使用等)查詢結果排序
SELECT DISTINCT deptno,job FROM emp 排除重復數據
ALTER SESSION SET nls_language=’SIMPLIFIED CHINESE’ 以簡體中文顯示日期
ALTER SESSION SET nls_date_format=’YYYY/MM/DD’ 以特定格式顯示日期
運算符優先級 + - * / 從左到右執行,乘除高於加減,括號內優先
NULL表示未知值,和其運算結果也為空(即NULL)
另外列可以給予默認值,使用default
列的別名用於改變列的顯示標題
列別名可以跟在列名的后面,也可以在二者之間加AS關鍵字
SELECT empno “雇員編號”, ename “雇員名”, sal*12 “全年工資” FROM emp
SELECT empno AS “雇員編號”, ename AS “雇員名”, sal*12 AS “全年工資” FROM emp
連接符 ||
它把列與列,列與字符 連接在一起
Select ename ||’的崗位是:’|| job as 員工的職位信息描述 from emp
WHERE子句過濾條件
select * from emp where deptno=20
select * from emp where job=’manager’
select * from emp where hiredate=’22-3月-86’
范圍查詢between…and和in
模糊查詢like (通配符%表示0個或多個字符,通配符_表示單個字符)
判斷空值is null
模糊查詢中如果字符值本身就包含_和%字符,就需要用escape選項和轉義符實現
Select * from emp where ename like ‘G\_%’ escape ‘\’ 其實模糊查詢的是G_%
另外判斷是否為空,不可以寫成=NULL,<>NULL 這都是錯誤寫法,應該是is null或is not null
NOT優先級最高,AND其次,OR最低
單列排序、多列排序、列別名排序
SELECT *|column_name FROM table_name [WHERE condition] [ORDER BY column_name [ASC|DESC] ]
當SELECT語句包含多個子句(where,group by,having,order by)時,order by必須是最后一條語句
Select ename,sal from emp order by sal desc 降序排序
Select empno,ename,sal*12 年收入 from emp order by 年收入 desc 使用列別名排序
Select empno,ename,deptno,sal from emp order by deptno asc, sal desc 多列排序
單行函數
顧名思義就是輸出一行的函數,當然多行函數就是輸出一行或多行的函數
單行函數有字符函數、數值函數、日期函數、轉換函數、通用函數
字符函數:1.大小寫控制函數 有UPPER、LOWER、INITCAP
2.字符控制函數 有CONCAT、SUBSTR、LENGTH、INSTR、LPAD、RPAD、TRIM、REPLACE
UPPER(char) 用於將字符串轉換為大寫格式
LOWER(char) 用於將字符串轉換為小寫格式
INITCAP(char) 用於將字符串中的每個單詞的首字母轉換為大寫格式,其他字符小寫
CONCAT(str1,str2) 用於字符串的連接
例子concat(‘hello’,’oracle’) 結果:hellooracle
SUBSTR(char,m[n]) 用來截取字符串,char指定源字符串,m用於指定從哪個位置開始截取,n用於指定截取字符串的長度。如果m為0,則從首字符開始,如果m為負數,則從尾部開始。
例子 substr(‘hello’,1,3) 結果:hel
例子 substr(‘hello’,0,3) 結果:hel
例子 substr(‘hello’,-1,1) 結果:o
LENGTH(char) 用於返回字符串的長度,字符串中的后綴空格也記作字符串的長度。
例子 length(‘oracle ‘) 結果:7
INSTR(char1,char2[,n[m]]) 用於指定字符串在源字符串中的位置,char1源字符串,char2指定字符串,n用於指定起始搜索位置,m用於指定字符串第m次出現的次數(n,m默認都是1)
例子 instr(‘hello oracle’,’oracle’) 結果:7
例子 instr(‘hello oracle hello oracle’,’oracle’,2,2) 結果:20
LPAD(char1,n,char2) 用於在字符串的左端填充字符,char1源字符串,char2被填充字符,n用於指定填充后的char1的總長度。
例子 lpad(‘hello’,10,’#’) 結果:#####hello
RPAD(char1,n,char2) 用於在字符串的右端填充字符,char1源字符串,char2被填充字符,n用於指定填充后的char1的總長度。
例子 rpad(‘hello’,10,’@’) 結果:hello@@@@@
REPLACE(char,search_string[,replacement_string]) 用於替換字符串的子串內容,char源字符串,search_string被替換子串,replacement_string替換子串
例子 replace(‘hello oracle’,’oracle’,’world’) 結果:hello world
數值函數有ROUND、TRUNC、MOD
ROUND(n,[m]) 用於四舍五入結果,n可以是任意數字,m必須是整數
例子 round(25.328,2) 結果:25.33 round(25.328,-1) 結果:30
TRUNC(n,[m]) 用於截取數字,n可以是任意數字,m必須是整數
例子 trunc(25.328,2) 結果:25.32 trunc(25.328,-1) 結果:20
MOD(m,n) 用於求余數,m除於n得到的余數,如果n為0,則返回結果為m
例子 mod(25,6) 結果:1 mod(25,0) 結果:25
日期函數常用函數有SYSDATE、MONTHS_BETWEEN、ADD_MONTHS、NEXT_DAY、LAST_DAY、ROUND、TRUNC
SYSDATE 用於返回當前系統日期
例子 select sysdate from dual
MONTHS_BETWEEN(d1,d2) 用於返回日期d1和d2之間相差的月數。d1大於d2結果為正數,否則為負數
例子 select months_between(sysdate,hiredate) from emp
ADD_MONTHS(d,n) 用於返回特定日期時間之后或之前的月份所對應的日期時間。(求出若干月之后的日期)d用於指定日期時間,n可以是任意整數。
例子 select ename,add_months(hiredate,30*12) from emp
NEXT_DAY(d,char) 用於返回特定日期之后的第一個工作日所對應的日期。D用於指定日期時間值,char用於指定工作日。注意:當使用該函數時,工作日必須與日期語言匹配,假如日期語言為AMERICAN,那么周一對應於MONDAY;假如日期語言為簡體中文,那么周一對應於”星期一”。
例子 select sysdate,next_day(sysdate,’星期一’) from dual
ROUND(d,[fmt]) 用於返回日期時間的四舍五入的結果。d用於指定日期的時間值,fmt用於指定四舍五入的方式,如果設置fmt為YEAR,則7月1日為分界線,如果設置fmt為MONTH,則16日為分界線。
例子 如果系統時間是’20-7月-17’ round(sysdate,’YEAR’) 結果:01-1月-18 round(sysdate,’MONTH’) 結果:01-8月-17
TRUNC(d,[fmt]) 用於截斷日期時間數據。d用於指定日期的時間值,fmt用於指定截斷日期時間數據的方法,如果設置fmt為YEAR,則結果為本年度的1月1日,如果設置fmt為MONTH,則結果為本月1日。
例子 trunk(sysdate,’YEAR’) trunk(sysdate,’MONTH’)
轉換函數 TO_DATE、TO_CHAR、TO_NUMBER
TO_CHAR(d,[fmt[‘nlsparams’]]) 將日期類型轉換為字符類型。d用於指定日期值,fmt用於指定日期格式模型,‘nlsparams’用於指定日期顯示語言
例子 select to_char(hiredate,’DD-MON-RR’, ‘NLS_DATE_LANGUAGE=AMERICAN’) from emp
TO_CHAR(n,[fmt]) 將數值類型轉換為字符類型。n用於指定數值,fmt用於指定數字格式模型。
格式模型,常見的元素如下:
9:顯示數字,並且會忽略前導0
0:顯示數字,如果位數不足,則用0補齊
. :在指定位置顯示小數點
, :在指定位置顯示逗號
$ :在數字前加美元符號
L :在數字前加本地貨幣符號
例子 select sal,to_char(sal,’L999,999.99’) from emp select sal,to_char(sal,’$999.999.99’) from emp
TO_DATE(char,[fmt[‘nlsparams’]]) 將字符串轉換成日期類型的數據。Char用於匹配日期數據的字符串,fmt用於指定日期格式模型,’nlsparams’用於指定日期語言。
例子 select ename,hiredate from emp where hiredate>to_date(‘1986-3-22’,’YYYY-MM-DD’)
TO_NUMBER(n,[fmt]) 將包含數字的字符串轉換成數值類型。N是包含數字的字符串,fmt用於指定數字格式模型
例子 select ename,sal from emp where sal>to_number(‘¥2000’,’L99999’)
通用函數有NVL、NVL2、NULLIF、COALESCE
NVL(expr1,expr2) 該函數用於處理NULL,如果expr1是null,則返回expr2,如果expr1不是null,則返回expr1
例子 select ename,sal,comm,sal+nvl(comm,0) from emp
NVL2(expr1,expr2,expr3) 該函數用於處理NULL,如果expr1不是null,則返回expr2,如果expr1是null,則返回expr3
例子 select ename,sal,comm,nvl2(comm,sal+comm,sal) from emp
NULLIF(expr1,expr2) 該函數用於比較表達式expr1和expr2,如果二者相等,則返回NULL,否則返回expr1
例子 select empno,ename,hiredate,nullif(hiredate,trunk(sysdate,’MONTH’)) from emp
COALESCE(expr1,[expr2]… ) 用於返回表達式列表中的第一個NOT NULL表達式的結果
例子 select ename,sal,comm,coalesce(sal+comm,sal) from emp
CASE表達式語法格式
CASE expr
WHEN comparison_expr1 THEN return_expr1
[WHEN comparison_expr2 THEN return_expr2
… …
ELSE else_expr]
END
例子 select empno,ename,
case job
when ‘CLERK’ then ‘辦事員’
when ‘SALESMAN’ then ‘銷售’
else ‘總裁’
end
from emp
DECODE(column | expression,search1,result1,[ search2,result2, …] [default])
例子 select empno,ename,job,decode(job, ‘CLERK’, ‘辦事員’, ‘SALESMAN’ , ‘銷售’, ‘總裁’) from emp
單行函數看可以嵌套。嵌套函數的執行順序是由內到外。
例子 to_char(next_day(add_months(hiredate,3),’星期一’),’YYYY-MM-DD’)
to_char(round(sal/30,2),’L999,999’)
分組函數
分組函數有avg、sum、min、max、count、wm_concat
分組函數就是多行函數,作用於一組數據,並一組數據返回一個值。
Select avg(sal) from emp
Select min(sal) from emp
Select max(sal) from emp
Select count(*) from emp
Distinct關鍵字去除重復記錄 select count(distinct deptno) from emp
WM_COUCAT行轉列(讓查詢結果行轉列)該函數可以把列值以 逗號 分隔起來,並顯示成一行。
Select wm_concat(ename) from emp
使用分組函數要注意空值的問題,分組函數會自動忽略空值,如果要空值的數據,可以用NVL函數
數據分組 GROUP BY
在select列表中的所有未包含在組函數中的列都應包含在group by子句中
正確寫法:select deptno,avg(sal) from emp group by deptno
錯誤寫法:select deptno,avg(sal) from emp
錯誤寫法:select deptno,job,avg(sal) from emp group by deptno
正確寫法:select deptno,job,avg(sal) from emp group by deptno,job
包含在group by子句中的列不必包含在select列表中
Select avg(sal) from emp group by deptno
Having子句 用於對分組后的結果進行過濾
Select deptno,avg(sal) from emp group by deptno having avg(sal)>2500 這里的having不能換成where
不能在where子句中使用組函數,可以在having子句中使用組函數。
分組函數嵌套時候需要配合group by子句一起使用
例子 select * max(avg(sal)) from emp group by deptno 如果沒有group by子句會報錯的
多表查詢和笛卡爾集
多表查詢顧名思義就是從多個表中獲取數據
笛卡爾集是集合的一種,它是數學上的概念。假設A和B都是集合,A和B的笛卡爾積用A*B來表示,那么A*B所形成的集合叫笛卡爾集。
Oracle多表查詢
等值連接,它是指使用等值比較符 = 指定連接條件的查詢
例子 select empno,ename,job,dname from emp,dept where emp.deptno=dept.deptno
例子 用表別名方式 select e.empno,e.ename,e.job,d.dname from emp e,dept d where e.deptno=d.deptno
在連接查詢中,當有多個連接條件時,使用AND指定其他條件
例子 select e.empno,e.ename,e.job,d.dname from emp e,dept d where e.deptno=d.deptno and e.deptno=10
不等值連接,它是指使用除等值比較符之外的其他比較操作符執行連接查詢
例子 select e.empno,e.ename,e.sal,s.grade from emp e,salgrade s where e.sal between losal and hisal
外連接是標准連接的拓展,它不僅會返回滿足連接條件的所有記錄,而且還會返回不滿足連接條件的部分記錄
外連接是用+操作符來完成的,分右外連接、左外連接
右外連接:SELECT table1.column, table2.column FROM table1,table2 WHERE table1.column(+)=table2.column
返回右邊表table2的全部記錄,包括不滿足條件的記錄。返回左邊table1滿足條件的記錄。
左外連接:SELECT table1.column, table2.column FROM table1,table2 WHERE table1.column=table2.column(+)
返回左邊表table1的全部記錄,包括不滿足條件的記錄。返回右邊table2滿足條件的記錄。
例子 select d.deptno,d.dname,count(e.empno) from dept d,emp e where d.deptno=e.deptno(+) group by d.deptno,d.dname
自連接是同一張的互相連接,實質是將同一張表看成是多張表
SQL:1999標准
SELECT table1.column_name, table2.column_name FROM table1
[CROSS JOIN table2]|[NATURAL JOIN table2]|[JOIN table2 USING (column_name)]|
[JOIN table2 ON (table1.column_name= table2.column_name)]|
[LEFT | RIGHT | FULL OUTER JOIN table2 ON (table1.column_name= table2.column_name)]
交叉連接
例子 select e.detpno,e.ename,d.deptno,d.dname from emp e cross join dept d
自然連接是一種特殊的等價連接,它將表中具有相同名稱的列自動進行記錄匹配。自然連接不必指定任何同等連接條件
例子 select table1.column_name,table2.column_name from table1 natural join table2
內連接,返回兩個表中想匹配的數據(只返回滿足條件的數據)
等值連接、非等值連接、自然連接都屬於內連接
用USING子句建立相等連接
例子 select e.ename,e.sal,d.dname from dept d join emp e using(deptno) 兩個表都有的列deptno
用ON子句建立相等連接
例子 select e.ename,e.sal,d.dname from dept d join emp e on e.deptno=d.deptno
左外連接、右外連接、完全外連接
例子 select e.ename,e.sal,d.dname from dept d left join emp e on e.deptno=d.deptno
例子 select e.ename,e.sal,d.dname from dept d right join emp e on e.deptno=d.deptno
例子 select e.ename,e.sal,d.dname from dept d full join emp e on e.deptno=d.deptno
Set運算符,並不是set這個符號,它是集合操作符,專門用於合並多條SELECT語句的結果。
有union/union all 並集 intersect 交集 minus 差集
例子 select deptno,empno,ename from emp1
union
select deptno,empno,ename from emp2
union all與union不同的是它不會取消重復行,並且不會對結果集數據進行排序
例子 select deptno,empno,ename from emp1
union all
select deptno,empno,ename from emp2
例子 select deptno,empno,ename from emp1
intersect
select deptno,empno,ename from emp2
例子 select deptno,empno,ename from emp1
minus
select deptno,empno,ename from emp2
子查詢
子查詢是指嵌套在其他SQL語句中的SELECT語句,也稱為嵌套查詢。
例子 select * from emp where job=(select job from emp where ename=’SMITH’)
一個主查詢可以有多個子查詢
例子 select * from emp where job=(select job from emp where empno=7521)
and sal>(select sal from emp where empno=7934)
執行順序,一般是先執行子查詢,再執行主查詢,但相關子查詢例外
什么是相關子查詢?
當子查詢需要引用主查詢到的表列時,ORACLE會執行相關子查詢,也就是先執行主查詢,再執行子查詢。
例子 select ename,sal,deptno from emp e where sal>(select avg(sal) from emp where deptno=e.deptno)
主查詢和子查詢可以不是同一張表
單行子查詢和多行子查詢,這個自己去體會,其實就是返回的是單行還是多行,另外知道它們各自的運算符。
子查詢需注意的問題:
- 不可以在group by子句中使用子查詢
- 在TOP-N分析問題中,須對子查詢排序
- 單行子查詢和多行子查詢中的空值問題
視圖
視圖是一個虛擬的表,它是建立在已有表的基礎上的,視圖賴以建立的這些表稱為基表。
使用視圖主要原因:1.安全原因,限制數據訪問 2.視圖可使復雜的查詢易於理解和使用
視圖分:簡單視圖、復雜視圖、連接視圖、只讀視圖
創建視圖語法格式:
CREATE [OR REPLACE] VIEW view_name [(alias[,alias]…)] alias是視圖列的別名
AS subquery
[WITH CHECK OPTION [CONSTRAINT constraint]] [WITH READ ONLY]
簡單視圖例子 create view emp_view as select empno,ename,sal from emp
連接視圖例子 create view dept_view as select d.deptno,d.dname,e.empno,e.ename,e.job
From dept d,emp e
Where d.deptno=e.deptno and d.deptno=10
只讀視圖例子 select view emp_view as select * from emp where deptno=10 with read only
視圖DML操作
Select * from emp_view
Insert into emp_view(empno,ename,sal)values(888.’LAYAN’,666)
Update emp_view set sal=sal+100 where empno=888
Delete from emp_view where empno=888
針對視圖的更新操作(insert、update、delete)實際改變的是基表中的數據
視圖定義CHECK約束
create view emp_view as select * emp where deptno=20 with check option constraint chk_view
以上代碼,如果去更新插入或刪除不是deptno=20的信息,會報錯提示違反了約束
修改視圖例子 create or replace view emp_view as select * from emp where job=’SALSMAN’
刪除視圖例子 drop view emp_view (只是刪除視圖的定義,並沒有刪除基表中的數據)
復雜視圖是指包括函數、表達式或分組數據的視圖,它主要用於執行查詢操作。
注意當定義復雜視圖時,必須要為函數或表達式定義列別名。
例子 create view job_view(job,avgsal,sumsal,maxsal,minsal)
As
select job,avg(sal),sum(sal),max(sal),min(sal) from emp group by job
復雜視圖執行DML操作原則:
視圖中包含以下元素之一不能執行delete操作:
- group by子句
- 分組函數
- distinct關鍵字
- rownum偽列
視圖中包含以下元素之一不能執行update操作:
- group by子句
- 分組函數
- distinct關鍵字
- rownum偽列
- 使用表達式定義的列
視圖中包含以下元素之一不能執行insert操作:
- group by子句
- 分組函數
- distinct關鍵字
- rownum偽列
- 使用表達式定義的列
- 視圖上沒有包含基表的not null列
序列、索引、同義詞
創建序列語法格式:
CREATE SEQUENCE sequence_name
[INCREMENT BY n] 每次增長的數值(步長)
[START WITH n] 從哪個值開始(初始值)
[{MAXVALUE n|NOMAXVALUE}]
[{MINVALUE n|NOMINVALUE}]
[{CYCLE|NOCYCLE}] 是否需要循環
[{CACHE n|NOCACHE}] 是否緩存
當使用序列時,必須通過偽列nextval和currval來引用序列。
例子 deptno_seq.nextval 引用返回下一個序列值
例子 deptno_seq.currval 引用返回當前序列值
查詢數據字典視圖 USER_SEQUENCES獲取序列定義信息
SELECT sequence_name,min_value,max_value,increment_by,cycle_flag,cache_size,last_number FROM user_sequences
注意在定義cache值,可提高訪問效率,但使用時在:回滾、系統異常、多個表同時使用同一序列等情況下出現跳號
修改序列語法格式:
ALTER SEQUENCE sequence_name
[INCREMENT BY n] 每次增長的數值(步長)
[{MAXVALUE n|NOMAXVALUE}]
[{MINVALUE n|NOMINVALUE}]
[{CYCLE|NOCYCLE}] 是否需要循環
[{CACHE n|NOCACHE}] 是否緩存
注意序列的初始值不能修改
刪除序列 DROP SEQUENCE sequence_name
索引是為了加速對表中數據行的檢索而創建的一種存儲結構。
按索引列的個數分類有:單列索引、復合索引
按索引列值的唯一性分類有:唯一索引、非唯一索引
在一個或多個列上創建索引
CREATE INDEX index_name ON table(column …)
單列索引例子 create index idx_ename on emp(ename)
復合索引例子 create index idx_deptno_job on emp(deptno,job)
唯一索引例子 create unique index idx_dname on dept(dname) dname列值不可重復
非唯一索引例子 create index idx_job on emp(job) job列值可以重復
刪除索引 drop index idx_dname
同義詞是數據庫方案對象的一個別名。
那什么是方案?方案對象比如表、索引、視圖、觸發器、序列、同義詞、存儲過程等
非方案對象比如表空間、用戶、角色等
同義詞分公共同義詞和私有同義詞
公共同義詞是指數據庫中所有的用戶都可以使用
私有同義詞只能被創建它的用戶所擁有,其他用戶在引用時必須帶有方案名
創建公共同義詞 CREATE PUBLIC SYNONYM synoym FOR [schema.]object
創建私有同義詞 CREATE SYNONYM synoym FOR [schema.]object
注:schema指方案名
例子 create public synonym dn for scott.deptnew 把scott用戶下的deptnew表創建其同義詞dn
select * from dn 就相當於查找scott用戶下的deptnew表
PL/SQL
PL/SQL是一種程序語言,叫做過程化SQL語言。它是ORACLE數據對SQL語言的擴展
PL/SQL是面向過程的語言,是對SQL語言的擴展
塊,是PL/SQL的基本程序單元
PL/SQL塊由三部分構成:聲明部分、執行部分、異常處理部分
DECLARE 聲明部分,聲明變量、常量、復雜數據類型、游標等
BEGIN 執行部分,PL/SQL語句和SQL語句
EXCEPTION 異常處理部分,處理運行錯誤
END 塊結束標記
打印輸出hello everyone
注意:當使用DBMS_OUPUT包輸出信息時,需要設置SQL*Plus環境serveroutput的值為ON
set serveroutput on
BEGIN
dbms_output.put_line(‘hello everyone’)
END
PL/SQL塊的分類:
匿名塊:動態構造、只能執行一次。
子程序:存儲在數據庫中的存儲過程、函數及包等。當在數據庫上建立好后可以在其它程序中調用它們。
觸發器:當數據庫發生操作時,會觸發一些事件,從而自動執行相應的程序。
標識符
當編寫PL/SQL塊時,為了臨時存儲數據,需要定義變量和常量。那么變量和常量的定義是需要滿足標識符的限制要求的:
- 標識符名不能超過30個字符
- 第一個字符必須為字母
- 不分大小寫
- 不能用’-’(減號)
注意:盡量不把變量名聲明和表中字段名一樣。
建議遵從下面編碼規則:
程序變量 v_name
程序常量 c_name
游標變量 name_curror
異常標識 e_name
記錄類型 name_record
注釋
單行注釋: --注釋內容 多行注釋: /*注釋內容*/
引用變量
在許多情況下,PL/SQL變量可以用來存儲在數據庫表中的數據。在這種情況下,變量應該擁有與表列相同的類型。
想一想,當用某個變量在定義和應用時候對應某表列的數據類型,如果這個表列數據類型變了,你還得去修改對應的這個變量,如果涉及的地方很多,煩不煩?
例子 DECLARE
v_name varchar2(10);
BEGIN
SELECT ename INTO v_name FROM emp WHERE empno=8888;
END;
emp表的ename列數據類型如果改變,那么定義的變量v_name也要隨着去改變
怎么才能讓其變量自動隨着其對應表列數據類型的改變而改變,這就是引用型變量、記錄型變量的作用。
引用型變量是指其數據類型與已經定義的某個數據變量的類型相同,或者與數據庫表的某個列的數據類型相同。
例子 v_name emp.ename%TYPE
這樣v_name就不關心其到底是什么數據類型,反正跟emp.ename一樣,你變我也變。emp.ename也可以放心的改變其數據類型,不會影響v_name
記錄型變量,PL/SQL提供%ROWTYPE操作符,返回一個記錄類型,其數據類型和數據庫表的數據結構相一致。
例子 emp_record emp%ROWTYPE
這樣emp_record對應emp表的數據結構,也就是說emp_record含有emp表所有的列,emp_record不必關心到底有多少個列,每個列是什么數據類型,反正跟emp表中的所有列一樣,你變我也變。Emp表也可以放心改變,因為不會影響emp_record
記錄型變量分量的引用 如:emp_record.ename:=’ROSE’
了解算術運算符、關系運算符、比較運算符、邏輯運算符
補充 := 是賦值意思 &n1 輸入值,其中n1是自定名稱
另外注意NULL:1.空值+數字=空值 2.空值 || 字符串1 還等於字符串1
PL/SQL流程控制語句分類:
- 條件控制語句 有IF條件語句和CASE條件 語句
- 循環語句 有基本循環LOOP語句、WHILE循環語句、FOR循環語句
- 順序語句 有GOTO語句和NULL語句
以上不做詳細介紹,說下特別的部分
嵌套循環是指一個循環語句中嵌入另一個循環語句。
標號用於標記嵌套塊或嵌套循環。
使用<<label_name>>定義標號
例子 DECLARE
v_result int
BEGIN
<<outter>>
FOR i IN 1..5 LOOP
<<inter>>
FOR j IN 1..5 LOOP
v_result:=i;
EXIT outter WHEN i=4;
END LOOP inter;
DBMS_OUTPUT.PUT_LINE(‘內’||v_result);
END LOOP outter;
DBMS_OUTPUT.PUT_LINE(‘外’||v_result);
END;
EXIT WHEN 是當滿足某條件時跳出循環
CONTINUE WHEN 是當滿足某條件時跳出當前循環,進入下一個循環
GOTO語句用於跳轉到特定標號處執行語句 如:GOTO lable_name (標號lable_name要在某處標識好)
注意:當使用GOTO跳轉到特定標號時,標號后至少要包含一條執行語句。
NULL語句不會執行任何操作,並且會直接將控制傳遞到下一個語句,使用該語句主要為了提高可讀性。
游標
游標是SQL的一個內存工作區,由系統或用戶以變量的形式定義。
游標的作用是用於臨時存儲從數據庫中提取的數據塊。
通俗來講游標就是一個結果集。
游標類型分為:顯示游標和隱式游標
顯示游標處理的四個步驟:
定義游標
CURSOR cursor_name[(parameter_name datatype)] IS select_statement
打開游標
OPEN cursor_name
提取數據
FETCH cursor_name INTO variable1[,variable2,… ]
關閉游標
CLOSE cursor_name
查詢所有員工的員工號、姓名和職位的信息
DECLARE
--定義游標
CURSOR emp_cursor IS SELECT empno,ename,job FROM emp
v_empno emp.empno%TYPE
v_ename emp.ename%TYPE
v_job emp.job%TYPE
BEGIN
--打開游標、執行查詢
OPEN emp_cursor
--提取數據
LOOP
FETCH emp_cursor INTO v_empno,v_ename,v_job
dbms_output.put_line(‘員工號:’|| v_empno || ‘姓名:’ || v_ename || ‘職位:’ || v_job)
--當找不到數據的時候退出
EXIT WHEN emp_cursor%NOTFOUND
END LOOP
--關閉游標
CLOSE emp_cursor
END
顯示游標的屬性
%FOUND 該屬性用於檢測游標結果集是否存在數據,如果存在數據,返回TRUE
%NOTFOUND 該屬性用於檢測游標結果集是否不存在數據,如果不存在數據,返回TRUE
%ISOPEN 該屬性用於檢測游標是否已經打開,如果已經打開返回TRUE
%ROWCOUNT 該屬性用於返回已提取的實際行數
按職工的職稱漲工資,總裁漲1000元,經理漲500元,其他員工漲300元
DECLARE
--定義游標
CURSOR empnew_cursor IS SELECT empno,job FROM empnew
v_empno empnew.empno%TYPE
v_job empnew.job%TYPE
BEGIN
--打開游標、執行查詢
OPEN empnew_cursor
--提取數據
LOOP
FETCH empnew_cursor INTO v_empno ,v_job
IF v_job=’president’ THEN
UPDATE empnew SET sal=sal+1000 WHERE empnew=v_empno
ELSIF v_job=’manager’ THEN
UPDATE empnew SET sal=sal+500 WHERE empnew=v_empno
ELSE
UPDATE empnew SET sal=sal+300 WHERE empnew=v_empno
END IF
EXIT WHEN empnew_cursor%NOTFOUND
END LOOP
COMMIT
--關閉游標
CLOSE empnew_cursor
END
當使用游標FOR循環時,ORACLE會隱含地打開游標,提取數據並關閉游標
語法格式:
FOR record_name IN cursor_name LOOP
Statement
END LOOP
查詢所有員工的員工號、姓名和職位的信息
DECLARE
CURSOR emp_cursor IS SELECT empno,ename,job FROM emp
BEGIN
FOR emp_record IN emp_cursor LOOP
dbms_output.put_line(‘員工號:’|| emp_record.empno || ‘姓名:’ || emp_record.ename || ‘職位:’ || emp_record.job)
END LOOP
END
可以改進下
BEGIN
FOR emp_record IN (SELECT empno,ename,job FROM emp) LOOP
dbms_output.put_line(‘員工號:’|| emp_record.empno || ‘姓名:’ || emp_record.ename || ‘職位:’ || emp_record.job)
END LOOP
END
參數游標是指帶有參數的游標。通過使用參數游標,使用不同參數值可以生成不同的游標結果集。
語法格式:
CURSOR cursor_name (parameter_name datatype) IS select_statement
OPEN cursor_name (parameter_value)
參數游標例子
DECLARE
CURSOR emp_cursor(dno NUMBER) IS SELECT empno,ename,job FROM emp WHERE deptno=dno
BEGIN
FOR emp_record IN emp_cursor(&no) LOOP
dbms_output.put_line(‘員工號:’|| emp_record.empno || ‘姓名:’ || emp_record.ename || ‘職位:’ || emp_record.job)
END LOOP
END
顯示游標是用戶自定義的顯示創建的游標,主要是用於對查詢語句的處理。
隱式游標是由系統隱含創建的游標。主要用於對非查詢語句,如修改,刪除等操作,則有ORACLE系統自動地為這些操作設置游標並創建其工作區,對於隱式游標的操作,如定義、打開、取值及關閉操作,都有ORACLE系統自動完成,無需用戶進行處理。
隱式游標的名字為SQL,這是由ORACLE系統定義的。
隱式游標DML操作和單行SELECT語句會使用隱式游標,它們是:
插入操作 insert
更新操作 update
刪除操作 delete
單行查詢操作 select…into
當系統使用一個隱式游標時,可以通過隱式游標的屬性來了解操作的狀態和結果,進而控制程序的流程。
注意:通過SQL游標名總是只能訪問前一個DML操作或單行SELECT操作的游標屬性。
隱式游標屬性: SQL%FOUND SQL%NOTFOUND SQL%ISOPEN SQL%ROWCOUNT
為了對正在處理(查詢)的行不被另外的用戶改動,oracle提供一個for update子句來對所選擇的行進行鎖住。
如果創建的游標需要執行更新或刪除的操作必須帶有for update子句
FOR UPDATE子句會將游標提取出來的數據進行行級鎖定,這樣在本會話更新期間,其他用戶的會話就不能對當前游標中的數據行進行更新操作。
語法格式:
CURSOR cursor_name IS select_statement
FOR UPDATE [OF column_reference] [NOWAIT]
UPDATE table_name SET column=… WHERE CURRENT OF cursor_name
DELETE FROM table_name WHERE CURRENT OF cursor_name
異常處理
異常處理是為了提高程序的健壯性,使用異常處理部分可以有效地解決程序正常執行過程中可能出現的各種錯誤,是程序正常運行。
異常處理語法格式:
EXCEPTION
WHEN first_exception THEN
Statement1 …
WHEN second_exception THEN
Statement2 …
WHEN OTHERS THEN
Statement3 …
異常處理的分類:
- 預定義異常 2.非預定義異常 3.自定義異常
異常處理代碼的PL/SQL塊中的位置
DECLARE 聲明部分—聲明變量、常量、復雜數據類型、游標等
BEGIN 執行部分—PL/SQL語句
EXCEPTION 異常處理部分—處理運行錯誤
END 塊結束標記
預定義異常是指有PL/SQL所提供的系統異常,oracle提供了20多個預定義異常,每個預定義異常對應一個特定的oracle錯誤,當PL/SQL塊出現這些oracle錯誤時,會隱含地觸發相應的預定義異常。
對於預定義異常情況的處理,無需在程序中定義,只需在PL/SQL塊的異常處理部分,直接引用相應的異常情況名,並對其完成相應的異常錯誤處理即可。
例子:根據輸入的工資,查詢員工的姓名,並輸出員工的姓名及工資
分析:1.輸入工資,需要替代變量&salary
2.根據工資查詢員工的姓名,並將查詢到的姓名賦值給姓名變量。數據庫賦值需要用到SELECT…INTO
3.考慮一些特殊情況,如沒有該工資的員工,該工資有多個員工
DECLARE
v_name emp.ename%TYPE;
v_sal emp.sal%TYPE:=&salary;
BEGIN
SELECT ename INTO v_name FROM emp WHERE sal=v_sal;
DBMS_OUTPUT.PUT_LINE(v_name||’的工資是:’||v_sal);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘沒有該工資的員工’);
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE(‘多個員工具有該工資’);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘其他異常’);
END;
非預定義異常用於處理預定義異常所不能處理的oracle錯誤,此種異常需要在程序中定義。
非預定義異常的處理包括3步:
1.在PL/SQL塊定義部分定義異常情況
<異常情況>EXCEPTION;
2.將其定義好的異常情況與標准的oracle錯誤聯系起來,使用PRAGMA EXCEPTION_INIT語句
PRAGMA EXCEPTION_INIT(<異常情況>,<錯誤代碼>);
3.在PL/SQL塊的異常情況處理部分對異常情況作出相應的處理。
例子 刪除dept表中指定部門的信息
分析 dept和emp表之間具有主外鍵關系,當刪除指定部門的信息時,應確保該部門下沒有員工。
先獲得其錯誤代碼—此處略
DECLARE
--1.定義非預定義異常的標識符
e_fk EXCEPTION;
--2.把oracle錯誤與異常建立關聯
PRAGMA EXCEPTION_INIT(e_fk,-2292);
BEGIN
DELETE FROM dept WHERE deptno=&deptno;
EXCEPTION
WHEN e_fk THEN
--3.捕捉並處理異常
DBMS_OUTPUT.PUT_LINE(‘此部門下有員工,不能刪除’);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLCODE||’###’||SQLERRM);
END;
自定義異常
如果你想在某個特定事件發生時向應用程序的用戶發出一些警告信息。而事件本身不會拋出oracle內部異常,這個異常是屬於應用程序特定異常。那么就需要自定義異常。
用戶定義的異常錯誤是通過顯式使用RAISE語句來觸發。當引發一個異常錯誤時,控制就轉向到EXCEPTION塊異常錯誤部分,執行錯誤處理代碼。
自定義異常的處理步驟:
1.在PL/SQL塊的聲明部分定義異常情況:
<異常情況>EXCEPTION
2.RAISE<異常情況>
3.在PL/SQL塊的異常情況處理部分對異常情況做出相應的處理
DECLARE
v_empno emp.empno%TYPE:=&empno;
e_no_result EXCEPTION;
BEGIN
UPDATE emp SET sal=sal+100 WHERE empno=v_empno;
IF SQL%NOTFOUND THEN
RAISE e_no_result;
ELSE
COMMIT;
END IF;
EXCEPTION
WHEN e_no_result THEN
DBMS_OUTPUT.PUT_LINE(‘數據更新失敗’);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘其他錯誤’);
END;
異常處理函數
異常處理函數用於取得oracle錯誤號和錯誤信息,其中函數SQLCODE用於取得錯誤號,SQLERRM用於取得錯誤信息。當編寫PL/SQL塊時,通過在異常處理部分引用函數SQLCODE和SQLERRM,可以取得未預計到的oracle錯誤。另外,通過使用內置過程RAISE_APPLICATION_ERROR,可以在建立子程序(過程、函數、包)時自定義錯誤號和錯誤信息。
例子:
DECLARE
v_empno emp.empno%TYPE:=&empno;
v_ename emp.ename%TYPE:=’&ename’;
v_deptpno emp.deptpno%TYPE:=&deptpno;
BEGIN
INSERT INTO emp(empno,ename,deptno) VALUES(v_empno, v_ename, v_deptpno);
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘數據插入成功’);
COMMIT;
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘錯誤號:’||SQLCODE);
DBMS_OUTPUT.PUT_LINE(‘錯誤信息:’||SQLERRM);
END;
RAISE_APPLICATION_ERROR語法格式:
raise_application_error(error_number,message);
error_number用於定義錯誤號(-20000到-20999)
messag用於指定錯誤信息,長度不能超過2048個字節
例子:
CREATE OR REPLACE PROCEDURE change_sal (eno NUMBER,salary NUMBER)
IS
BEGIN
UPDATE emp SET sal=salary WHERE empno=eno;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20000,’該員工不存在’);
ELSE
DBMS_OUTPUT.PUT_LINE(‘更新成功’);
COMMIT;
END IF;
END;
存儲過程與存儲函數
創建存儲過程的語法格式:
CREATE [OR REPLACE] PROCEDURE procedure_name
[( argment1 [ {IN|OUT|IN OUT}] TYPE,
argment2 [ {IN|OUT|IN OUT}] TYPE,…)]
{ IS|AS }
聲明部分,類型、變量的說明
BEGIN
執行部分
EXCEPTION
可選的異常錯誤處理部分
END
例子:創建帶有輸入參數的存儲過程(代碼中沒有COMMIT命令,存儲一般是用來調用的,所以沒有啦)
CREATE OR REPLACE PROCEDURE proc1
(v_empno IN empnew.empno%TYPE)
IS
BEGIN
--根據員工號刪除指定的員工信息
DELETE FROM empnew WHERE empno=v_empno;
--判斷是否刪除成功
IF SQL%NOTFOUND THEN
--錯誤號在-20000到-20999之間
RAISE_APPLICATION_ERROR(-20008,’指定刪除的員工不存在’);
ELSE
DBMS_OUTPUT.PUT_LINE(‘刪除成功’);
END IF;
END;
例子:再創建帶有輸出參數的存儲過程
CREATE OR REPLACE PROCEDURE proc2
(v_deptno IN NUMBER, v_avgsal OUT NUMBER, v_cnt OUT NUMBER)
IS
BEGIN
SELECT AVG(sal),COUNT(*)
INTO v_avgsal,v_cnt
FROM emp
WHERE deptno=v_deptno;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘沒有此部門’);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
例子:創建帶有輸入輸出的存儲過程
CREATE OR REPLACE PROCEDURE proc3
(v_num1 IN OUT NUMBER, v_num2 IN OUT NUMBER)
AS
v_temp NUMBER:=0;
BEGIN
v_temp:=v_num1;
v_num1:=v_num2;
v_num2:=v_temp;
END;
創建存儲函數的語法格式:
CREATE [OR REPLACE] FUNCTION procedure_name
[( argment1 [ {IN|OUT|IN OUT}] TYPE, argment2 [ {IN|OUT|IN OUT}] TYPE,…)]
RETURE datatype
{ IS|AS }
聲明部分,類型、變量的說明
BEGIN
執行部分
RETURE datatype
EXCEPTION
可選的異常錯誤處理部分
END
例子:根據您部門編號返回該部門的總工資
CREATE OR REPLACE FUNCTION func1
(v_deptno IN NUMBER)
RETURE NUMBER
IS
v_sumsal NUMBER;
BEGIN
SELECT SUM(sal) INTO v_sumsal FROM emp WHERE deptno=v_deptno;
RETURE v_sumsal;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘沒有此部門’);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
例子:根據員工號輸出員工的姓名和工資,並返回員工的年收入
CREATE OR REPLACE FUNCTION func2
(v_empno IN emp.empno%TYPE, v_name OUT emp.ename%TYPE, v_sal OUT emp.sal%TYPE)
RETURE NUMBER
IS
v_salsum NUMBER;
BEGIN
SELECT ename,sal,(sal+nvl(comm,0))*12
INTO v_name,v_sal,v_salnum
FROM emp
WHERE deptno=v_deptno;
RETURE v_salsum;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘沒有此員工’);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
例子:求兩個數的平方,並輸出兩個數的平方和
CREATE OR REPLACE FUNCTION func3
(n1 IN OUT NUMBER, n2 IN OUT NUMBER)
RETURE NUMBER
AS
BEGIN
n1:=n1*n1;
n2:=n2*n2;
RETURE n1+n2
END;
存儲過程的調用
一種是使用EXECUTE語句來實現
EXECUTE procedure_name (parameter1, parameter2…)
另外一種就是在PL/SQL代碼中直接調用
BEGIN
procedure_name (parameter1, parameter2…)
END
刪除存儲過程
DROP PROCEDURE [user.]procedure_name
調用存儲函數也調用存儲過程一毛一樣,不再啰嗦了,因為他們真的差不多,是否他們區別就在於是否有返回值?
包
包是一組相關過程、函數、變量、常量和游標等PL/SQL程序設計元素的組合。
它具有面向對象程序設計語言的特點,是對PL/SQL程序設計元素的封裝,它使程序設計模塊化。
包中的程序元素分為,公用元素和私用元素
包由兩部分組成:包規范和包體
包規范,用於定義包的公用元素,包括常量、變量、游標、過程、函數等
包體,用於實現包規范所定義的公用過程和函數。包體不僅用於實現公用過程和函數,還可定義私用元素。
包規范語法格式:
CREATE [OR REPLACE] PACKAGE package_name
IS|AS
--定義公用常量、變量、游標、過程、函數等
END [package_name]
包體語法格式:
CREATE [OR REPLACE] PACKAGE BODY package_name
IS|AS
--定義私有常量、變量、游標、過程、函數等
--實現公有過程和函數
END [package_name]
例子:
--創建包規范
CREATE OR REPLACE PACKAGE first_package
IS
v_no emp.deptno%TYPE:=10;
--過程
PROCEDURE query_emp(v_deptno IN NUMBER DEFAULT v_no, v_avgsal OUT NUMBER, v_cnt OUT NUMBER);
END first_package;
--創建包體
CREATE OR REPLACE PACKAGE BODY first_package
IS
PROCEDURE query_emp(v_deptno IN NUMBER DEFAULT v_no, v_avgsal OUT NUMBER, v_cnt OUT NUMBER);
IS
BEGIN
SELECT AVG(sal),COUNT(*)
INTO v_avgsal,v_cnt
FROM emp
WHERE deptno=v_deptno;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘沒有此部門’);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
--調用
DECLARE
v_avgsal NUMBER;
v_cnt NUMBER;
BEGIN
First_package.query_emp(20,v_avgsal,v_cnt);
DBMS_OUTPUT.PUT_LINE(‘平均工資’||v_avgsal);
DBMS_OUTPUT.PUT_LINE(‘總人數’||v_cnt);
END;
那么包的調用或刪除、子程序重載等,我就發發懶不做詳細介紹了,希望你能觸類旁通,舉一反三
觸發器
觸發器是指存放在數據庫中,並且被隱含執行的存儲過程。
當發生特定事件時,oracle會自動執行觸發器的相應代碼。
觸發器類型:
- DML觸發器
- DDL觸發器
- 替代觸發器
- 系統觸發器
觸發器的組成
- 觸發事件:即在何種情況下觸發TRIGGER
- 觸發時間:即該TRIGGER是在觸發事件發生之前還是之后觸發
- 觸發器本身:即該TRIGGER被觸發之后的目的和意圖,正是觸發器本身要做的事情
- 觸發頻率:說明觸發器內定義的動作被執行的次數
DDL觸發器
當創建、修改或刪除數據庫對象時,也會引起相應的觸發器操作事件,而此時就可以利用觸發器來對這些數據庫對象的DDL操作進行監控。
創建DDL觸發器的語法格式:
CREATE [OR REPLACE] TRIGGER 觸發器的名稱
[BEFORE | AFTER | INTEAD OF] [DDL事件] ON [DATABASE | SCHEMA]
[WHEN觸發條件]
[DECLARE]
[程序的聲明部分]
BEGIN
程序的代碼部分
END
例子:禁止scott用戶的DDL操作
CREATE OR REPLACE TRIGGER scott_trigger
BEFORE DDL
ON SCHEMA
BEGIN
RAISE_APPLICATION_ERROR(-20005,’scott用戶禁止使用所有的DDL操作’)
END
RAISE_APPLICATION_ERROR是用來測試的異常處理。
RAISE_APPLICATION_ERROR是將應用程序專有的錯誤從服務器端傳達到客戶端應用程序
例子:實現對數據庫對象操作的日志記錄
先創建記錄操作的日志表
create table object_log
(logid number constraint pk_logid primary key,
operatedate date not null,
objecttype varchar2(50) not null,
objectowner varchar2(50) not null)
再給表創建一個序列
create sequence object_log_seq
創建觸發器
create or replace trigger object_trigger
after create or drop or alter
on database
begin
insert into object_log(logid, operatedate, objecttype, objectowner)
values(object_log_seq.nextval,sysdate,ORA_DICT_OBJ_TYPE, ORA_DICT_OBJ_OWNER)
end
DDL觸發器事件的屬性函數
ORA_DICT_OBJ_TYPE 觸發DDL的數據庫對象的類型
ORA_DICT_OBJ_OWNER 觸發DDL的數據庫對象的用戶
DML觸發器是指基於DML操作所建立的觸發器。
DML觸發器作用可用於實現數據安全保護、數據審計、數據完整性、參照完整性、數據復制等功能。
DML觸發器類型分:語句觸發器和行觸發器
語句觸發器:在指定的操作語句語句之前或之后執行一次,不管這條語句影響了多少行。
行觸發器:觸發語句作用的每一條記錄都被觸發,在行級觸發器中使用 :old 和:new 偽記錄變量,識別值的狀態。
:old表示操作該行之前,這一行的值
:new表示操作該行之后,這一行的值
創建DML觸發器的語法格式:
CREATE [OR REPLACE] TRIGGER 觸發器的名稱
{BEFROE | AFTER}
{DELETE | INSERT | UPDATE [OF列名]}
ON 表名
[FOR EACH ROW [WHEN(條件)]] --行級觸發器
PL/SQL塊
例子1,實現數據安全保護:禁止在休息日改變emp表的數據
分析:時間,to_char(sysdate,’day’)
采用語句觸發器
CREATE OR REPLACE TRIGGER emp_trigger
BEFORE INSERT OR UPDATE OR DELETE
ON emp
BEGIN
IF to_char(sysdate,’day’) IN (‘星期六’,’星期日’) THEN
RAISE_APPLICATION_ERROR(-20006,’不能在休息日改變員工信息’);
END IF;
END;
例子2,實現數據審計功能:審計員工信息表數據的變化,審計刪除時間,以及被刪除的雇員名。
CREATE TABLE delete_emp_audit(name VARCHAR2(10), delete_time DATE)
CREATE OR REPLACE TRIGGER del_emp_trigger
AFTER DELETE ON emp
FOR EACH ROW
BEGIN
INSERT INTO delete_emp_audit VALUES(:old.ename, SYSDATE);
END
例子3,實現數據完整性:要求員工漲后工資不能低於原來工資,並且所漲的工資不能超過原工資的50%
CREATE OR REPLACE TRIGGER tr_check_sal
BEFORE UPDATE OF sal ON emp
FOR EACH ROW
WHEN (new.sal<old.sal OR new.sal>old.sal*1.5 )
BEGIN
RAISE_APPLICATION_ERRORR(-20028,’工資只升不降,並且升幅不能超過50%’);
END;
例子4,實現參照完整性:級聯更新dept表的主鍵列以及emp表的外部鍵列
參照完整性是指在兩張表之間具有主從關系。
為了實現級聯刪除,可以在定義外部鍵約束時指定ON DELETE CASCADE關鍵字。
但使用約束卻不能實現級聯更新,為了實現級聯更新,需要使用觸發器。
CREATE OR REPLACE TRIGGER upd_cascade_trigger
AFTER UPDATE OF deptno
ON dept
FOR EACH ROW
BEDIN
UPDATE emp SET deptno=:new.deptno WHERE deptno=:old.deptno;
END;
替代觸發器適用於視圖上的一種觸發器。
在簡單視圖上往往可以執行INSERT、UPDATE、DELETE操作。但在復雜視圖上執行這些操作是有限制的。
為了在這些復雜視圖上執行這些操作,需要建立替代觸發器。
替代觸發器的限制:
替代觸發器只適用於視圖
替代觸發器不能指定BEFORE和AFTER選項
不能在具有WITH CHECK OPTION選項的視圖上建立替代觸發器
替代觸發器必須包含FOR EACH ROW選項
例子:
CREATE OR REPLACE VIEW emp_dept
AS
SELECT d.deptno,d.dname,e.empno,e.ename FROM dept d,emp e WHERE d.deptno=e.deptno
CREATE OR REPLACE TRIGGER instead_of_trigger
INSTEAD OF
INSERT
ON emp_dept
FOR EACH ROW
DECLARE
v_temp INT;
BEGIN
SELECT COUNT(*) INTO v_temp FROM dept WHERE deptno=:new.deptno;
IF v_temp=0 THEN
INSERT INTO dept(deptno,dname)VALUES(:new.deptno,:new.dname);
END IF;
SELECT COUNT(*) INTO v_temp FROM emp WHERE empno=:new.empno;
IF v_temp=0 THEN
INSERT INTO emp(empno,ename,deptno)VALUES(:new.empno,:new.ename,:new.deptno);
END IF;
END;
系統觸發器是有特定系統事件所觸發的觸發器。
系統事件是指與例程或方案相關的數據事件,他包括STARTUP、SHUTDOWN、DB_ROLE_CHANGE 和 SERVERERROR
STARTUP事件觸發器在啟動數據庫后觸發
SHUTDOWN事件觸發器在關閉數據庫之前觸發
DB_ROLE_CHANGE事件觸發器在改變角色后第一次打開數據庫時觸發
SERVERERROR事件觸發器在發生oracle錯誤時觸發
例子:
CREATE TABLE event_table(event VARCHAR2(50),event_time date)
CREATE OR REPLACE TRIGGER startup_trigger
AFTER STARTUP NO DATABASE
BEGIN
INSERT INTO event_table VALUES(ora_sysevent,SYSDATE);
END;
好了,小人物不才,粗粗過了一遍,希望對您有用!
