初學Orcale記錄

Orcale存儲過程:
1 、創建存儲過程
create or replace procedure test(var_name_1 in type,var_name_2 out type) as
-- 聲明變量( 變量名 變量類型),用as來代替declare
begin
-- 存儲過程的執行體
end test;
打印出輸入的時間信息
E.g:
create or replace procedure test(workDate in Date) is
begin
/*打印前必須在pl/sql中設置set serveroutput on;否則不能顯示結果
dbms_output.putline('The input date is:'||to_date(workDate,'yyyy-mm-dd'));
end test;
2 、變量賦值
變量名 := 值;
E.g :
create or replace procedure test(workDate in Date) is
x number(4,2);
 begin
 x := 1;
end test;
3 、判斷語句:
if 比較式 then begin end; end if;
E.g
create or replace procedure test(x in number) is
begin
        if x >0 then
         begin
        x := 0 - x;
        end;
    end if;
    if x = 0 then
       begin
        x: = 1;
    end;
    end if;
end test;
4 、For 循環
For ... in ... LOOP
-- 執行語句
end LOOP;
(1) 循環遍歷遊標
create or replace procedure test() as
Cursor cursor is select name from student; name varchar(20);
begin
for name in cursor LOOP
begin
 dbms_output.putline(name); 
end;
end LOOP;
end test;
(2) 循環遍歷數組
 create or replace procedure test(varArray in myPackage.TestArray) as
--( 輸入參數varArray 是自定義的數組類型,定義方式見標題6)
i number;
begin
i := 1;  -- 存儲過程數組是起始位置是從1 開始的,與java 、C 、C++ 等語言不同。因爲在Oracle 中本是沒有數組的概念的,數組其實就是一張
-- 表(Table), 每個數組元素就是表中的一個記錄,所以遍歷數組時就相當於從表中的第一條記錄開始遍歷
for i in 1..varArray.count LOOP     
dbms_output.putline('The No.'|| i || 'record in varArray is:'||varArray(i));   
 end LOOP;
end test;
5 、While 循環
while 條件語句 LOOP
begin
end;
end LOOP;
E.g
create or replace procedure test(i in number) as
begin
while i < 10 LOOP
begin    
 i:= i + 1;
end;
end LOOP;
 end test;
6 、數組
首先明確一個概念:Oracle 中本是沒有數組的概念的,數組其實就是一張表(Table), 每個數組元素就是表中的一個記錄。
使用數組時,用戶可以使用Oracle 已經定義好的數組類型,或可根據自己的需要定義數組類型。
(1) 使用Oracle 自帶的數組類型
x array; -- 使用時需要需要進行初始化
e.g:
create or replace procedure test(y out array) is
 x array;  
 begin
x := new array();
y := x;
end test;
(2) 自定義的數組類型 ( 自定義數據類型時,建議通過創建Package 的方式實現,以便於管理)
E.g ( 自定義使用參見標題4.2)
create or replace package myPackage is
   Public type declarations   type info is record(     name varchar(20),     y number);
  type TestArray is table of info index by binary_integer;  
-- 此處聲明瞭一個TestArray 的類型數據,其實其爲一張存儲Info 數據類型的Table 而已,及TestArray 就是一張表,有兩個字段,一個是name ,一個是y 。需要注意的是此處使用了Index by binary_integer 編制該Table 的索引項,也可以不寫,直接寫成:type TestArray is
table of info ,如果不寫的話使用數組時就需要進行初始化:varArray myPackage.TestArray; varArray := new myPackage.TestArray();
end TestArray;
7. 遊標的使用 Oracle 中Cursor 是非常有用的,用於遍歷臨時表中的查詢結果。其相關方法和屬性也很多,現僅就常用的用法做一二介紹:
(1)Cursor 型遊標( 不能用於參數傳遞)
create or replace procedure test() is  
cusor_1 Cursor is select std_name from student where  ...;  --Cursor 的使用方式1   cursor_2 Cursor;
begin
select class_name into cursor_2 from class where ...;  --Cursor 的使用方式2
可使用For x in cursor LOOP .... end LOOP; 來實現對Cursor 的遍歷
end test;
(2)SYS_REFCURSOR 型遊標,該遊標是Oracle 以預先定義的遊標,可作出參數進行傳遞
create or replace procedure test(rsCursor out SYS_REFCURSOR) is
cursor SYS_REFCURSOR; name varhcar(20);
begin
OPEN cursor FOR select name from student where ... --SYS_REFCURSOR 只能通過OPEN 方法來打開和賦值
LOOP
 fetch cursor into name   --SYS_REFCURSOR 只能通過fetch into 來打開和遍歷 exit when cursor%NOTFOUND;              --SYS_REFCURSOR 中可使用三個狀態屬性:                                         ---%NOTFOUND( 未找到記錄信息) %FOUND( 找到記錄信息)                                         ---%ROWCOUNT( 然後當前遊標所指向的行位置)
 dbms_output.putline(name);
end LOOP;
rsCursor := cursor;
end test;
下面寫一個簡單的例子來對以上所說的存儲過程的用法做一個應用:
現假設存在兩張表,一張是學生成績表(studnet) ,字段爲:stdId,math,article,language,music,sport,total,average,step              
一張是學生課外成績表(out_school), 字段爲:stdId,parctice,comment
通過存儲過程自動計算出每位學生的總成績和平均成績,同時,如果學生在課外課程中獲得的評價爲A ,就在總成績上加20 分。
create or replace procedure autocomputer(step in number) is
rsCursor SYS_REFCURSOR;
commentArray myPackage.myArray;
math number;
article number;
language number;
music number;
sport number;
total number;
average number;
stdId varchar(30);
record myPackage.stdInfo;
i number;
begin
i := 1;
get_comment(commentArray); -- 調用名爲get_comment() 的存儲過程獲取學生課外評分信息
OPEN rsCursor for select stdId,math,article,language,music,sport from student t where t.step = step;
LOOP
fetch rsCursor into stdId,math,article,language,music,sport; exit when rsCursor%NOTFOUND;
total := math + article + language + music + sport;
for i in 1..commentArray.count LOOP 
 record := commentArray(i);    
if stdId = record.stdId then  
 begin     
 if record.comment = &apos;A&apos; then     
  begin         
 total := total + 20;   
   go to next; -- 使用go to 跳出for 循環       
  end;    
end if;  
end;  
end if;
end LOOP;
<<continue>>  average := total / 5;
 update student t set t.total=total and t.average = average where t.stdId = stdId;
end LOOP;
end;
end autocomputer;
-- 取得學生評論信息的存儲過程
create or replace procedure get_comment(commentArray out myPackage.myArray) is
rs SYS_REFCURSOR ;
record myPackage.stdInfo;
stdId varchar(30);
comment varchar(1);
i number;
begin
open rs for select stdId,comment from out_school
i := 1;
LOOP
 fetch rs into stdId,comment; exit when rs%NOTFOUND;
record.stdId := stdId;
 record.comment := comment;
recommentArray(i) := record;
i:=i + 1;
end LOOP;
end get_comment;
-- 定義數組類型myArray
create or replace package myPackage is begin
type stdInfo is record(stdId varchar(30),comment varchar(1));
type myArray is table of stdInfo index by binary_integer;
end myPackage;
 
複習內容:
一.Oracle數據庫中常用的數據類型
varchar2(長度)可變長字符串
char(長度) 定長
number()表示整數或者浮點數number(8) number(8,2)
clog 字符的大對象
blog 二進制的大對象

二.數據庫查詢
1)SELECT語句
從表中提取查詢數據.語法爲SELECT [DISTINCT] {column1,column2,…} FROM tablename WHERE {conditions} GROUP BY {conditions} ORDER BY {expressions} [ASC/DESC];
說明:SELECT子句用於指定檢索數據庫的中哪些列,FROM子句用於指定從哪一個表或視圖中檢索數據。
2)WHERE子句。
WHERE子句用來選擇符合條件的的記錄.
like '...' 通配查詢 _,%
between ... and ... ,表示結果在這之間,between and是一個閉區間。
!=,<>,^=,這三個都可以表示不等於。
in (va1,val2,...) 判斷結果是否在這個集合中存在 。
like '...' 字符串通配查詢,'%'表示0或多個字符,'_'表示一個字符。
... and ... 表示只有兩個條件同時滿足
... or ... 表示條件只要滿足其中之一就可以
all ... 是要求都滿足條件。
not .....,則是可以與以上的條件產生反效果。
... is null 使用來判斷值是不是空。
3) ORDER BY子句
ORDER BY 子句使得SQL在顯示查詢結果時將各返回行按順序排列,返回行的排列順序由ORDER BY 子句指定的表達式的值確定。
ASC(默認,升序) DESC(降序)
order by 目標列名(別名) 排序順序(不寫排序順序,會默認爲升序排序)
例:select first_name from s_emp order by first_name;
select first_name from s_emp order by first_name desc;

三.SQL常用的命令分類及例子
數據定義語言:create(創建)、alter(更改)和drop(刪除)命令。
數據操縱語言:insert(插入)、select(選擇)、delete(刪除)和update(更新)命令。
事務控制語言:commit(提交)、savepoint(保存點)和rollback(回滾)命令。
數據控制語言:grant(授予)和revoke(回收)。
1.數據定義語言舉例:
SQL> create table myTab(no number(4),name varchar2(20));創建一個名爲myTab的表,包含兩列no和name;
SQL> alter table myTab modify (name varchar2(25));修改myTab中的name列,使此列能容納25個字符;
SQL> alter table myTab add (tel_no varchar2(20));給表myTab增加一列tel_no;
SQL> alter table myTab drop column tel_no;刪除表myTab的tel_no列;
SQL> drop table myTab;刪除表myTab;
SQL> truncate table myTab;刪除表myTab中的所有行(截斷表),注意:不可以回滾。

2.數據操縱語言舉例:
SQL> insert into myTab values(‘001’,’John’);
向表myTab中插入一行數據;
SQL> select distinct salary “薪水” from s_emp where salary>1500 order by sal desc;
選擇表中salary大於1500的數據,以別名“薪水”顯示並按照salary的降序進行排列輸出;
SQL> create table empa as select empno,ename,job,sal from emp;
從emp表中選擇“empno,ename,job,sal”四列的數據建立新表empa;
SQL> create table empa as select * from emp where 1=2;
使用一個假條件根據現有表emp創建一個只包含結構的空表empa;
SQL> delete from empa where sal<1500;
刪除表empa中sal小於1500的行;
SQL> update empa set sal=1500 where sal<1500;更新,將表empa中sal小於1500的行的sal值全部改爲1500。

3.事務控制語言舉例:
SQL> commit;用於提交併結束事務處理;
SQL> savepoint mark1;保存點類似於標記,用來標記事務中可以應用回滾的點;
SQL> rollback to savepoint mark1;回滾到保存點mark1。

四.Oracle數據庫函數
注意:dual表(虛表)是專門用於函數測試和運算的.
1.字符函數
   字符是大小寫敏感的
   轉小寫 lower(字段名)
   轉大寫 upper(字段名)
   首字母大寫 initcap(字段名)
   字符串拼接 concat(字段1, 字段2)
   截取子串 substr(字段名, 起始位置,取字符個數)
例: select first_name,substr(first_name,2,2) sub from s_emp;(從名字的第二個字符開始取兩個字符)
select first_name,substr(first_name,-2,2) sub from s_emp;(從名字的倒數第二個字符開始取兩個字符)
2.數值函數
   四捨五入函數 round(數據,保留到小數點後幾位)
   1表示保留到小數點後一位,-1表示保留到小數點前一位。
   例:select round(15.36,1) from dual;
   截取數值函數 trunc(數據,保留到小數點後幾位)
   例:select trunc(123.456,1) from dual;
截取到小數點後一位,注意:與round函數不同,不會四捨五入。
3.日期函數
   缺省日期格式,日-月-年 dd-mon-rr
   修改當前會話的日期格式,會按照指定的格式輸出日期
   alter session set nls_date_format='yyyy mm dd hh24:mi:ss';
   返回當前日期 sysdate
   例:select sysdate from dual;
4.不同數據類型間轉換函數
   將日期轉成字符 tochar(date,'日期格式')
   日期格式要用有效格式,格式大小寫敏感 'yyyy mm dd hh24:mi:ss'(標準日期格式),'year'(年的全拼),'month'(月的全拼),'day'(星期的全拼),'ddspth' (日期的全拼)
   例:select to_char(sysdate,'yyyy mm dd hh24:mi:ss')from dual;
select to_char(sysdate,'year month day ddspth')from dual;
   將字符串轉成日期 to_date('...','日期格式')
   例:select to_char(to_date('2006 11 03','yyyy mm dd'),'dd-month-yy') from dual;

五.表連接(關聯查詢)
等值連接
select table1.column1,table2.column2
from table1 t1,table2 t2
where t1.column3=t2.column4;
表連接時,當表與表之間有同名字段時,可以加上表名或表的別名,加以區分,使用時要用表名.字段名或表別名.字段名(列名)。當表的字段名是唯一時,可以不用加上表名或表的別名。
注意:當爲表起了別名,就不能再使用表名.字段名了。
例如:select e.first_name ||’ ’|| e.last_name name,
d.name dept_name
from s_emp e, s_dept d
where e.dept_id=d.id;

非等值連接
select [表別名1.字段名1],[表別名2.字段名2],...
from 表1 表別名1 ,表2 表別名2
where 表別名1.字段名3 ..... 表別名2.字段名4
....可以使比較運算符,也可以使其他的除了'='的運算符
例:select first_name, salary
from s_emp
where salary between 1000 and 2000;

自連接
把一個表的兩個字段關係轉換成兩個表字段之間的關係.
select [表別名1.字段名1],[表別名2.字段名2],...
from 表1 表別名1 ,表1 表別名2
where 表別名1.字段名3=表別名2.字段名4;
例:select a.first_name ename,b.first_name cname
from s_emp a,s_emp b
where a.manager_id=b.id;

外連接
使用一張表中的所有記錄去和另一張表中的記錄按條件匹配(空值也會匹配)這個表中的所有記錄都會顯示。
//想在哪邊模擬記錄就在哪邊加上(+)
1. LEFT OUTER JOIN:左外連接
SELECT e.last_name, e.dept_id, d.name
FROM s_emp e
LEFT OUTER JOIN s_dept d
ON (e.dept_id = d.id);
等價於
SELECT e.last_name, e.dept_id, d.name
FROM s_emp e, s_dept d
WHERE e.dept_id=d.id(+);
結果爲:所有員工及對應部門的記錄,包括沒有對應部門編號dept_id的員工記錄。
2. RIGHT OUTER JOIN:右外連接
SELECT e.last_name, d.name
FROM s_emp e
RIGHT OUTER JOIN s_dept d
ON (e.dept_id = d.id);
等價於
SELECT e.last_name,d.name
FROM s_emp e, s_dept d
WHERE e.dept_id(+)=d.id;
結果爲:所有員工及對應部門的記錄,包括沒有任何員工的部門記錄。
3. FULL OUTER JOIN:全外關聯
SELECT e.dept_id,d.id
FROM s_emp e
FULL OUTER JOIN s_dept d
ON (e.dept_id = d.id);

結果爲:所有員工及對應部門的記錄,包括沒有對應部門編號department_id的員工記錄和沒有任何員工的部門記錄。
六.組函數
group by把 select 的結果集分成幾個小組,這個group by 子句可以跟在 select 語句後或是 having前面。group by子句也會觸發排序操作,會按分組字段排序。
select [組函數或分組的字段名]... from 表名 group by [字段名1],[字段名2],.....;
例:select avg(salary) from s_emp group by dept_id;
注意:組函數會忽略空值,但是count(*)除外,他會把空記錄也記錄在內。avg和sum這兩個函數的參數只能是number型的。
以下所提到的函數可以使用任意類型做參數。
max(..),min(..)求最大值和最小值,
count(*)統計表中記錄數。
例:select max(b.name),avg(a.salary), max(c.name)
from s_emp a,s_dept b,s_region c
where a.dept_id=b.id
and b.region_id=c.id
group by b.id;
注意:只要寫了group by子句,select後就只能用group by之後的字段或者是組函數。having子句可以過濾組函數結果或是分組的信息,並且寫在group by子句後。

七.子查詢
可以嵌在sql語句中的select語句。
在select語句中嵌套子查詢時,會先執行子查詢。一般的會將子查詢放在運算符的右邊。
注意:在使用子查詢時,要注意這個運算符是單行的(也就是隻能是單值),還是多行運算符(範圍,多值)。配合使用子查詢返回的結果必須符合運算符的用法。
例:
select first_name||' '||last_name name
from s_emp
where title in (select title from s_emp
where dept_id=42);
查詢和42部門員工職位相同的所有員工的姓名

八.約束
針對表中的字段進行定義的。
primary key(主鍵約束 PK)保證實體的完整性,保證記錄的唯一
主鍵約束,唯一且非空,並且每一個表中只能有一個主鍵,有兩個字段聯合作爲主鍵時,將兩個字段放在一起唯一標識記錄,叫做聯合主鍵。
主鍵約束的定義:
第一種定義形式:
create table test(c number primary key );        列級約束
第二種定義形式:
create table test(c number , primary key(c) ) ;        表級約束
create table test(c1 number constraints   pk_c1 primary key );   此約束有名字: pk_c1
create table   test(c number , c2 number , primary key (c ,c1) ) ; 用表級約束可以實現聯合主鍵

foreign key(外鍵約束 FK)保證引用的完整性,外鍵約束,外鍵的取值是受另外一張表中的主鍵或唯一鍵的約束,不能夠取其他值,只能夠引用主鍵或唯一鍵的值,被引用的表,叫做 parent table(父表),引用方的表叫做child table(子表),要想創建子表,就要先創建父表,記錄的插入也是如此,先父表後子表,刪除記錄,要先刪除子表記錄,後刪除父表記錄,要修改記錄,如果要修改父表的記錄要保證沒有被子表引用。要刪表時,要先刪子表,後刪除父表。(可以通過使用cascade constraints 選項來刪除父表)
carete   table     parent(c1 number primary key );
create   table    child (c number primary key ,   c2 number references parent(c1));
或表級約束定義:
create   table child( c number primary key , c2 number , foreign key(c2) references parent(c1));
非空約束(not null)這是一個列級約束,在建表時,在數據類型的後面加上 not null ,也就是在插入時不允許插入空值。
例:create table student(id number primary key,name varchar2(32) not null,address varchar2(32));
unique 唯一約束
唯一約束,允許爲空,要求插入的記錄中的值是唯一的。
例:create table student(id number,name varchar2(32),address varchar2(32),primary key (id),unique (address));
check約束
檢查約束,可以按照指定條件,檢查記錄的插入。check中不能使用僞列,不能使用函數,不能引用其他字段。
例:create table sal (a1 number , check(a1>1000));

九.數據字典
數據字典是由系統維護的,包含數據庫的信息
數據字典示圖
user_XXXXX 用戶示圖
all_XXXXX 所有示圖
dba_XXXXX 數據庫中所有示圖
v$_XXXXX   動態性能示圖

dict或 dictionary 表示數據字典的數據字典。
user_constraints 用戶的表中約束的表
其中有constraints_name字段存放的是約束名,constraint_type字段存放的是約束的類型,r_constraints_name字段表示外鍵引用自何處.
user_cons_column表,是用戶的列級約束表,column_name字段存放的是約束字段的名字,position字段存放的是約束在聯合鍵中的位置.

十.事務transaction
原子操作,也就是不可分割的操作,必須一起成功一起失敗。
事務的結束動作就是commit,DDL,DCL語句執行會自動提交commit。
sqlplus正常退出是會做提交動作的commit;,當系統異常推出是,會執行回滾操作rollback;。
一個沒有結束的事務,叫做活動的事務 (active transaction),活動的事務中修改的數據,只有本會話才能看見。

十一.Oracle中的僞列
僞列就像Oracle中的一個表列,但實際上它並未存儲在表中。僞列可以從表中查詢,但是不能插入、更新或刪除它們的值。常用的僞列:rowid和rownum。
rowid:數據庫中的每一行都有一個行地址,rowid僞列返回該行地址。可以使用rowid值來定位表中的一行。通常情況下,rowid值可以唯一地標識數據庫中的一行。
rowid僞列有以下重要用途:
1)能以最快的方式訪問表中的一行;
2)能顯示錶的行是如何存儲的。
3)可以作爲表中行的唯一標識。
如:SQL> select rowid,ename from emp;
rownum:對於一個查詢返回的每一行,rownum僞列返回一個數值代表的次序。
rownum僞列特點:
1) 有個特點要麼等於1 要麼小於某個值, 不能直接等於某個值, 不能大於某個值。
2)常用於分頁顯示。
返回的第一行的rownum值爲1,第二行的rownum值爲2,依此類推。通過使用rownum僞列,用戶可以限制查詢返回的行數。
如:SQL>select * from emp where rownum<11; 從emp表中提取10條記錄。

十二.序列(sequence)
create sequence 序列名;
(不帶參數時默認爲從1 開始每次遞增 1,oracle中爲了提高產生序列的效率一般一次性產生20個序列放入當前會話的序列池中備用以加快效率)

sequence 的參數:
increment by n   起始值
start with n     遞增量
maxvalue n       最大值
minvalue n       最小值
cycle|no cycle     循環
cache n          緩存(第一次取時會一次取多少個id存起來)

查看sequence 示圖:
desc    user_sequences ;
select   sequence_name , cache_size , last_number from user_sequences   where   sequence_name like 's_';
select 序列名.currval from   dual    查看當前的序列數
select 序列名.nextval from   dual    查看下一個序列數,它會自動給當前的序列加1
刪除序列sequence
drop sequence 序列名;

十三. 視圖(View)
視圖就相當於一條select 語句,定義了一個視圖就是定義了一個sql語句, 視圖不佔空間,使用視圖不會提高性能,但是能簡化sql語句
創建視圖:
creating views視圖名;
如:
create or replace views test as select * from test1 where c1=1;
create or replace:如果view存在就覆蓋,不存在才創建。
force|no force:基表存在時使用,不存在時則創建該表。
注意:向視圖中插入數據時,會直接插進基表中,查看視圖中的數據時,相當於就是執行創建時的select語句。
刪除視圖:
drop views視圖名;
試圖的約束:
with read only視圖只讀約束
with check option 不允許插入與where條件不符的記錄,類似於check約束的功能.
create view test_cc
as select * from test
where c1>10
with check option;

十四.索引(index)
建立索引的目的就是爲了加快查詢速度,建立索引後會使DML操作效率慢,但是對用戶查詢會提高效率。刪除一個表時,相對應的索引也會刪除。另外,索引是會進行排序。
創建一個索引:
create index 索引名 on 表名 (字段名);
create index test_index on test(c1);
刪除索引:
drop index test_index;
注意:創建索引就是爲了減少物理讀,索引會減少掃描的時間。在經常要用到where的子句的字段,應該使用索引,另外還要看所查詢的數據與全部數據的百分比,表越大,查詢的記錄越少,索引的效率就越高.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章