Java SSM入門(十三)——Oracle(二)(PLSQL)
iwehdio的部落格園:https://www.cnblogs.com/iwehdio/
1、檢視和索引
- 檢視:提供一個查詢的視窗,所有資料來自原表。改變檢視資料也會修改原表。
- 建立檢視必須有dba許可權。
- 跨使用者查詢建立表:
create table emp as select * from scott.emp
。 - 建立檢視:
create view v_emp as select ename,job from emp
。 - 查詢檢視:
select * from v_emp
。 - 修改檢視:
update v_emp set job='CLERK' where ename = 'ALLEN'
,+ commit。 - 檢視的作用:
- 遮蔽一些敏感的欄位。
- 保證總部和分部的資料及時統一。
- 索引:在表的列上構建一個二叉樹,達到大幅增加查詢效率的目的,但是會影響增刪改的效率。
- 單列索引:
- 建立:
create index idx_ename on emp(ename)
。 - 單列索引觸發規則:條件必須是索引列中的原始值。單行函式、模糊函式不會觸發索引。
- 建立:
- 複合索引:
- 建立:
create index idx_enamejob on emp(ename, job)
。 - 複合索引中第一列為優先檢索列,如果要觸發複合索引,必須包含優先檢索列中的原始值。用 or 做查詢條件時不觸發。
- 又是單列索引又是複合索引,先觸發單列索引。
- 建立:
2、PLSQL
-
PLSQL語言是對sql語言的擴充套件,使得其具有過程化程式設計的特性。主要用來編寫儲存過程和儲存函式等。
-
宣告方法:
declare -- 定義變數 begin -- 處理業務邏輯 end;
-
賦值操作:
-
定義變數必須在declare 下。
-
賦值數字:
i number(2) := 10;
。 -
賦值字串:
s varchar2(10) := '名'
。 -
輸出:
dbms_output.put_line(i)
。 -
輸入:
i number(3) := &i
-
賦值指定表中列的型別(引用型變數):
declare ena emp.ename%type; begin select ename into ena from emp where empno =7788; dbms_output.put_line(ena); end;
-
賦值指定表中某一行的型別(記錄性變數):
declare emprow emp%rowtype; begin select * into emprow from emp where empno =7788; dbms_output.put_line(emprow.ename || '的工作是' || emprow.job); end;
-
-
流程控制語句:
-
判斷語句格式:
declare -- 定義變數 begin if i <18 then dbms_output.put_line('a') elsif i <60 then dbms_output.put_line('b') else dbms_output.put_line('c') end if; end;
-
迴圈語句格式:
-- 方法1 while i <11 loop dbms_output.put_line(i) i := i+1; end loop; -- 方法2 loop exit when i >10; dbms_output.put_line(i) i := i+1; end loop; -- 方法3 for i in 1..10 loop dbms_output.put_line(i); end loop;
-
-
PLSQL中的遊標:
-
類似於集合,可以儲存多行記錄。
-
輸出emp表中所有員工的姓名:
declare cursor c1 is select * from emp; emprow emp%rowtype; begin open c1; loop fetch c1 into emprow; exit when c1%notfound; dbms_output.put_line(emprow.ename); end loop; close c1; end;
-
更改指定部門員工的工資:
declare cursor c2(eno emp.deptno%type) is select empno from emp where deptno=eno; en emp.empno%type; begin open c2(10); loop fetch c2 into en; exit when c2%notfound; update emp set sal=sal+100 where empno=en; commit; end loop; close c2; end;
-
-
儲存過程:
-
就是提前已經編譯好的一段PLSQL語言,放置在資料庫端,可以直接被呼叫。一般都是固定步驟的業務。
-
語法:
create [or replace] procedure 過程名[(引數名 in/out 資料型別)] as begin -- 業務程式; end;
-
給指定員工漲工資的儲存過程:
create or replace procedure p1(eno emp.empno%type) is begin update emp set sal=sal+100 where empno = eno; commit; end;
-
測試儲存過程:
declare begin p1(7788); end;
-
out 型別引數:
- 定義:
yearsal out number
。 - 獲取輸出:
p1(7788,yearsal)
。 - 涉及到 into 或 := 賦值的引數都用out 來修飾。
- 定義:
-
-
儲存函式:
-
一般來說,過程和函式的區別在於函式可以有一個返回值,而過程沒有返回值。
-
語法:
create or replace function 函式名(引數名 資料型別) return 資料型別 is 結果變數 資料型別; begin --業務程式 return(結果變數); end 函式名;
-
計算指定員工年薪的儲存函式:
create or replace function f_year(eno emp.empno%type) return number is s number(10); begin select sal*12 + nvl(comm,0) into s from emp where empno=eno; return s; end;
-
測試儲存函式:
declare s number(10); begin s:=f_year(7788); dbms_output.put_line(s); end;
-
-
儲存過程和儲存函式的區別:
- 語法區別:關鍵字不同。
- 儲存函式比儲存過程多了兩個return。
- 本質區別:儲存函式有返回值,而儲存過程沒有返回值。
- 如果儲存過程需要返回值,需要out 型別引數。但本質也不是真有返回值,而是在儲存過程內部給out 引數賦值。
- 儲存函式可以利用有返回值的特性,來自定義函式(如聚合函式),而儲存過程不能用來自定義函式。
-
觸發器:
- 制定一個規則,在進行增刪改操作的時候,只要滿足規則,自動觸發,無需呼叫。
- 分為語句級觸發器和行級觸發器。
- 行級觸發器中含有
for each row
,為了使用:oid 或 :new 物件。 - 插入操作時,:old 所有欄位都是空,:new 是將要插入的資料。
- 更新操作時,:old 是更新前該行的值,:new 是更新後的值。
- 刪除操作時,:old 是刪除前該行的值,:new 所有欄位為空。
-
建立觸發器:
-
語句級觸發器:插入一條記錄,輸出一個新員工入職。
create or replace trigger t1 after -- 在操作前還是操作後 insert -- 對應的操作 on person -- 對應的表 declare begin dbms_output.put_line('入職'); end;
-
測試觸發器:
insert into person values (2,'小綠'); commit; select * from person;
-
行級觸發器:不能給員工降薪。
create or replace trigger t2 before -- 在操作之前 update on emp for each row declare begin if :old.sal > :new.sal then raise_application_error(-20001,'不能降薪'); end if; end;
-
測試觸發器:
update emp set sal = sal -100 where empno = 7788; commit; select * from emp where empno = 7788;
-
-
觸發器實現主鍵自增:
-
在使用者插入操作之前,拿到即將插入的資料,給資料的主鍵列賦值。使用序列。
create or replace trigger auid before insert on person for each row declare begin select s_person.nextval into :new.pid from dual; end;
-
測試觸發器:
insert into person (pname) values ('a'); commit; select * from person;
-
3、Java呼叫儲存過程/函式
-
Oracle10g的驅動包為ojdbc14.jar,Oracle11g的驅動包為ojdbc6.jar。
-
maven 座標:
<dependencies> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc14</artifactId> <version>10.2.0.4.0</version> <scope>runtime</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.10</version> <scope>test</scope> </dependency> </dependencies>
-
測試查詢:
@Test public void test1() throws Exception { //載入資料庫驅動 Class.forName("oracle.jdbc.driver.OracleDriver"); //獲取連線 Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@iwehdio:1521:orcl", "iwehdio0", "hhh"); //得到預編譯物件並賦值 PreparedStatement preparedStatement = connection.prepareStatement("select * from person where pid = ?"); preparedStatement.setObject(1, "21"); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next()) { System.out.println(resultSet.getString("pname")); } resultSet.close(); preparedStatement.close(); connection.close(); }
-
呼叫儲存過程:
@Test public void test2() throws Exception { //載入資料庫驅動 Class.forName("oracle.jdbc.driver.OracleDriver"); //獲取連線 Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@iwehdio:1521:orcl", "scott", "tiger"); //得到物件並賦值 CallableStatement callableStatement = connection.prepareCall("{call p1(?)}"); callableStatement.setObject(1, "7788"); callableStatement.execute(); callableStatement.close(); connection.close(); }
-
呼叫儲存函式:
@Test public void test3() throws Exception { //載入資料庫驅動 Class.forName("oracle.jdbc.driver.OracleDriver"); //獲取連線 Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@iwehdio:1521:orcl", "scott", "tiger"); //得到物件並賦值 CallableStatement callableStatement = connection.prepareCall("{? = call f_year(?)}"); callableStatement.setObject(2, "7788"); callableStatement.registerOutParameter(1, OracleTypes.NUMBER); callableStatement.execute(); //獲得第一個引數並輸出 System.out.println(callableStatement.getObject(1)); callableStatement.close(); connection.close(); }
-
呼叫儲存過程時,sql語句寫
{call 過程名(引數)}
。 -
呼叫儲存函式時,sql語句寫
{? = call 函式名(引數)}
。- 儲存函式的第一個?屬於引數,需要註冊指定為Oracle中的那個型別。
- 使用
.getObject(第幾個)
方法獲得返回值。