1. 程式人生 > >oracle的學習筆記(轉)

oracle的學習筆記(轉)

Oracle的介紹

1. Oracle的創始人----拉里•埃裡森

2. oracle的安裝

WinServer2003映象掛載
Oracle安裝步驟
[連線Oracle步驟](](https://img2018.cnblogs.com/blog/1224549/201810/1224549-20181017214101430-1777213931.png)
亂碼解決

3. oracle的體系結構:
    資料庫: 在oracle中,資料庫只有一個,就是全域性資料庫(orcl)---不同模組的表結構,通過使用者區分
    例項
    表空間(datafile 'C:/db1.dbf'): 一個邏輯概念,就是用來儲存資料庫表的 使用者 資料檔案: 用來具體儲存資料資訊的,磁碟上的具體檔案 

準備工作:

1. 建立表空間:
    create tablespace 名稱
    datafile 'c:\itheima.dbf'
    size 100m -- 大小 autoextend on -- on 表示自動擴充 next 10m -- 每次擴充的大小 2. 刪除表空間 drop tablespace 名稱; 3. 建立使用者: create user 使用者名稱 identified by 使用者名稱 -- 設定密碼 default tablespace 使用者名稱; -- 指定使用者所屬的表空間 4. 使用者授權: connect -- 連線角色 resource --開發者角色 dba --超級管理員角色 grant dba to 使用者名稱 -- 賦予許可權

表的基本操作:

常用資料型別: varchar, varchar2,date,number(10,2)==>10是總長度,2表示小數點後的位數 1. 建立表 create table person( pid number(20), pname varchar2(10) ); 2. 修改表 1. 新增一列 alter table person add gender number(1); 2. 新增多列 alter table person add (gender number(1),(age number(3))); 3. 修改列型別: alter table person modify gender char(1); 4. 修改列名稱: alter table person rename column gender to sex; 5. 刪除一列: alter table person drop column sex; 

增刪改基本操作:

1. 增加
    insert into person (pid,pname) values (1,'小明'); commit; 2. 修改 update person set pname = '小馬' where pid = 1; commit; 3. 刪除 delete from person; ---刪除表中全部記錄 drop table person; ---刪除表結構 truncate table person; ---先刪除表,再次建立表,效果等同於刪除表中的全部記錄

修改字符集:

select userenv('language') from dual; 配置環境變數: NLS_LANG 值為查詢出的結果

序列:預設從1開始,依次遞增,為主鍵賦值使用(Mysql的自增)

1. 建立
    create sequence s_person;
2. 檢視(序列不屬於任何一張表,但是可以邏輯和表做繫結)
    select s_person.nextval from dual; --- dual表示的是虛表,補全語法,沒有任何意義 select s_person.currval from dual; 3. 基本使用: insert into person (pid,pname) values (s_person.nextval,'王智'); 

解鎖使用者

1. alter user scott account unlock;  ------------> 解鎖scott使用者,如果在安裝的時候已經解鎖,可以不需要設定 2. alter user scott identified by tiger; --解鎖scott使用者的密碼【此句也可以用來重置密碼】 

單行函式:作用於一行,返回一個值

1. 字元函式
    select upper('yes') from dual; ==== 小寫變大寫
    select lower('yes') from dual; ==== 大寫變小寫 CONCAT : 拼接兩個字串,與 || 相同 select concat('Hello',' Oracle') from dual; INITCAP : 將字串的第一個字母變為大寫 select INITCAP('hello') from dual; 2. 數值函式 select round(26.18, 1) from dual; ==== 四捨五入,後面的引數表示保留的小數點後的位置,如果是-1呢?自行測試 select trunc(26.18, 1) from dual;直接擷取 select mod(10, 3) from dual; ==== 求餘數 3. 日期函式: select sysdate - e.hiredate from emp e; === 查詢emp表所有員工入職到現在多少天了,sysdate表示當前時間 select sysdate + 1 from dual; === 算出明天此刻(運算操作都是針對天) select months_between(sysdate,e.hiredate) from emp e; 查詢emp表所有員工入職到現在多少月了 如果算年呢? 禮拜呢? 考慮使用上面兩個例子的基礎上修改 select months_between(sysdate,e.hiredate) / 12 from emp e; select (sysdate - e.hiredate) / 7 from emp e; 4. 轉換函式: select to_char(sysdate,'fm yyyy-mm-dd hh24:mi:ss') from dual; === 日期轉字串,去掉fm試試?去掉24試試? select to_date('2018-6-7 16:39:50','fm yyyy-mm-dd hh24:mi:ss') from dual; === 字串轉日期 5. 通用函式: select e.sal * 12 + nvl(e.comm,0) from emp e; === 算出emp表中所有員工的年薪(由於comm獎金有null值,所以需要排除掉null值,nvl表示判斷第一個數是否為null,是則返回第二個引數,不是返回第一個引數) select e.sal * 12 + nvl2(e.comm,e.comm,0) from emp e;=== 第一個引數是判定值,第二個是不為null的返回值,第三個是為null的返回值 

條件表示式(1和2是mysql和oracle通用):

1. 給emp表中員工起中文名稱: 
    select e.ename,
        case e.ename 
            when 'SMITH' then '曹操' when 'WARD' then '諸葛' else '無名' end from emp e; 2. 判斷emp表中員工工資,高於3000,顯示高收入,1500-3000中等,其餘低等 select e.ename, case when e.ename > 3000 then '高收入' when e.ename > 1500 then '中等收入' else '低收入' end from emp e; 3. oracle專用: select e.ename, decode(e.ename 'SMITH' , '曹操' , 'WARD' , '諸葛' , '無名') 中文名 from emp e; 中文名錶示起別名,在oracle中,除了起別名,都用單引號,別名可以不用引號或者使用雙引號

多行/聚合函式:作用於多行,返回一個值

select count(1) from emp; -- 查詢總數量 select sum(sal) from emp; -- 工資總和 select max(sal) from emp; -- 最大工資 select min(sal) from emp; -- 最低工資 select avg(sal) from emp; -- 平均工資

分組查詢

1. 查詢出每個部門的平均工資:
    select e.deptno,avg(e.sal)
    from emp e
    group by e.deptno 2. select [欄位列表] from 表名 where 條件 group by 欄位 having 條件; --- 欄位列表: group by之後的欄位和聚合統計函式 3. where和having的區別: where: 在group by分組之前進行條件的過濾 having: 在group by分組之後進行條件的過濾 

多表查詢

1. 笛卡爾積(沒有任何意義)
2. 等值連線
    select * from emp e, dept d where e.deptno = d.deptno;
3. 內連線
    select * from emp e inner join dept d on e.deptno = d.deptno; 4. 外連線(左/右) select * from emp e left join dept d on e.deptno = d.deptno; select * from emp e right join dept d on e.deptno = d.deptno; select * from emp e full join dept d on e.deptno = d.deptno;

自連線查詢:

關鍵在於起別名
查詢出員工的姓名和員工領導的姓名
select e1.ename. e2.ename from emp e1. emp e2 where e1.mgr = e2.empno;

子查詢(儘量使用多表查詢,不要使用子查詢-----sql優化)

子查詢返回一個值(=)
    
子查詢返回一個集合(in)
    
子查詢返回一張表(子查詢,把查詢出的結果看作一個表起別名來使用)
    

Oracle的分頁:

rownum偽列,配合三層巢狀子查詢完成 
條件中的rownum是從1開始的,不能設定大於某個數字,所以考慮使用別名
select * from (
    select rownum rn,t.* from ( select e.* from emp e order by sal desc ) t where rownum < 11 ) where rn > 5;

檢視和索引

檢視:
    1. 檢視的概念:
        提供一個查詢視窗,所有資料來自於原表
    2. 檢視的操作:
        建立檢視(必須有dba許可權)
            create or replace view v_name as 查詢語句;
        使用檢視    
            select * from v_name; 檢視修改欄位(可以修改,但是不推薦) update v_emp set job='CLERK' where ename='ALLEN'; commit; 建立只讀檢視 create view v_name as 查詢語句 with read only; 3. 檢視的作用: 1. 檢視可以遮蔽掉敏感欄位(資料安全) 2. 方便操作,資料的統一 4. 建立表(將查詢結果存入表中): create table table_name as 查詢語句; ----- create table emp as select * from scott.emp; 索引: 1. 索引的概念: 在表的列上構建一個二叉樹,達到大幅度提高查詢效率的目的,但是索引會影響增刪改的效率 2. 索引建立的時機: 1. 資料量大的表 2. 經常查詢的表 3. 針對什麼樣的欄位建立索引: 經常在where條件後的欄位 4. 索引的分類: * 單列索引 1. 建立: create index idx_name on table_name(column_name); 2. 觸發規則(單行函式,模糊查詢都會影響索引的觸發,也就是不會觸發索引): 單列索引觸發規則,條件必須是索引列中的原始值 * 複合索引 1. 建立: create index idx_name on table_name(column_name1,column_name2); 2. 觸發規則: 複合索引第一列為優先檢索列. 如果要觸發複合索引,必須包含有優先檢索列中的原始值

pl/sql程式語言

1. 概念:
    pl/sql程式語言對sql語言的擴充套件,使得sql語言具有過程化程式設計的特性.
    主要用來編寫儲存過程和儲存函式的.
2. 宣告方法:
    declare
        i number(2) := 10; ====> 定義普通變數 s varchar2(10) := '小明'; ena table_name.column_name%type; ====> 定義引用型變數,型別與表的欄位型別一樣 emprow emp%rowtype; ====> 記錄型變數 begin dbms_output.put_line(i); ====> 輸出 dbms_output.put_line(s); select ename into ena from emp where empno = 1; ====> 使用查詢語句為變數賦值 dbms_output.put_line(ena); select * into emprow from emp where empno = 1; -- 不能直接輸出emprow,輸出emprow.column來輸出內容 dbms_output.put_line(emprow.ename || '工作為' || emprow.job); end; 3. if判斷: declare i number(3) := &i; ====> 輸入值,將值給i begin if 條件1 then 條件1滿足執行的邏輯 elsif 條件2 then 條件2滿足執行的邏輯 else 條件都不滿足執行的邏輯 end if; end; -------------------------------------------- declare -- 輸入值 i number(2) := &i; begin if i < 18 then dbms_output.put_line('未成年'); elsif i < 30 then dbms_output.put_line('青年'); elsif i < 50 then dbms_output.put_line('壯年'); else dbms_output.put_line('老年'); end if; end; 4. loop迴圈: 1. while迴圈: declare i number(2) := 1; ===> 如果i遞增越界,會報異常 begin while 條件 loop 執行邏輯(輸出等); 條件變數的改變; ===> i := i+1; end loop; end; 2. exit迴圈(掌握掌握): declare i number(2) := 1; begin loop exit when 條件; ===> 條件符合,退出迴圈 執行邏輯(輸出等); 條件變數的改變; end loop; end; 3. for迴圈 decalre begin for i in 1..10 loop ===> 兩個點代表範圍 執行邏輯; end loop; end; 5. 遊標的使用: 遊標: 可以存放多個物件,多行記錄(臨時存放多行資料). declare cursor c1 is select * from emp; ====> 定義遊標 emprow emp%rowtype; begin open c1; ===> 開啟遊標 loop fetch c1 into emprow; ====> 獲取遊標中的一行記錄 exit when c1%notfound; ====> 查詢不到物件的時候自動退出(notfound是遊標中的屬性,用來判斷是否還有資料) dbms_output.put_line(emprow.ename); end loop; close c1; ===> 關閉遊標 end; -------------------------------------------------------- 為指定部門漲工資 declare cursor c3(dno emp.deptno%type) is select empno from emp where deptno = dno; eno emp.empno%type; begin open c3(20); loop fetch c3 into eno; exit when c3%notfound; update emp set sal=sal + 100 where empno = eno; commit; end loop; close c3; end;

儲存過程和儲存函式

1. 儲存過程(提高複用性,提高業務邏輯的執行效率):
    1. 概念: 提前已經編譯好的一段pl/sql片段,放置在資料庫端,可以直接被呼叫,這一段pl/sql一般都是固定步驟的業務.
    2. 建立語法(引數型別不能加長度):
        create or replace procedure 過程名(引數名 in/out 資料型別) ===> in可以省略 AS/IS 變數的宣告; begin PLSQL子程式體; end; ------------------------------------------------------ 給指定員工漲工資: create or replace procedure p1(eno in emp.empno%type) as begin update emp set sal=sal+100 where empno = eno; commit; end; 3. 呼叫儲存過程(兩種) 通過PL/SQL進行呼叫 declare begin p1(1); end; 通過java程式呼叫 2. 儲存函式: 1. 建立(返回的引數型別和引數的型別不能加長度): create or replace function fun_name(引數名 in type,....) return 引數型別 is 變數名 變數型別; begin 執行邏輯; return 結果變數; end 函式名; ---------------- 儲存函式算年薪 create or replace function fun_salyear(eno in number) return number is yearsal number(10); begin select sal*12+nvl(comm,0) into yearsal from emp where empno = eno; return yearsal; end; 2. 呼叫: 儲存函式在呼叫的時候返回值必須接受. declare 返回變數的宣告 begin 返回變數 := 函式名(引數); 邏輯處理; end; ----------------- declare yearsal number(10); begin yearsal := fun_salyear(7788); dbms_output.put_line(yearsal); end; 3. out引數的使用: 儲存過程算年薪: --------- 使用儲存過程測試out引數的使用 create or replace procedure pro_yearsal(eno in emp.empno%type,yearsal out number) is begin select sal*12+nvl(comm,0) into yearsal from emp where empno = eno; end; ----------- 測試 declare yearsal number(10); begin pro_yearsal(7788,yearsal); dbms_output.put_line(yearsal); end; 另外一種寫法: ---- 儲存過程計算年薪的另外一種寫法 create or replace procedure pro_yearsal2(eno in emp.empno%type,yearsal out number) is s number(10); c emp.comm%type; begin select sal*12,nvl(comm,0) into s,c from emp where empno = eno; yearsal := s + c; end; ---- 呼叫儲存過程 declare yearsal number(10); begin pro_yearsal2(7788,yearsal); dbms_output.put_line(yearsal); end; 4. in和out的引數區別是什麼? in: 輸入的引數(預設值) out: 輸出引數(對外暴露的變數) 呼叫的時候需要傳入的值就是輸入引數,呼叫的時候不需要傳入值並且在執行完成後還需要獲取的值是輸出引數. 5. 儲存過程和儲存函式的區別 1. 語法區別: * 關鍵字不一樣: procedure和function * 儲存函式比儲存過程多了兩個return 2. 本質區別: 儲存函式有返回值,儲存過程沒有返回值. > 實際開發中,還是儲存過程用的比較多. 

觸發器

1. 觸發器的概念:
    制定一個規則,在我們做增刪改操作前(before)後(after),只要滿足規則,自動觸發,無需呼叫.
2. 分類
    語句級觸發器: 在insert/update/delete語句的時候觸發一次,不包含有for each row的就是語句級觸發器. 行級觸發器: 在insert/update/delete語句的時候影響多少行就觸發多少次,包含有for each row的就是行級觸發器. 3. 偽記錄變數: 一般在修改的刪除的時候用的多,用於備份,下面兩個只能用於行級觸發器. :old,獲取操作前的資料 :new,獲取操作後的資料 4. 建立語句級觸發器 create or replace trigger trigger_name before/after insert/update/delete on table_name declare begin 邏輯的執行; end; ---------------------------------------------- ---- 建立語句級觸發器 create or replace trigger tri_name after insert on person declare begin dbms_output.put_line('插入一條資料'); end; ---- 滿足條件即可觸發觸發器 insert into person values(s_person.nextval,'b'); 5. 觸發器的觸發: 只要滿足條件就觸發. 6. 建立行級別的觸發器: create or replace trigger trigger_name before/after insert/update/delete on table_name for each row declare begin 邏輯的執行; end; --------------------------------------------- ---- 建立行級插入觸發器觸發器,輸出插入的id值 create or replace trigger tri_id after insert on person for each row declare begin dbms_output.put_line('插入的資料id是:' || :new.pid); end; ---- 滿足條件即可觸發觸發器 insert into person values(s_person.nextval,'b'); 7. pl/sql丟擲異常(第一個引數是異常的編碼,第二個是異常的提示資訊) raise_application_error(-20001~-20999之間,'提示資訊'); 8. 觸發器實現主鍵自增(行級觸發器) create or replace trigger trigger_name before insert on table_name for each row declare begin select seq_person.nextval into :new.主鍵名 from dual; end; ---------------------------------- ---- 建立主鍵自增的觸發器(主鍵自增一定是行級觸發器,並且在插入之前) 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 ('小zhi'); select * from person; 

儲存函式和觸發器的兩個小例子:

---- 建立不能給員工降薪的觸發器
create or replace trigger tri_raise_sal 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 - 1 where empno = 7788; ---- 使用儲存函式實現提供部門id,查詢部門名稱 create or replace function fun_ename_dname(dno dept.deptno%type) return dept.dname%type is dna dept.dname%type; begin select dname into dna from dept where deptno = dno; return dna; end; ---- 使用上面的儲存函式 select e.ename, fun_ename_dname(e.deptno) from emp e; select e.ename, d.dname from emp e, dept d where e.deptno=d.deptno;

java程式連線Oracle資料庫

oracle10g----> ojdbc14.jar
oracle11g----> ojdbc6.jar

與mysql相比,不同的地方在於驅動包不同,url不同.
1. 首先需要注意的是oracle的ojdbc的驅動jar包從maven中央倉庫下載不下來,所以只能手動向本地倉庫進行安裝:
    mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc14 -Dversion=10.2.0.4.0 -Dpackaging=jar -Dfile=D:/ojdbc14.jar --- 後面的Dfile是你本地的ojdbc14.jar存放的位置 2. 使用java連線oracle的步驟: // 載入資料的驅動 Class.forName("oracle.jdbc.driver.OracleDriver"); // 獲取資料庫的連線,ip是oracle服務所在伺服器的ip,username表示使用者名稱,password表示密碼 Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@ip:1521:orcl","username","password";) // 得到預編譯的Statement物件(增刪改查的時候使用) PreparedStatement ps = connection.preparedStatement("sql語句"); // 設定預編譯sql語句中的佔位符 preparedStatement.setObject(1,"值"); // 執行資料庫查詢操作 ResultSet rs = ps.executeQuery(); // 處理結果集 while(rs.next()){ 邏輯處理; } // 釋放資源 rs.close(); ps.close(); connection.close(); 3. 使用java執行儲存過程和儲存函式 /** * java呼叫儲存過程 * {?= call <procedure-name>[(<arg1>,<arg2>, ...)]} 呼叫儲存函式使用 * {call <procedure-name>[(<arg1>,<arg2>, ...)]} 呼叫儲存過程使用 * @throws Exception */ @Test public void testProcedure() throws Exception{ // 載入資料庫驅動 Class.forName("oracle.jdbc.driver.OracleDriver"); // 得到連線 Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.88.131:1521:orcl", "itheima", "itheima"); // 得到預編譯的Statement物件 CallableStatement cs = connection.prepareCall("{call pro_yearsal(?,?)}"); // 替換佔位符 cs.setObject(1,7788); cs.registerOutParameter(2, OracleTypes.NUMBER); // 執行查詢操作 cs.executeQuery(); // 輸出結果 System.out.println(cs.getObject(2)); // 釋放資源 cs.close(); connection.close(); } /** * java呼叫儲存過程 * {?= call <procedure-name>[(<arg1>,<arg2>, ...)]} 呼叫儲存函式使用 * {call <procedure-name>[(<arg1>,<arg2>, ...)]} 呼叫儲存過程使用 * @throws Exception */ @Test public void testFunction() throws Exception{ // 載入資料庫驅動 Class.forName("oracle.jdbc.driver.OracleDriver"); // 得到連線 Connection connection = DriverManager.getConnection("jdbc:oracle:thin:@192.168.88.131:1521:orcl", "itheima", "itheima"); // 得到預編譯的Statement物件 CallableStatement cs = connection.prepareCall("{?=call fun_salyear(?)}"); // 替換佔位符 cs.setObject(2,7788); cs.registerOutParameter(1, OracleTypes.NUMBER); // 執行查詢操作 cs.executeQuery(); // 輸出結果 System.out.println(cs.getObject(1)); // 釋放資源 cs.close(); connection.close(); }

轉載地址:https://www.cnblogs.com/wadmwz/p/9806854.html