1. 程式人生 > >oracle進階實戰筆記

oracle進階實戰筆記

本文包含以下內容:
1、Oracle PL/SQL使用
2、Oracle中的5種約束條件(非空約束、唯一約束、主鍵約束、外來鍵約束、check約束)
3、oracle單引號、雙引號區別(OTL程式設計時不注意會經常犯錯)
5、事務
6、系統日期&系統時間
7、序列
8、儲存過程
9、函式

1. Oracle PL/SQL使用

【簡介】
PL/SQL是在oracle裡面的程式語言,用來寫儲存過程、觸發器、函式等等。
PL/SQL語言是SQL的補充。SQL沒有分支,沒有迴圈,是第四代程式語言,非過程的,只要求得結果。

【注意】

必須先執行set serveroutput on 才能看到輸出。
執行set serveroutput on以後能導致 SQL*Plus檢索和顯示buffer。

“/”表示執行,相當於輸入了run;

【舉例】

SQL> set serveroutput on
SQL> declare
2 v_sal number(6,0);
3 begin
4 v_sal := 6600;
5 if (v_sal < 2500) then
6 v_sal := v_sal * 2;
7 dbms_output.put_line('sal < 2500 ' || v_sal);
8 elsif (v_sal > 2500) then
9 v_sal := v_sal / 2;
10 dbms_output.put_line('sal > 2500 '
|| v_sal); 11 else 12 dbms_output.put_line('sal = 2500 ' || v_sal); 13 end if; 14 end; 15 / sal > 2500 3300 PL/SQL procedure successfully completed.

常用變數型別:
1)binary_integer:整數,主要用來計數而不是用來表示欄位型別
2)number:數字型別
3)char:定長字串
4)varchar2:變長字串
5)date:日期
6)long:長字串,最長2GB
7)boolean:布林型別,可以取值為true、false和null值(建議boolean型別在宣告時給初值,否則就是空值)

變數宣告的規則:
1)變數名不能夠使用保留字,如from、select等
2)第一個字元必須是字母
3)變數名最多包含30個字元
4)不要與資料庫的表或者列同名
5)每一行只能宣告一個變數

說明:
1)constant相當於Java裡面的final,常量; C++中的const, 常量。
2)“||”是字串連線符。
3)dbms_output.put_line不能列印布林型別的值。

//迴圈
SQL> declare
2 i binary_integer := 1;
3 begin
4 loop
5 dbms_output.put_line(i);
6 i := i + 1;
7 exit when (i >= 9);
8 end loop;
9 end;
10 /
1
2
3
4
5
6
7
8

PL/SQL procedure successfully completed.

【總結】
PL/SQL寫程式非常的固定:
[DECLARE]
–宣告部分,可選。宣告各種變數遊標
BEGIN
–執行部分,必須。從這兒開始,程式開始執行
[EXCEPTION]
–異常處理部分,可選。相當於catch到exception時執行的東西
END;
–結束,end後要有分號

–eg:最簡單的語句塊

begin
dbms_output.put_line(‘Hello World!’);
end;
/

2.Oracle中的5種約束條件

oracle中對錶有五種約束條件
非空(not null)約束
唯一(unique)約束
主鍵(primary key)約束
外來鍵(foreign key)約束
check約束

2.1 非空約束

create table TT (
id number(3) not null,
name varchar2(100) constraint TT_NAME_NN not null
);

2.2 唯一性約束

1)、唯一約束要求被約束的列或列的組合值是唯一的,不能有兩個相同值存在。
2)、唯一約束可以定義在列級也能定義在表級。表級可以定義欄位的組合。
3)、唯一約束允許空值,因為空值不等於任何值。
4)、組合欄位的唯一約束,只要欄位的組合不完全一樣就可以插入表。
create table TT (
id number(3),
name varchar2(100),
constraint TT_ID_NAME_UK unique (id, name)
);

SQL> select owner, constraint_name, constraint_type, table_name from user_constraints where table_name='TT';

OWNER
--------------------------------------------------------------------------------
CONSTRAINT_NAME C TABLE_NAME
------------------------------ - ------------------------------
SYSTEM
SYS_C007178 C TT

SYSTEM
TT_NAME_NN C TT

違反唯一性插入舉例:
SQL> drop table TT;
Table dropped.

//建立
SQL> SQL> create table TT (
2 id number(3),
3 name varchar2(100),
4 constraint TT_ID_NAME_UK unique (id, name)
5 );
Table created.

//插入
SQL> insert into TT values(1, ‘aaaa’);
1 row created.

