总结:Oracle快速入门
2019獨角獸企業重金招聘Python工程師標準>>>
一:數據庫分類
小:access/foxbase等
中:mysql/sql server/informix等
大:oracle/sybase/db2
二:sqlpus常用命令
oracle自帶用戶:sys(超級用戶,具有sysdba角色,可以創建數據庫)、system(具有sysoper角色),區別在于是否能創建數據庫。
1:連接命令:【conn 用戶名/密碼@網絡服務名 [as sysdba/sysoper]】
2:顯示當前用戶:【show user】
3:斷開連接:【disc/disconn/disconnect】
4:修改當前用戶的密碼:【passw/password】,修改其他用戶密碼(權限):【alter user 用戶名 identity by 新密碼】
5:退出sqlplus:【exit】
6:清空屏幕:【clear screen】
7:運行sql腳本:【start/@ url.sql】
8:編輯sql腳本:【edit url.sql】
9:將屏幕內容輸入到指定文件:【spool url.sql】【spool off】
10:交互式命令&:【&value】需要用戶輸入值
11:顯示和設置環境變量:【show/set linesize/pagesize】
12:創建用戶(dba權限):create user 用戶名 identified by 密碼;
13:刪除用戶:【drop user 用戶名 [cascade]】
14:授予權限(系統和對象權限):【grant 權限 to 用戶 [with grant option]/[with admin opyion]】
15:收回權限:【revoke 權限 on 對象 from 用戶】(系統權限不級聯,對象權限級聯收回)
16:賬號鎖定(創建profile口令限制的集合):【create profile lock_account limit failed_login_attempts 3 password_lock_time 2;】【alter user scott profile lock_account;】
17:賬戶解鎖:【alter user scott account unlock;】
18:終止口令(使用戶定期修改密碼):【create profile myprofile limit password_life_time 10 password_grace_time 2;】【alter user test profile myprofile;】
19:口令歷史:【create profile password_history limit password_life_time 10 password_grace_time 2 password_reuse_time 10】【alter user test profile password_history;】
20:刪除profile:【drop profile password_history [casade]】
三:常用SQL命令
1:數據類型:char/varchar2(n)/varchar/number(n,m)/date/timestamp/blob
2:創建表:create table demo( filed1 varchar2(20),...);
3:修改表:alter table demo add/modify ( filed1 varchar2(20))/drop column field1;
4:修改表名字:rename demo to test;
5:刪除表:drop table demo;
6:添加數據:insert into table demo values(...);
7:修改數據:update demo set ... where ...
8:刪除數據:delete from demo where ...;
9:刪除表結構和數據:drop table demo;
10:刪除所有表記錄,無日志寫入無法找回刪除的記錄:truncate table demo;
11:查看表結構:desc demo;
12:查詢所有列:select * from demo;
13:底部顯示操作時間:set timing on/off;
14:表復制語句:insert into t2(filed1,...) select v1,v2,...from t1;
15:查詢統計:select count(*) from demo;
16:查詢語句:select [distinct] field1 [as alias],... from ... where ...
17:nvl函數:nvl(str1,replace_str2)
18:連接字符串:||
19:模糊查詢:like '%demo_';
20:范圍查詢:in (A,B,C);
21:判空查詢:is null/null
22:升降序排列:order by [asc/desc]
23:聚合函數(如果列里面有一個分組函數,其它都必須是分組函數):max/min/avg/sum/count
24:分組統計:group by ... having ...??? (order by ...)
25: 當在from 子句中使用子查詢時,必須給子查詢指定別名 , 給表取別名的時候,不能加as;但是給列取別名,是可以加as的。
26:根據查詢結果創建新表: CREATE TABLE mytable (id, name, sal, job, deptno) as SELECT empno, ename, sal, job, deptno FROM emp;
27:合并查詢:union(去掉重復行)/union all/intersect/minus
四:oracel分頁方式
1:rowid分頁
SELECT *
FROM EMP
WHERE ROWID IN
?????? (SELECT RID
????????? FROM (SELECT ROWNUM RN, RID
????????????????? FROM (SELECT ROWID RID, EMPNO FROM EMP ORDER BY EMPNO DESC)
???????????????? WHERE ROWNUM <= ( (currentPage-1) * pageSize + pageSize )) --每頁顯示幾條
???????? WHERE RN > ((currentPage-1) * pageSize) ) --當前頁數
?ORDER BY EMPNO DESC;
2:rownum分頁
SELECT *
? FROM (SELECT T.*, ROWNUM RN
????????? FROM (SELECT * FROM EMP ORDER BY EMPNO DESC) T
???????? WHERE ROWNUM <= ( (currentPage-1) * pageSize + pageSize )) --每頁顯示幾條
? WHERE RN > ( (currentPage-1) * pageSize ); --當前頁數
3:分析函數分頁
SELECT *
FROM (SELECT T.*, ROW_NUMBER() OVER(ORDER BY empno DESC) RK FROM emp T)
WHERE RK <= ( (currentPage-1) * pageSize + pageSize ) --每頁顯示幾條
AND RK > ( (currentPage-1) * pageSize ); --當前頁數
解析步驟:
1:SELECT * FROM emp;
2:顯示rownum,由oracle分配的
SELECT e.*, ROWNUM rn FROM (SELECT * FROM emp) e; --rn相當于Oracle分配的行的ID號
3:先查出1-10條記錄
正確的: SELECT e.*, ROWNUM rn FROM (SELECT * FROM emp) e WHERE ROWNUM<=10;
錯誤的:SELECT e.*, ROWNUM rn FROM (SELECT * FROM emp) e WHERE rn<=10;
4:然后查出6-10條記錄
SELECT * FROM (SELECT e.*, ROWNUM rn FROM (SELECT * FROM emp) e WHERE ROWNUM<=10) WHERE rn>=6;
五:事務操作
1:設置保存點:savepoint a;
2:回滾到保存點:rollback to a;
3:回滾全部事務操作:rollback;
4:提交事務:commit;
5:java中使用事務:conn.setAutoCommit(false);關閉自動提交事務,然后事務機制操作
6:只讀事務: set transaction read only;
六:常用函數
1:字符函數: lower(char) /upper(char)/length(char)/substr(char, m, n)/replace(char1, search_string, replace_string) /instr(C1,C2,I,J)
2:數字函數: cos,cosh,exp,ln, log,sin,sinh,sqrt,tan,tanh,acos,asin,atan,round 等
3:日期函數: sysdate (返回系統時間 )、 add_months(time,moths)函數 ( 得到某一時間之前或之后n個月的時間 )、 last_day(d)(返回指定日期所在月份的最后一天 )
4:轉換函數: to_char(date,formatStr)函數(
yy:兩位數字的年份 2004-->04
yyyy:四位數字的年份 2004年
mm:兩位數字的月份 8 月-->08
dd:兩位數字的天 30 號-->30
hh24: 8點-->20
hh12:8點-->08
mi、ss-->顯示分鐘\秒
9:顯示數字,并忽略前面0
0:顯示數字,如位數不足,則用0補齊
.:在指定位置顯示小數點
,:在指定位置顯示逗號
$:在數字前加美元
L:在數字前面加本地貨幣符號
C:在數字前面加國際貨幣符號
G:在指定位置顯示組分隔符、
D:在指定位置顯示小數點符號(.)
)
to_date()函數 ('dateStr',formatStr)
5:sys_context(‘USERENV’,param)系統函數:(param=teminal/language/db_name/nls_date_format/session_user/currentt_schema/host)
6:管理員區別: sysdba>sysoper>dba
7:顯示初始化參數:show parameter
8:修改參數: oracle\admin\myoral\pfile\init.ora 文件中去修改。
七:備份與恢復
一:備份(導出):導出表、導出方案、導出數據庫
參數:
userid:用于指定執行導出操作的用戶名,口令,連接字符串
tables:用于指定執行導出操作的表
owner:用于指定執行導出操作的方案
full=y:用于指定執行導出操作的數據庫
inctype:用于指定執行導出操作的增量類型
rows:用于指定執行導出操作是否要導出表中的數據
file:用于指定導出文件名
1:導出表:
exp userid=scott/oracle@orcl tables=(emp) file=d:\emp.dmp --導出單個表
exp userid=scott/oracle@orcl tables=(emp,dept) file=d:\emp.dmp --導出多個表
導出其他方案的表:
exp userid=system/oracle@orcl tables=(scott.emp) file=d:\emp.emp
exp userid=system/oracle@orcl tables=(scott.emp,scott.dept) file=d:\emp.emp
導出表結構:
exp userid=scott/oracle@orcl tables=(emp) file=d:\emp.dmp rows=n
直接導出方式 :
exp userid=scott/oracle@orcl tables=(emp) file=d:\emp.dmp direct=y
2:導出方案:
導出方案:
exp userid=scott/oracle@orcl owner=scott file=d:\scott.dmp
導出其它方案:
exp userid=system/oracle@orcl owner=(system,scott) file=d:\system.dmp
3:導出數據庫
exp userid=system/oracle@orcl full=y inctype=complete file=d:\all.dmp
二:恢復(導入)
參數:
userid:用于指定執行導入操作的用戶名,口令,連接字符串
tables:用于指定執行導入操作的表
formuser:用于指定源用戶
touser:用于指定目標用戶
file 用于指定導入文件名
full=y:用于指定執行導入整個文件
inctype:用于指定執行導入操作的增量類型
rows:指定是否要導入表行(數據)
ignore:如果表存在,則只導入數據
1:導入表
導入表:
imp userid=scott/oracle@orcl tables=(emp) file=d:\xx.dmp
導入表到其它用戶:
imp userid=system/oracle@orcl tables=(emp) file=d:\xx.dmp touser=scott
導入表結構:
imp userid=scott/oracle@orcl tables=(emp) file=d:\xx.dmp rows=n
導入數據:
imp userid=scott/oracle@orcl tables=(emp) file=d:\xx.dmp ignore=y?
2:導入方案
導入自身的方案:
imp userid=scott/oracle@orcl file=d:\xxx.dmp
導入其它方案:
imp userid=system/oracle@orcl file=d:\xxx.dmp fromuser=system touser=scott
3:導入數據庫(相當于數據庫遷移)
imp userid=system/oracle@orcl full=y file=d:\xxx.dmp
八:視圖操作
1:數據字典視圖: user_xxx,all_xxx,dba_xxx
user_tables: 用于顯示當前用戶所擁有的所有表,它只返回用戶所對應方案的所有表 。
all_tables: 用于顯示當前用戶可以訪問的所有表,它不僅會返回當前用戶方案的所有表,還會返回當前用戶可以訪問的其它方案的表 。
dba_tables: 它會顯示所有方案擁有的數據庫表。但是查詢這種數據庫字典視圖,要求用戶必須是dba角色或是有select any table 系統權限。
2:用戶名和權限和角色
dba_users可以顯示所有數據庫用戶的詳細信息;
dba_sys_privs可以顯示用戶所具有的系統權限;
dba_tab_privs可以顯示用戶具有的對象權限;
dba_col_privs 可以顯示用戶具有的列權限;
dba_role_privs 可以顯示用戶所具有的角色。
九:表空間和數據文件
表空間:數據庫的邏輯組成部分, 物理上講,數據庫數據存放在數據文件中。邏輯上講,數據庫數據則是存放在表空間中,表空間由一個或多個數據文件組成( 數據庫由表空間構成,而表空間又是由段構成,而段又是由區構成,而區又是由oracle塊構成 )。
1:建立表空間: create tablespace data01 datafile 'D:\dev\oracle\product\10.2.0\dada01.dbf' size 20m uniform size 128k;
2:使用表空間:
create table mypart(
?? deptno number(4),
?? dname varchar2(14),
?? loc varchar2(13)
) tablespace data01;
3:改變表空間狀態:
表空間脫機: alter tablespace 表空間名 offline;
表空間聯機: alter tablespace 表空間名 online;
只讀表空間: alter tablespace 表空間名 read only;
4:刪除表空間: drop tablespace ‘表空間’ including contents and datafiles;
5:擴展表空間:
增加數據文件 : alter tablespace sp01 add datafile 'D:\dev\oracle\product\10.2.0\dada02.dbf' size 1m;
修改數據文件的大小 : alter tablespace sp01 'D:\dev\oracle\product\10.2.0\dada01.dbf' resize 4m;
設置文件的自動增長 : alter tablespace sp01 'D:\dev\oracle\product\10.2.0\dada01.dbf' autoextend on next 10m maxsize 500m;
6:移動數據文件: 確定數據文件所在的表空間 》 使表空間脫機 》 使用命令移動數據文件到指定的目標位置 》 執行alter tablespace 命令 》 使得表空間聯機
select tablespace_name from dba_data_files where file_name=upper('D:\dev\oracle\product\10.2.0\dada01.dbf');
alter tablespace sp01 offline;
host move D:\dev\oracle\product\10.2.0\dada01.dbf c:\dada01.dbf;
alter tablespace sp01 rename datafile 'D:\dev\oracle\product\10.2.0\dada01.dbf' to 'c:\sp01.dbf';
alter tablespace sp01 online;
7:顯示表空間信息: select tablespace_name from dba_tablespaces;
8: 除了最常用的數據表空間外,還有其它類型表空間:索引表空間、 undo表空間、 臨時表空間、 非標準塊的表空間。
十:約束
1:約束包括:not null、 unique, primary key, foreign key和check 五種。
1)、not null(非空)
如果在列上定義了not null,那么當插入數據時,必須為列提供數據。
2)、unique(唯一)
當定義了唯一約束后,該列值是不能重復的,但是可以為null。
3)、primary key(主鍵)
用于唯一的標示表行的數據,當定義主鍵約束后,該列不但不能重復而且不能為null。
需要說明的是:一張表最多只能有一個主鍵,但是可以有多個unqiue約束。
4)、foreign key(外鍵)
用于定義主表和從表之間的關系。外鍵約束要定義在從表上,主表則必須具有主鍵約束或是unique 約束,當定義外鍵約束后,要求外鍵列數據必須在主表的主鍵列存在或是為null。
5)、check
用于強制行數據必須滿足的條件,假定在sal列上定義了check約束,并要求sal列值在1000-2000之間如果不在1000-2000之間就會提示出錯。
2:刪除約束
alter table 表名 drop constraint 約束名稱 ;
3:顯示約束信息
select constraint_name, constraint_type, status, validated from user_constraints where table_name = '表名';
select column_name, position from user_cons_columns where constraint_name = '約束名';
直接用pl/sql developer查看 .
十一:索引
1:創建索引
單列索引:單列索引是基于單個列所建立的索引
語法:create index 索引名 on 表名(列名);
復合索引:復合索引是基于兩列或是多列的索引。在同一張表上可以有多個索引,但是要求列的組合必須不同,比如:create index emp_idx1 on emp(ename, job); create index emp_idx1 on emp(job, ename); 這兩個索引是兩個不同的索引。
2:使用原則
1)、在大表上建立索引才有意義
2)、在where子句或是連接條件上經常引用的列上建立索引
3)、索引的層次不要超過4層
3:索引缺點
1)、建立索引,系統要占用大約為表1.2倍的硬盤和內存空間來保存索引。
2)、更新數據的時候,系統必須要有額外的時間來同時對索引進行更新,以維持數據和索引的一致性。
比如在如下字段建立索引應該是不恰當的:
1. 很少或從不引用的字段;
2. 邏輯型的字段,如男或女(是或否)等。
4:索引分類
按照數據存儲方式,可以分為B*樹、反向索引、位圖索引;
按照索引列的個數分類,可以分為單列索引、復合索引;
按照索引列值的唯一性,可以分為唯一索引和非唯一索引。
此外還有函數索引,全局索引,分區索引...
5:顯示索引信息
1):在同一張表上可以有多個索引,通過查詢數據字典視圖dba_indexs和user_indexs,可以顯示索引信息。其中dba_indexs用于顯示數據庫所有的索引信息,而user_indexs用于顯示當前用戶的索引信息:select index_name, index_type from user_indexes where table_name = '表名';
2):顯示索引列:通過查詢數據字典視圖user_ind_columns,可以顯示索引對應的列的信息
select table_name, column_name from user_ind_columns where index_name ='IND_ENAME';
3):你也可以通過pl/sql developer工具查看索引信息 。
十二:權限
一:系統權限
常用:
create session 連接數據庫
create table 建表
create view 建視圖
create public synonym 建同義詞
create procedure 建過程、函數、包
create trigger 建觸發器
create cluster 建簇
1:顯示系統權限: select * from system_privilege_map order by name;
2:授予系統權限: grant create session, create table to ken with admin option;
3:回收系統權限(不級聯): revoke create session from ken;
二:對象權限
常用:
insert 添加
delete 刪除
alter 修改
select 查詢
index 索引
references 引用
execute 執行
1:顯示對象權限: select distinct privilege from dba_tab_privs;
2:授予對象權限: grant select on emp to blake with grant option;
3:授予列權限: grant select on emp(ename,sal) to monkey ;
4:回收對象權限(級聯): revoke select on emp from blake ;
十三:角色
一:預定義角色: connect、resource、dba
1:connect角色
connect角色具有一般應用開發人員需要的大部分權限。
create cluster
create database link
create session
alter session
create table
create view
create sequence
2:resource角色
resource角色具有應用開發人員所需要的其它權限。
resource角色包含以下系統權限:
create cluster
create indextype
create table
create sequence
create type
create procedure
create trigger?
3:dba角色:具有所有的系統權限,及with admin option選項,默認的dba用戶為sys和system,它們可以將任何系統權限授予其他用戶。但是要注意的是dba角色不具備sysdba和sysoper的特權(啟動和關閉數據庫)。
二:自定義角色
1:建立角色: create role 角色名 not identified; create role 角色名 identified by 密碼;
2:角色授權: grant insert, update, delete on scott.emp to 角色名;
3:分配角色給用戶: grant 角色名 to 用戶 with admin option;
4:刪除角色: drop role 角色名;
5:顯示角色信息:
1)、顯示所有角色: select * from dba_roles;
2)、顯示角色具有的系統權限:select privilege, admin_option from role_sys_privs where role='角色名';
3)、顯示角色具有的對象權限:通過查詢數據字典視圖dba_tab_privs可以查看角色具有的對象權限或是列的權限。
4)、顯示用戶具有的角色,及默認角色:當以用戶的身份連接到數據庫時,oracle 會自動的激活默認的角色,通過查詢數據字典視圖dba_role_privs 可以顯示某個用戶具有的所有角色及當前默認的角色。
select granted_role, default_role from dba_role_privs where grantee = ‘用戶名’;
十四:PL/SQL
1:編碼規范
2: pl/sql塊: 三個部分構成:定義部分,執行部分,例外處理部分。
declare
/*定義部分——定義常量、變量、游標、例外、復雜數據類型*/
begin
/*執行部分——要執行的pl/sql 語句和sql 語句*/
exception
/*例外處理部分——處理運行的各種錯誤*/
end;
eg:
set serveroutput on; DECLARE--定義字符串變量v_ename varchar2(10); v_sal NUMBER(7,2); BEGIN--執行部分select ename, sal into v_ename, v_sal from emp where empno=&empno; dbms_output.put_line('雇員名:'||v_ename||',薪水:'||v_sal); EXCEPTION--異常處理 WHEN no_data_found THEN dbms_output.put_line('朋友,您的編號輸入有誤!'); end; /3:存儲過程: 用于執行特定的操作,當建立存儲過程時,既可以指定輸入參數(in),也可以指定輸出參數(out),通過在過程中使用輸入參數,可以將數據傳遞到執行部分;通過使用輸出參數,可以將執行部分的數據傳遞到應用環境。在sqlplus中可以使用create procedure命令來建立過程。
編寫存儲過程:
CREATE PROCEDURE sp_update(uname VARCHAR2, newsal NUMBER) IS BEGINupdate emp set sal=newsal where ename=uname; END; /調用存儲過程:
SQL> exec sp_update('zhangsan', 888); SQL> commit;java中調用存儲過程:
package junit.test;import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager;/** * 演示java程序調用oracle的存儲過程案例* * @author jiqinlin**/ public class ProcedureTest {public static void main(String[] args) {try {// 1.加載驅動Class.forName("oracle.jdbc.driver.OracleDriver");// 2.得到連接Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "oracle");// 3.創建CallableStatementCallableStatement cs = ct.prepareCall("{call sp_update(?,?)}");// 4.給?賦值cs.setString(1, "SMITH");cs.setInt(2, 4444);// 5.執行cs.execute();// 關閉cs.close();ct.close();} catch (Exception e) {e.printStackTrace();}} }4:函數: 用于返回特定的數據,當建立函數時,在函數頭部必須包含return子句。而在函數體內必須包含return語句返回的數據。我們可以使用create function來建立函數。
編寫函數:
CREATE FUNCTION annual_incomec(uname VARCHAR2) RETURN NUMBER IS annual_salazy NUMBER(7,2); BEGIN SELECT a.sal*13 INTO annual_salazy FROM emp a WHERE a.ename=uname;RETURN annual_salazy; END; /調用函數:
SQL> var income NUMBER; SQL> call annual_incomec('SCOTT') into:income; SQL> print income;java中調用存儲過程:
package junit.test;import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet;/** * 演示java程序調用oracle的函數案例* * @author jiqinlin**/ public class ProcedureTest {public static void main(String[] args) {try {// 1.加載驅動Class.forName("oracle.jdbc.driver.OracleDriver");// 2.得到連接Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "oracle");// 3.創建PreparedStatementPreparedStatement ps = ct.prepareStatement("select annual_incomec('SCOTT') annual from dual");// 4.執行ResultSet rs=ps.executeQuery();if(rs.next()){Float annual=rs.getFloat("annual");System.out.println(annual);}//5、關閉rs.close();ps.close();ct.close();} catch (Exception e) {e.printStackTrace();}} }5:包: 用于在邏輯上組合過程和函數,它由包規范和包體兩部分組成, 使用create package命令來創建包 。
1:聲明包:
create package sp_package isprocedure update_sal(name varchar2, newsal number);function annual_income(name varchar2) return number; end;2:創建包體:
CREATE OR REPLACE PACKAGE BODY SP_PACKAGE IS--存儲過程PROCEDURE UPDATE_SAL(NAME VARCHAR2, NEWSAL NUMBER) ISBEGINUPDATE EMP SET SAL = NEWSAL WHERE ENAME = NAME;COMMIT;END;--函數FUNCTION ANNUAL_INCOME(NAME VARCHAR2) RETURN NUMBER ISANNUAL_SALARY NUMBER;BEGINSELECT SAL * 12 + NVL(COMM, 0) INTO ANNUAL_SALARY FROM EMP WHERE ENAME = NAME;RETURN ANNUAL_SALARY;END; END; /調用:
exec sp_package.update_sal('SCOTT', 8888); --調用函數 var income NUMBER; CALL sp_package.ANNUAL_INCOME('SCOTT') INTO:income; print income;6:變量:
1)、標量類型(scalar)
pl/sql中定義變量和常量的語法如下:
identifier [constant] datatype [not null] [:=| default expr]
identifier: 名稱
constant:指定常量。需要指定它的初始值,且其值是不能改變的
datatype:數據類型
not null:指定變量值不能為null
:= 給變量或是常量指定初始值
default 用于指定初始值
expr :指定初始值的pl/sql表達式,可以是文本值、其它變量、函數等。
使用%type類型可以避免數字或值錯誤( 超過了5個字符的話,就會有“ORA-06502: PL/SQL: 數字或值錯誤 :? 字符串緩沖區太小”錯誤 ) : 標識符名 表名.列名%type;
2)、復合類型(composite):
pl/sql記錄類似結構體:
set serveroutput on; --打開輸出選項
DECLARE
? --定義一個pl/sql記錄類型emp_record_type,
? --類型包含3個數據NAME, SALARY, TITLE。說白了,就是一個類型可以存放3個數據,主要是為了方便管理
? TYPE EMP_RECORD_TYPE IS RECORD(
??? NAME?? EMP.ENAME%TYPE,
??? SALARY EMP.SAL%TYPE,
??? TITLE? EMP.JOB%TYPE);
? --定義了一個sp_record變量,這個變量的類型是emp_record_type
? SP_RECORD EMP_RECORD_TYPE;
BEGIN
? SELECT ENAME, SAL, JOB INTO SP_RECORD FROM EMP WHERE EMPNO = 7788;
? DBMS_OUTPUT.PUT_LINE('員工名:' || SP_RECORD.NAME || '工資:' || SP_RECORD.SALARY);
END;
/
pl/sql表:類似數組
方法一(推薦):
set serveroutput on; --打開輸出選項
DECLARE
? --定義了一個pl/sql表類型sp_table_type,該類型是用于存放EMP.ENAME%TYPE
? --INDEX BY VARCHAR2(20)表示下標是字符串
? TYPE SP_TABLE_TYPE IS TABLE OF EMP.ENAME%TYPE INDEX BY VARCHAR2(20);
? --定義了一個sp_table變量,這個變量的類型是sp_table_type
? SP_TABLE SP_TABLE_TYPE;
BEGIN
? SELECT ENAME, sal INTO SP_TABLE('ename'), SP_TABLE('sal') FROM EMP WHERE EMPNO = 7788;
? DBMS_OUTPUT.PUT_LINE('員工名:' || SP_TABLE('ename')||'工資:'||SP_TABLE('sal'));
END;
/
方法二:
set serveroutput on; --打開輸出選項
DECLARE
? --定義了一個pl/sql 表類型sp_table_type,該類型是用于存放EMP.ENAME%TYPE
? --index by binary_integer表示下標是整數
? TYPE SP_TABLE_TYPE IS TABLE OF EMP.ENAME%TYPE INDEX BY BINARY_INTEGER; --注意binary_integer如果換為integer就會報錯,知道的朋友歡迎告訴我下
? --定義了一個sp_table變量,這個變量的類型是sp_table_type
? SP_TABLE SP_TABLE_TYPE;
BEGIN
? SELECT ENAME,sal INTO SP_TABLE(-1),SP_TABLE(-2) FROM EMP WHERE EMPNO = 7788;
? DBMS_OUTPUT.PUT_LINE('員工名:' || SP_TABLE(-1)||'工資:'||SP_TABLE(-2));
END;
/
3)、參照類型(reference)
參照變量——ref cursor游標變量:
SET serveroutput ON;
DECLARE
? --定義游標
? TYPE sp_emp_cursor IS REF CURSOR;
? --定義一個游標變量
? sp sp_emp_cursor;
? --定義變量
? v_ename emp.ename%TYPE;
? v_sal emp.sal%TYPE;
BEGIN
? OPEN sp FOR SELECT e.ename, e.sal FROM emp e WHERE e.deptno=10;
? --方法一 loop循環
? /*
? LOOP
? FETCH sp INTO v_ename, v_sal;
? EXIT WHEN sp%NOTFOUND;
? DBMS_OUTPUT.PUT_LINE('名字:' || V_ENAME || ' 工資:' || V_SAL);
? END LOOP;*/
? --方法二 while循環
? /*
? WHILE 1=1 LOOP
??? FETCH sp INTO v_ename, v_sal;
??? EXIT WHEN sp%NOTFOUND;
??? DBMS_OUTPUT.PUT_LINE('名字:' || V_ENAME || ' 工資:' || V_SAL);
? END LOOP;*/
? --方法三 for循環
? FOR cur IN (SELECT e.ename, e.sal FROM emp e WHERE e.deptno=10) LOOP
??? DBMS_OUTPUT.PUT_LINE('名字:' || cur.ename || ' 工資:' || cur.sal);
? END LOOP;
END;
/
4)、lob(large object)
7:pl/sql控制結構
條件分支語句: if—then,if–then–else,if–then–else if–then
1)、簡單的條件判斷if–then
問題:編寫一個過程,可以輸入一個雇員名,如果該雇員的工資低于2000,就給該員工工資增加10%。
2)、二重條件分支 if–then–else
問題:編寫一個過程,可以輸入一個雇員名,如果該雇員的補助不是0就在原來的基礎上增加100;如果補助為0就把補助設為200;
3)、多重條件分支 if–then–ELSIF–then
問題:編寫一個過程,可以輸入一個雇員編號,如果該雇員的職位是PRESIDENT就給他的工資增加1000,如果該雇員的職位是MANAGER 就給他的工資增加500,其它職位的雇員工資增加200。
循環語句-loop:
CREATE OR REPLACE PROCEDURE SP_PRO6(SPNAME VARCHAR2) IS--定義 :=表示賦值V_NUM NUMBER := 1; BEGINLOOPINSERT INTO USERS VALUES (V_NUM, SPNAME);--判斷是否要退出循環EXIT WHEN V_NUM = 10;--自增V_NUM := V_NUM + 1;END LOOP;COMMIT; END; /--調用存儲過程 EXEC SP_PRO6('ALLEN');循環語句-while循環:
CREATE OR REPLACE PROCEDURE SP_PRO6(SPNAME VARCHAR2) IS--定義 :=表示賦值V_NUM NUMBER := 11; BEGINWHILE V_NUM <= 20 LOOP--執行INSERT INTO USERS VALUES (V_NUM, SPNAME);V_NUM := V_NUM + 1;END LOOP;COMMIT; END; /--調用存儲過程 EXEC SP_PRO6('ALLEN');--調用存儲過程
EXEC SP_PRO6('ALLEN');
循環語句-for循環:
CREATE OR REPLACE PROCEDURE SP_PRO6 IS--注意如果無參記得不要加() BEGINFOR I IN REVERSE 1 .. 10 LOOP --REVERSE反轉函數,表示I從10到1遞減,去掉REVERSE表示I從1到10遞增INSERT INTO USERS VALUES (I, 'shunping');END LOOP; END; /--調用存儲過程 EXEC SP_PRO6;順序控制語句-goto、null:
set serveroutput on; DECLAREI INT := 1; BEGINLOOPDBMS_OUTPUT.PUT_LINE('輸出i=' || I);IF I = 1 THENGOTO END_LOOP;END IF;I := I + 1;END LOOP;<<END_LOOP>>DBMS_OUTPUT.PUT_LINE('循環結束'); END; / SET serveroutput ON; DECLAREV_SAL EMP.SAL%TYPE;V_ENAME EMP.ENAME%TYPE; BEGINSELECT ENAME, SAL INTO V_ENAME, V_SAL FROM EMP WHERE EMPNO = &NO;IF V_SAL < 3000 THENUPDATE EMP SET COMM = SAL * 0.1 WHERE ENAME = V_ENAME;dbms_output.put_line('1111');ELSENULL;dbms_output.put_line('2222');--不會被執行END IF; END; /8:pl/sql分頁
一、無返回值的存儲過程
古人云:欲速則不達,為了讓大家伙比較容易接受分頁過程編寫,我還是從簡單到復雜,循序漸進的給大家講解。首先是掌握最簡單的存儲過程,無返回值的存儲過程。 案例:現有一張表book,表結構如下:書號、書名、出版社。
CREATE TABLE book(ID NUMBER(4),book_name VARCHAR2(30),publishing VARCHAR2(30) );請寫一個過程,可以向book表添加書,要求通過java程序調用該過程。
--注意:in->表示這是一個輸入參數,默認為in --out->表示一個輸出參數 CREATE OR REPLACE PROCEDURE ADD_BOOK(ID IN NUMBER,NAME IN VARCHAR2,PUBLISHING IN VARCHAR2) IS BEGININSERT INTO BOOK VALUES (ID, NAME, PUBLISHING);COMMIT; END; /??java程序調用該存儲過程的代碼
package junit.test;import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager;/** * 調用一個無返回值的存儲過程* * @author jiqinlin**/ public class ProcedureTest {public static void main(String[] args) {try {// 1.加載驅動Class.forName("oracle.jdbc.driver.OracleDriver");// 2.得到連接Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "oracle");// 3.創建CallableStatementCallableStatement cs = ct.prepareCall("call ADD_BOOK(?,?,?)");//給?賦值cs.setInt(1, 1);cs.setString(2, "java");cs.setString(3, "java出版社");// 4.執行cs.execute();//5、關閉cs.close();ct.close();} catch (Exception e) {e.printStackTrace();}} }?????二、有返回值的存儲過程(非列表)
案例:編寫一個存儲過程,可以輸入雇員的編號,返回該雇員的姓名。
java程序調用該存儲過程的代碼
package junit.test;import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager;/** * 調用一個無返回值的存儲過程* * @author jiqinlin**/ public class ProcedureTest {public static void main(String[] args) {try {// 1.加載驅動Class.forName("oracle.jdbc.driver.OracleDriver");// 2.得到連接Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "oracle");// 3.創建CallableStatementCallableStatement cs = ct.prepareCall("{call sp_proc(?,?)}");//給第一個?賦值cs.setInt(1,7788);//給第二個?賦值cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR);//4、執行cs.execute();//取出返回值,要注意?的順序String name=cs.getString(2);System.out.println("編號7788的名字:"+name);//5、關閉cs.close();ct.close();} catch (Exception e) {e.printStackTrace();}} }??案例擴張:編寫一個過程,可以輸入雇員的編號,返回該雇員的姓名、工資和崗位。
--輸入和輸出的存儲過程 CREATE OR REPLACE PROCEDURE SP_PROC(SPNO IN NUMBER,SPNAME OUT VARCHAR2,SPSAL OUT NUMBER,SPJOB OUT VARCHAR2) IS BEGINSELECT ENAME, SAL, JOB INTO SPNAME, SPSAL, SPJOB FROM EMP WHERE EMPNO = SPNO; END; /java程序調用該存儲過程的代碼
package junit.test;import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager;/** * 調用一個無返回值的存儲過程* * @author jiqinlin**/ public class ProcedureTest {public static void main(String[] args) {try {// 1.加載驅動Class.forName("oracle.jdbc.driver.OracleDriver");// 2.得到連接Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "oracle");// 3.創建CallableStatementCallableStatement cs = ct.prepareCall("{call sp_proc(?,?,?,?)}");//給第一個?賦值cs.setInt(1,7788);//給第二個?賦值cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR);//給第三個?賦值cs.registerOutParameter(3,oracle.jdbc.OracleTypes.DOUBLE);//給第四個?賦值cs.registerOutParameter(4,oracle.jdbc.OracleTypes.VARCHAR);//4、執行cs.execute();//取出返回值,要注意?的順序String name=cs.getString(2);double sal=cs.getDouble(3);String job=cs.getString(4);System.out.println("編號7788的名字:"+name+",職位:"+job+",薪水:"+sal+"");//5、關閉cs.close();ct.close();} catch (Exception e) {e.printStackTrace();}} }三、有返回值的存儲過程(列表[結果集])
案例:編寫一個存儲過程,輸入部門號,返回該部門所有雇員信息。
該題分析如下:由于oracle存儲過程沒有返回值,它的所有返回值都是通過out參數來替代的,列表同樣也不例外,但由于是集合,所以不能用一般的參數,必須要用pagkage了。所以要分兩部分:
1)、建立一個包,在該包中我們定義類型test_cursor,它是個游標。
2)、建立存儲過程。
CREATE OR REPLACE PROCEDURE SP_PROC(SPNO IN NUMBER,P_CURSOR OUT TESTPACKAGE.TEST_CURSOR) IS BEGINOPEN P_CURSOR FORSELECT * FROM EMP WHERE DEPTNO = SPNO; END SP_PROC; /??3)、如何在java 程序中調用該過程
package junit.test;import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet;/** * 調用一個無返回值的存儲過程* * @author jiqinlin**/ public class ProcedureTest {public static void main(String[] args) {try {// 1.加載驅動Class.forName("oracle.jdbc.driver.OracleDriver");// 2.得到連接Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "oracle");// 3.創建CallableStatementCallableStatement cs = ct.prepareCall("{call sp_proc(?,?)}");//給第一個?賦值cs.setInt(1,10);//給第二個?賦值cs.registerOutParameter(2,oracle.jdbc.OracleTypes.CURSOR);//4、執行cs.execute();//得到結果集ResultSet rs = (ResultSet) cs.getObject(2);while (rs.next()) {System.out.println(rs.getInt(1) + " " + rs.getString(2));}//5、關閉rs.close();cs.close();ct.close();} catch (Exception e) {e.printStackTrace();}} }四、編寫分頁過程
有了上面的基礎,相信大家可以完成分頁存儲過程了。
要求,請大家編寫一個存儲過程,要求可以輸入表名、每頁顯示記錄數、當前頁。返回總記錄數,總頁數,和返回的結果集。
1)、開發一個包
建立一個包,在該包中定義類型為test_cursor的游標。
java調用分頁代碼
package junit.test;import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet;/** * 調用一個無返回值的存儲過程* * @author jiqinlin* */ public class ProcedureTest {public static void main(String[] args) {try {// 1.加載驅動Class.forName("oracle.jdbc.driver.OracleDriver");// 2.得到連接Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "oracle");// 3.創建CallableStatementCallableStatement cs = ct.prepareCall("{call fenye(?,?,?,?,?,?)}");cs.setString(1, "emp"); //表名cs.setInt(2, 5); //每頁顯示記錄數cs.setInt(3, 1);//頁數// 注冊總記錄數cs.registerOutParameter(4, oracle.jdbc.OracleTypes.INTEGER); //總記錄數// 注冊總頁數cs.registerOutParameter(5, oracle.jdbc.OracleTypes.INTEGER); //總頁數// 注冊返回的結果集cs.registerOutParameter(6, oracle.jdbc.OracleTypes.CURSOR); //返回的記錄集// 4、執行cs.execute();// 得到結果集// 取出總記錄數 /這里要注意,getInt(4)中4,是由該參數的位置決定的int rowNum = cs.getInt(4);int pageCount = cs.getInt(5);ResultSet rs = (ResultSet) cs.getObject(6);// 顯示一下,看看對不對System.out.println("rowNum=" + rowNum);System.out.println("總頁數=" + pageCount);while (rs.next()) {System.out.println("編號:" + rs.getInt(1) + " 名字:" + rs.getString(2) + " 工資:" + rs.getFloat(6));}// 5、關閉//rs.close();cs.close();ct.close();} catch (Exception e) {e.printStackTrace();}} }十五:oracle例外
1)、預定義例外用于處理常見的oracle錯誤。
2)、非預定義例外用于處理預定義例外不能處理的例外。
3)、自定義例外用于處理與oracle錯誤無關的其它情況。
1:處理預定義例外
case_not_found預定義例外 :
SET SERVEROUTPUT ON; CREATE OR REPLACE PROCEDURE SP_PRO6(SPNO NUMBER) ISV_SAL EMP.SAL%TYPE; BEGINSELECT SAL INTO V_SAL FROM EMP WHERE EMPNO = SPNO;CASEWHEN V_SAL < 1000 THENUPDATE EMP SET SAL = SAL + 100 WHERE EMPNO = SPNO;WHEN V_SAL < 2000 THENUPDATE EMP SET SAL = SAL + 200 WHERE EMPNO = SPNO;END CASE; EXCEPTIONWHEN CASE_NOT_FOUND THENDBMS_OUTPUT.PUT_LINE('case語句沒有與' || V_SAL || '相匹配的條件'); END; /--調用存儲過程 SQL> EXEC SP_PRO6(7369); case語句沒有與4444相匹配的條件cursor_already_open預定義例外 :
DECLARECURSOR EMP_CURSOR ISSELECT ENAME, SAL FROM EMP; BEGINOPEN EMP_CURSOR; --聲明時游標已打開,所以沒必要再次打開FOR EMP_RECORD1 IN EMP_CURSOR LOOPDBMS_OUTPUT.PUT_LINE(EMP_RECORD1.ENAME);END LOOP; EXCEPTIONWHEN CURSOR_ALREADY_OPEN THENDBMS_OUTPUT.PUT_LINE('游標已經打開'); END; /dup_val_on_index預定義例外 :
BEGININSERT INTO DEPT VALUES (10, '公關部', '北京'); EXCEPTIONWHEN DUP_VAL_ON_INDEX THENDBMS_OUTPUT.PUT_LINE('在deptno列上不能出現重復值'); END; /invalid_cursorn預定義例外 :
DECLARECURSOR EMP_CURSOR ISSELECT ENAME, SAL FROM EMP;EMP_RECORD EMP_CURSOR%ROWTYPE; BEGIN--open emp_cursor; --打開游標FETCH EMP_CURSOR INTO EMP_RECORD;DBMS_OUTPUT.PUT_LINE(EMP_RECORD.ENAME);CLOSE EMP_CURSOR; EXCEPTIONWHEN INVALID_CURSOR THENDBMS_OUTPUT.PUT_LINE('請檢測游標是否打開'); END; /invalid_number預定義例外 :
SET SERVEROUTPUT ON; BEGINUPDATE EMP SET SAL = SAL + 'AAA'; EXCEPTIONWHEN INVALID_NUMBER THENDBMS_OUTPUT.PUT_LINE('輸入的數字不正確'); END; /no_data_found預定義例外 :
SET serveroutput ON; DECLAREV_SAL EMP.SAL%TYPE; BEGINSELECT SAL INTO V_SAL FROM EMP WHERE ENAME = 'ljq'; EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('不存在該員工'); END; /too_many_rows預定義例外 :
DECLAREV_ENAME EMP.ENAME%TYPE; BEGINSELECT ENAME INTO V_ENAME FROM EMP; EXCEPTIONWHEN TOO_MANY_ROWS THENDBMS_OUTPUT.PUT_LINE('返回了多行'); END; /zero_divide預定義例外 : 當執行2/0語句時,則會觸發該例外
value_error預定義例外 : 當在執行賦值操作時,如果變量的長度不足以容納實際數據,則會觸發該例外value_error
login_denied : 當用戶非法登錄時,會觸發該例外
not_logged_on:如果用戶沒有登錄就執行dml操作,就會觸發該例外
storage_error:如果超過了內存空間或是內存被損壞,就觸發該例外
timeout_on_resource:如果oracle在等待資源時,出現了超時就觸發該例外
2:非預定義例外:非預定義例外用于處理與預定義例外無關的oracle錯誤。使用預定義例外只能處理21個oracle 錯誤,而當使用pl/sql開發應用程序時,可能會遇到其它的一些oracle錯誤。比如在pl/sql塊中執行dml語句時,違反了約束規定等等。
3:處理預定義例外: 預定義例外和自定義例外都是與oracle錯誤相關的,并且出現的oracle 錯誤會隱含的觸發相應的例外;而自定義例外與oracle 錯誤沒有任何關聯,它是由開發人員為特定情況所定義的例外.
CREATE OR REPLACE PROCEDURE EX_TEST(SPNO NUMBER) IS BEGINUPDATE EMP SET SAL = SAL + 1000 WHERE EMPNO = SPNO; END; /--調用存儲過程, EXEC EX_TEST(56); CREATE OR REPLACE PROCEDURE EX_TEST(SPNO NUMBER) IS --定義一個例外 MYEX EXCEPTION; BEGIN --更新用戶sal UPDATE EMP SET SAL = SAL + 1000 WHERE EMPNO = SPNO; --sql%notfound 這是表示沒有update --raise myex;觸發myex IF SQL%NOTFOUND THEN RAISE MYEX; END IF; EXCEPTION WHEN MYEX THEN DBMS_OUTPUT.PUT_LINE('沒有更新任何用戶'); END; /轉載于:https://my.oschina.net/zhuqingbo0501/blog/1815912
總結
以上是生活随笔為你收集整理的总结:Oracle快速入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Shell脚本编程----变量的使用
- 下一篇: (四)maven之查找jar包坐标,选择