//插入
SQL> insert into TT values(1, ‘bbbb’);
1 row created.

//再次重複插入,報錯!
SQL> insert into TT values(1, ‘aaaa’);
insert into TT values(1, ‘aaaa’)
*
ERROR at line 1:
ORA-00001: unique constraint (SYSTEM.TT_ID_NAME_UK) violated

2.3主鍵

**通過主鍵可以找到唯一一行與之對應的記錄。
1)、一個表只能有一個主鍵約束。
2)、單一主鍵定義在列級,組合主鍵定義在表級。
3)、主鍵不允許空值,不允許出現重複值。
SQL> CREATE TABLE TB_PK_EXAMPLE( ID number, NAME varchar2(50), DESCRIPTION varchar2(300), CONSTRAINT TB_PK_EXAMPLE_PK PRIMARY KEY(ID));
Table created.

//插入一行資料
SQL> insert into TB_PK_EXAMPLE values(1, ‘laoyang’, ‘testing’);
1 row created.

//插入一行資料,ID相同,違反主鍵約束,會報錯。
SQL> insert into TB_PK_EXAMPLE values(1, ‘zhang’, ‘testing’);
insert into TB_PK_EXAMPLE values(1, ‘zhang’, ‘testing’)
*
ERROR at line 1:
ORA-00001: unique constraint (SYSTEM.TB_PK_EXAMPLE_PK) violated

2.4外來鍵

1)一個表的外來鍵必須是,另一個表的主鍵或唯一鍵。
2) 外來鍵可以為空值,一個外來鍵值必須匹配一個在父表中存在的值或者空值。
3) 外來鍵可以定義在表級(單列),列級(單列或列的組合)。
4) 外來鍵必須指向父表的PK欄位或UK欄位。

//建立表
SQL> create table tb_supplier
2 (
3 supplier_id number not null,
4 supplier_name varchar2(50) not null,
5 contact_name varchar2(50),
6 CONSTRAINT pk_supplier PRIMARY KEY (supplier_id)
7 );

Table created.

//建立表
SQL> create table tb_products
2 (
3 product_id number not null,
4 product_name varchar2(100),
5 supplier_id number not null,
//外來鍵約束
//
6 constraint fk_products_supplier foreign key (supplier_id) references tb_supplier(supplier_id)
7 );

Table created.

2.5 Check約束

check約束定義了一個每行都必須滿足的條件,類似與在插入資料時,對資料做了一個where過濾。
舉例如下:
SQL> CREATE TABLE tb_age (age NUMBER(3));
Table created.
//限定年齡的範圍【0,125】
SQL> ALTER TABLE tb_age ADD CONSTRAINT ck_temp_age CHECK((AGE>0) AND (AGE <= 125));
Table altered.
//在給定範圍內可以插入。
SQL> insert into tb_age values(33);
1 row created.

//超出範圍內的兩個測試值-1, 126都會報錯。
SQL> insert into tb_age values(126);
insert into tb_age values(126)
*
ERROR at line 1:
ORA-02290: check constraint (SYSTEM.CK_TEMP_AGE) violated

SQL> insert into tb_age values(-1);
insert into tb_age values(-1)
*
ERROR at line 1:
ORA-02290: check constraint (SYSTEM.CK_TEMP_AGE) violated

3.Oracle雙引號&單引號區別

1.雙引號的作用:
關鍵字,物件名、欄位名加雙引號,則示意 Oracle將嚴格區分大小寫,否則Oracl都預設大寫。

2.單引號的作用:
1)引用一個字串常量,也就是界定一個字串的開始和結束。
2)轉義符,對緊隨其後出現的字元(單引號)進行轉義。
3) 表示它本身,也就是它作為一個字串的一部分而出現在一個字串常量中,這點與2密不可分。

eg:

SQL> select sysdate from dual;

SYSDATE
------------------
18-APR-16

//以下則表示字串
SQL> select 'sysdate' from dual;

'SYSDAT
-------
sysdate

4.group by & count使用
1)、分組的實質就是一行(或多行)中的某一列(或多列)具有相同值。

2)、組是非空的,如果分組成功,組至少包含一個成員(或行)。

3)、組是獨特的,意味著,當查詢中使用group by時,select列表中就不必使用distinct關鍵字。

4)、當針對非空表的查詢(包含group by)中使用聚集函式count時,它絕對不會返回0。至少會返回一個非0//建立表

SQL> create table fruits (name varchar2(10));
Table created.

//插入資料
SQL> insert into fruits values ('Oranges');
1 row created.

SQL> insert into fruits values ('Oranges');
1 row created.

SQL> insert into fruits values ('Oranges');
1 row created.

SQL> insert into fruits values ('Apple');
1 row created.

SQL> insert into fruits values ('Peach');
1 row created.

SQL> insert into fruits values (null);
1 row created.

SQL> insert into fruits values (null);
1 row created.

SQL> insert into fruits values (null);
1 row created.

SQL> insert into fruits values (null);
1 row created.

SQL> insert into fruits values (null);
1 row created.

//分組查詢1
SQL> select name, count(name) from fruits group by name;
NAME COUNT(NAME)
---------- -----------
0
Oranges 3
Apple 1
Peach 1

//分組查詢2
SQL> select name, count(*) from fruits group by name;
NAME COUNT(*)
---------- ----------
5
Oranges 3
Apple 1
Peach 11&分組查詢2對比表明:
count(name)會忽略列的空值行,count(*)不會忽略空值行。

4.Oracle字符集

SQL> select userenv('language') from dual;
USERENV('LANGUAGE')
----------------------------------------------------
AMERICAN_AMERICA.AL32UTF8

//oracle安裝的宿主機查詢
[[email protected] rc.d]# echo $NLS_LANG
AMERICAN_AMERICA.AL32UTF8

oracle環境變數中的NLS_LANG是定義客戶端的字符集。
比如環境變數NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
但是資料庫三個例項的字符集可以分別是:
AMERICAN_AMERICA.AL32UTF8、
AMERICAN_AMERICA.WE8ISO8859P1、
AMERICAN_AMERICA.ZHS16GBK。

5、事務

事務會把資料庫從一種一致狀態轉變為另一種一致狀態,這就是事務的任務。

oracle的事務提供了ACID特徵:

原子性(atomicity):事務中的所有動作要麼都發生,要麼都不發生。

一致性(consistency):事務將資料庫從一種一致狀態轉變為下一種一致狀態。

隔離性(isolation):一個事務的影響在該事務提交前對其他事務都不可見。

永續性(durability):事務一旦提交,其結果就是永久性的。

其中最重要的特性是它的原子性。

一定要顯式地使用commit或rollback來終止你的事務。commit:commit會結束你的事務,並使得已做的所有修改成為永久性的(持久儲存)。

6、系統日期、系統時間操作

//系統日期

SQL> create table tb_date(x date);



Table created.


SQL> insert into tb_date values(sysdate);


1 row created.


SQL> select * from tb_date;


X
------------------
18-APR-16

//系統時間

SQL> create table tb_time(stamp timestamp);



Table created.


SQL> insert into tb_time values(sysdate);


1 row created.


SQL> insert into tb_time values(systimestamp);


1 row created.


SQL> select * from tb_time;


STAMP
---------------------------------------------------------------------------
18-APR-16 02.11.57.000000 PM
18-APR-16 02.12.03.242952 PM

擷取時間舉例(擷取年份):

SQL> select trunc(sysdate,'YYYY') from dual;
TRUNC(SYSDATE,'YYY
------------------
01-JAN-16

7、序列

序列(sequence)是oracle資料庫物件中的一個,每次使用時它會自動增加(或減少)。

//建立序列

SQL> create sequence seq1
2 increment by 1
3 start with 1
4 maxvalue 999999
5 minvalue 1
6 cycle
7 nocache;

Sequence created.

//查詢序列的nextval值

SQL> select seq1.nextval from dual;


NEXTVAL
----------
1

//查詢序列的當前currval值

SQL> select seq1.currval from dual;


CURRVAL
----------
1

//查詢序列的 nextval值

SQL> select seq1.nextval from dual;


NEXTVAL
----------
2

SQL> create table tb_stu(id number,name varchar2(40));

Table created.

//用序列作為引數插入表中
SQL> insert into tb_stu values (seq1.nextval, ‘testtest’);

1 row created.

//查詢表,能看到序列值的遞增。
SQL> select * from tb_stu;

ID NAME

3 testtest

//刪除表中資料
SQL> delete from tb_stu;

1 row deleted.

//修改表第一個屬性型別
SQL> alter table tb_stu modify id char(1);

Table altered.
//向表中插入資料,注意:插入時,數字型和字元型oracle會自動做轉換,序列像一個元件一樣在插入記錄時直接拿來用。

SQL> insert into tb_stu values (seq1.nextval, ‘test2test2’);

1 row created.

//查詢表中資料(序列值仍出現遞增)
SQL> select * from tb_stu;

I NAME

4 test2test2

總結:
建立序列語法:

CREATE SEQUENCE sequence_name
[INCREMENT BY n]
[START WITH n]
[{MAXVALUE n | NOMAXVALUE}] 10^27
[{MINVALUE n | NOMINVALUE}] -10^27
[{CYCLE | NOCYCLE }]
[{CACHE n | NOCACHE}];

說明:
INCREMENT BY:每次加幾個
START WITH:從幾開始
MAXVALUE:最大值是多少,或NOMAXVALUE不設定最大值
MINVALUE:最小值是多少,或NOMINVALUE不設定最小值
CYCLE:累加到最大值之後迴圈,或NOCYCLE一直累加不迴圈
CACHE:設定記憶體裡快取多少個序列,如果系統down掉了記憶體中的序列會丟失,導致序列跳號,也可以設定為NOCACHE不快取。

8、儲存過程

儲存過程:一段程式,用於改變資料庫物件的狀態,可以包含一個或多個行為,往往是將一個表的記錄經過處理後放到另一個表。

說明:和函式的功能非常相似,但又有不同,下節9會有詳細的對比不同說明。

//建立儲存過程

SQL> CREATE OR REPLACE PROCEDURE proc_1 (num number, name varchar2)
2 IS
3 BEGIN insert into tb_emp1(empno, ename) values (num, name);
4 END;
5
6 /

Procedure created.

//執行儲存過程(最後的“/”代表執行,詳見本文1. Oracle PL/SQL使用部分描述)。
SQL> BEGIN proc_1(11, ‘laoyang11’);
2 END;
3 /

PL/SQL procedure successfully completed.

//檢視執行結果

SQL> select * from tb_emp1;


EMPNO
----------
ENAME
--------------------------------------------------------------------------------
JOB
--------------------------------------------------------------------------------
11
zhang
engineer


11
laoyang11



EMPNO
----------
ENAME
--------------------------------------------------------------------------------
JOB

總結:

建立儲存過程的語法格式:

CREATE [OR REPLACE] PROCEDURE procedure_name
[(parameter_name [IN | OUT | IN OUT] TYPE[,….])]
{IS | AS }
[LOCAL declarations]
BEGIN
executable statements;
[EXCEPTION
exception_statements;
END procedure_name;

9、函式

函式的作用是計算一個功能,往往是用來計算並返回一個計算結果。
//建立函式(含引數)。
//返回number型別的資料。
SQL> CREATE OR REPLACE FUNCTION sal_tax
2 (v_sal number)
3 return number
4 is
5 begin
6 if (v_sal < 2000) then
7 return 0.10;
8 elsif (v_sal < 2750) then
9 return 0.15;
10 else
11 return 0.20;
12 end if;
13 end;
14 /

Function created.

//查詢

SQL> select sal_tax(2000) from dual;
SAL_TAX(2000)
-------------
          .15

SQL> select sal_tax(5555) from dual;
SAL_TAX(5555)
-------------
           .2

//函式中沒有引數的,可以不加()。
//函式中一般不會用dbms_output.put_line列印資訊,因為函式是用來計算並返回一個計算結果的,當然加了列印也沒關係(測試後也驗證了:不會列印)
SQL> CREATE OR REPLACE FUNCTION hello RETURN VARCHAR2 IS
2 var VARCHAR2(40) := ‘hello function’;
3 BEGIN
4 –dbms_output.put_line(‘aaaaaaaaaaa’);
5 return var;
6 END;
7 /

Function created.

SQL> select hello from dual;
HELLO
--------------------------------------------------------------------------------
hello function

總結:
函式的基本語法格式:
CREATE [OR REPLACE] FUNCTION function_name
[(parameter_name [IN | OUT | IN OUT] TYPE[,….])]
RETURN TYPE
{IS | AS}
BEGIN
FUNCTION BODY
END function_name;

重點————函式和儲存過程的區別:
1)函式和過程比較類似,不同的是函式必須返回一個值,而儲存過程僅是為了執行一系列的操作。

2)在呼叫的時候,函式可以作為表示式的一部分進行呼叫,並且可以使用在SELECT中。而儲存過程只能作為一個PL/SQL語句進行呼叫,且不能在SELECT語句中使用。

3)函式的語法結構和儲存過程比較類似,除了函式使用FUNCTION進行定義之外。外一個重要的特點就是,函式具有RETURN子句,指定函式的返回型別。

4)函式和儲存過程都可以使用out引數來返回內容。