oracle學習筆記


 
   一 oracle數據庫安裝
    下載軟件 
     1 oracle官方網址:www.oracle.com
  2 oracle 11g官網下載地址:http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html
  
  pl/sql : https://www.allroundautomations.com/registered/plsqldev.html
    環境變量設置
  1 在dos環境下進行設置
       set oracle_sid=orcl
       set oracle_home=F:\oracle\product
       set nls_lang=simplified chinese_china.zhs16gbk 或 set nls_lang=american_america.zhs16gbk
       set nls_date_format='yyyy-mm-dd hh24:mi:ss'
     2 在用戶下面設置環境變量
       grant select any dictionary to mandy; 給mandy查看數據字典的權限
       show parameter nls; 顯示數據字典
       alter session set nls_language='american'; 修改語言(中文simplified chinese)
       alter session set nls_territory='america'; 修改國家(中國 china) 
    alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';--當前會話有效
 plsql配置連接
     1 位置 工具 首選項 連接
     2 設置
       Oracle主目錄名  = F:\PLSQL\instantclient_11_2
       OCI庫 = F:\PLSQL\instantclient_11_2\oci.dll  必須添加oci.dll
     3 tnsname.ora文件設置,oracle_home下面的tasname.ora與oci庫下面的tasname.ora文件內容統一。
    F:\oracle\product\NETWORK\ADMIN 下面直接有tasnames.ora(若無,復制一份在下面)
    在系統環境變量下設置oracle_home=F:\oracle\product 
  4 在即時客戶端的目錄里新建文件夾 network  ,network里在新建 admin,在admin目錄下建一個后綴名為.ora的文件:   tnsnames.ora
 plsql連接其它數據庫配置 
  1 在dos命令窗口執行 netca  配置本地網絡服務 
  2 使用ip地址與電腦名連接 sqlplus scott/scott@SDWM-20160811NN:1521/orcl
  3 在配置文件中進行設置 plsql配置文件地址:F:\PLSQL\instantclient_11_2下面的tasnames.ora文件 
    oracle配置文件地址:F:\oracle\product\NETWORK\ADMIN 下面直接有tasnames.ora 
    
 plsql配置文件 打開命令窗口時生效
  1 配置文件地址:F:\PLSQL\PLSQL Developer 對下面的login.sql文件編輯
   
 sqlplus啟動時的配置文件位置,讓格式永久生效。
     1 查找路徑 regedit注冊表中查出oracle_home路徑.
     2 文件路徑為 %ORACLE_HOME%\sqlplus\admin\glogin.sql下面的glogin.sql中進行設置。 
  
 環境腳本的執行
     1 寫好的環境腳本,通過屬性查找到相應位置,選擇用戶或創建專用用戶 
     2 執行:@ 環境腳本的保存路徑\環境腳本名稱
     3 顯示文件 get F:\a.sql 運行sql文件 @(或start)F:\a.sql。 
  
 關閉啟動數據庫命令
     1 關閉數據庫 shutdown immediate 啟動數據庫 srartup
 
 查看數據庫名稱 
  1 show parameter db_name;
  
   二 SQL查詢基礎 
    sql語言 
     1 sql結構化查詢語言(structured query language) 
     2 sql是操作和檢索關系型數據庫的標准語言。在Oracle mysql db2數據庫管理系統上應用 
     3 使用sql語句,程序員和管理員可以完成如下任務 
       改變數據庫對象的結構 
       更改系統的安全配置
       變更用戶對數據庫對象的操作權限 
       在數據庫中檢索需要的信息 
       對數據庫的信息進行更新
    sql語句分類
     1 DML語句(數據操作語言data manipulation language) 
       select/insert/update/delete/merge/select...for update 
     2 DDL語句(數據定義語言data definition language) 
       create/alter/drop/truncate/grant/revoke 
     3 事務控制語句(transaction control language) 
       commit/rollback/savepoint 
    select 語句的功能 
     1 從數據庫中查詢數據 
     2 列查詢:查詢表的部分或所有行
     3 行查詢:設定條件查詢表的部分或所有行
     4 連接:將多個表組合起來進行查詢 
    select 語法 
     select * [distinct]column | expression[alias] from table where 條件;
  --select 查詢關鍵字
  --* 查詢所有的列
  --distinct 去掉重復
  --column|expression選擇指定的字段(列)或表達式
  --alias 給所選擇的列取別名
  --from table 指定表
  --where 后面是篩選條件
  --注意:最后的分號必須加上,表示一個sql語句結束
     概念 
   1 keyword關鍵字,照寫。例 select和from是關鍵字 
   2 clause是sql語句的一個部分 例 select col1...是一個子句,from也是一個子句 
   3 statement 是兩個或多個子句的組合 例 select * from emp是一個sql語句
     查詢列 
   1 select * from emp;--查詢表中所有的列 
   2 select empno,ename,sal from emp;--查詢員工編號 姓名 工資三列
     查詢行
   1 select * from emp where ename='SCOTT';--查出名字叫scott這個人的所有信息 
   2 select empno,ename,sal from emp where ename='FORD';--查出ford的編號 姓名 工資 
  算述表達式 
   1 select ename,sal*(1+0.2) from emp;--給每個員工漲20%工資 
   2 select ename,sal+500 from emp;--給每個員工工資加500 
  列別名 
      1 select ename 姓名,sal*(1+0.2) newsal from emp;--別名 姓名 newsal 
     字符串連接 
      1 select first_name||','||last_name fullname from employees;  
  去除重復的行
   1 select distinct deptno from emp;
   三 SQLPLUS的使用 
    登錄 用戶 
  1 conn / as sysdba --操作系統認證方式登錄 
  2 conn scott/scott --密碼方式登錄 
  3 show user --顯示當前登錄用戶 
  4 discon --取消連接,退出登錄
 sqlplus幫助 
  1 help index 查看所有sqlplus命令 
  2 help set 查看set命令的具體用法
    格式化 
  1 set linesize 120 --設置行寬為120 
  2 set pagesize 100 --設置每頁顯示100行 
  3 set feedback on --顯示反饋信息
  4 set timing on --顯示sql執行了多長時間 
  5 set time on --提示符顯示為時間 
 格式化列 
  1 column name format a30 (簡寫:col name for a30)--將字符類型的列name,列寬設置為30 
  2 column sal format 99,990(簡寫:col sal for 99,990)--設置數字類型列sal,三位分隔的方式 
  3 column sal clear --清楚sal列的格式
 編輯命令行 
  1 list2 將第二行設置為當前行 
  2 change/enmae/ename(c/enmae/ename) --將當前行的enmae字符串替換成ename 
  3 edit 在文本編輯器中,編輯最后一次執行的sql。
 保存執行的sql 
  1 save d:\a.sql --最后一次執行的sql保存到文件中,沒有新建,若有覆蓋 
  2 save d:\a.sql append --文件存在,則追加在文件末尾。只能保存最后執行的一句sql。
  3 spool d:\b.sql --開始保存一下執行的操作和結果 
    spool off --結束,保存到這里為止
    spool d:\b.sql append --以追加的方式保存
 顯示和運行腳本 
  1 get d:\a.sql --把文件中的內容顯示出來 
  2 運行sql文件 @d:\a.sql 或者 start d:\a.sql
 替換變量 
  1 & 定義變量,從鍵盤輸入變量值,不在內存中保存 
  2 && 定義變量,從鍵盤輸入變量值,在內存中保存,下次可以繼續用 
     3 define 定義變量 
     4 undefine 清除變量定義
    查看當前設置的sqlplus相關參數 
     1 show all --查看當前配置的所有參數 
     2 show linesize --查看某個具體參數當前設置的值  
    清屏
  1 clear screen(clear scr) --清楚屏幕上的顯示信息
    查看表結構,分屏顯示 
  1 describe table_name (desc table_name)--顯示某個表的所有列名,列類型 
  2 set pause on --分屏顯示結果 
  3 set pause 'please input enter'--分屏顯示,並加提示信息'please input enter' 
  4 set pause off --關閉分屏顯示 
 查看錯誤信息 
  1 sql>!oerr ora 00942 或者 $oerr ora 00942 --查看ora-00942錯誤的詳細信息 
  2 show errors --顯示pl/sql錯誤信息 
 讓格式永久生效 
  1 $oracle_home/sqlplus/admin/glogin.sql --將格式寫在文件中 
  2 $oracle_home是指oracle的安裝路徑,並不是具體的資料夾
 
   四 常用資料查詢 
    聯機文檔 
  1 幫助用戶正確操作和使用oracle數據庫,oracle公司給出的一份最權威的官方文檔 
  2 若書籍和其它資料上與官方聯機文檔說法不一致,以聯機文檔為准。
 查看聯機文檔 
  1 Oracle公司所有產品的聯機文檔總入口 http://docs.oracle.com/ 
  2 數據庫各版本聯機文檔入口 http://docs.oracle.com/en/database/database.html
     3 聯機文檔下載,熟悉聯機文檔的大體結構和內容 
  4 聯機文檔查資料 查oracle有哪些數據類型 sql reference 
  5 查看語法圖 
  6 查看執行計划 
   set autotrace on --打開執行計划查看
   set autotrace off--關閉執行計划查看
   set autotrace on explain --只顯示查詢結果和執行計划 
   set autotrace on statistics --只顯示結果和統計信息
   set autotrace traceonly --不顯示查詢輸出,顯示執行計划和統計信息 
   set autot traceonly explain --只顯示執行計划 
   set autot traceonly statistics --只顯示統計信息
   --connect / as sysdba 
      --@?\rdbms\admin\utlxplan 
      --@?\sqlplus\admin\plustrce.sql 
      --grant plustrace to public;   
  
     
   五 數據類型 
    字符類型 oracle數據庫的核心是表,表中的列使用到的常見字符類型如下 
  1 char(n) 存儲固定長度的字符串,參數n指定了長度,如果存儲的字符串長度小於n,用空格填充,默認長度是1,最長不超過2000字節 
  2 nchar(n) 輔助字符集,特征同char 
  3 varchar2(n) 存儲可變長度的字符串,length指定了該字符串的最大長度。默認長度1,最長不超過4000字節 
  4 nvarchar2(n) 輔助字符集,特征同varchar2.
  --輔助字符集,只能用unicode字符集,AL16UTF16或UTF8其中的一種
  5 Oracle支持的字符集 
   1 單字節字符集 分為7bit和8bit,ascii就是7bit,iso8859-1就是8bit iso8859-1是ascii的嚴格超級。單字節字符集,1byte=1character。
     1char=1byte , char(5byte)=5bytes , char(5char)=5*1byte=5bytes 
   2 多字節字符集 分為可變長度字符集,固定長度字符集。
     雙字節中文字符集 1char=2bytes , char(5char)=5*2bytes=10 bytes 
  對於多字節字符集 1char=n bytes 如:1char=3bytes
   3 unicode字符集 官網 www.unicode.org.
 數值類型,日期類型
  1 number(p,s) 既可以存儲浮點數,也可以存儲整數,p表示有效位(p默認是38),s是小數位數(默認0) 
  2 date 存儲日期和時間,世紀,4位年,月,日,時,分,秒 
  3 timesamp 存儲日期的年月日,時分秒,以及秒后9位(默認6位),同時包含時區。 
 ROWID rowid是存儲每條記錄的實際物理地址,rowid值可以唯一標識表中的一行。
   --最快到達行,最快訪問 索引中葉節點rowid 可以改變
   --dbms_rowid rowid數據包
   select dbms_rowid.rowid_object(rowid) object_id,
       dbms_rowid.rowid_relative_fno(rowid) rfile,
       dbms_rowid.ROWID_BLOCK_number(rowid) block,
       dbms_rowid.rowid_row_number(rowid) row#,
       emp.*
      from emp;
 
      delete from emp where rowid not in (select min(rowid) from emp group by empno) --去重
   
 ROWNUM 在Oracle表的使用過程中,實際表中還有一些附加的列,稱為偽列。偽列就像表中的列一樣,但是在表中 並不存儲。偽列只能查詢,不能進行增刪改操作。
  1 rownum是一個偽列(不是真正的列,在表中並不真實存在) 
  2 rownum是oracle數據庫讀取數據的順序 
   --在emp表中,工資按降序排列,顯示5到10行數據 
   select b.* from 
   (select rownum rn,a.* from 
   (select rownum,emp.* from emp order by sal desc) a) b 
   where rn>=5 and rn<=10;
     
   六 函數  
    Oracle sql提供了用於執行特定操作的專用函數,這些函數大大增強了sql語言的功能。函數可以接受零個或者多個輸入參數,並返回一個輸出結果。 
 Oracle數據庫中主要使用兩種類型的函數: 
  單行函數:對每一個函數應用在表的記錄時,只能輸入一行結果,返回一個結果,常用單行函數 
   1 字符函數:對字符串操作 
   2 數值函數:對數字進行計算,返回以惡數字 
   3 日期函數:對日期和時間進行處理 
   4 轉換函數:可以將一種數據類型轉換為另外一種數據類型 
   5 條件函數:case...when和decode條件判斷函數 
  分組函數(聚合函數):聚合函數可以對多行數據進行操作,並返回一個結果 
   如:sum(x)返回結果集中x列的總和。 
  字符函數 字符函數可以是表中的列,也可以是一個字符串表達式,常用函數 
   1 ASCII(X) 返回字符x的ASCII碼。互反函數:chr() 
     select ascii('A'),ascii('a'),ascii(''),ascii('') from dual; 
   2 concat(x,y) 連接字符串x和y 同|| 
     select concat('010','8888')||'66' from dual; 
   3 instr(x,str,n1,n2) 在x中查找str,可以指定從n1開始,也可以指定從第n2次開始 
     select instr('oracle traning','ra',1,2) from dual;--返回9 
   4 length(x) 返回x的長度 lengthb(x)返回字節的長度
     select length('hello') from dual; 
   5 lower(x) x轉換為小寫 
     select lower('ABC') from dual;
   6 upper(x) x轉換為大寫 
     select upper('abc') from dual; 
      7 ltrim(x,trim_str) 把x的左邊截去trim_str字符串,缺省截去空格
     select ltrim('abaaxxbaa','ab') from dual;--截取左邊全部a和b(遇符號,其它字符結束)。   
   8 rtrim(x,trim_str) 把x的右邊截去trim_str字符串,缺省截去空格 
     select rtrim('adxxabdadasbaab','ab') from dual; 
   9 trim(trim_str from x)把x的兩邊截去trim_str字符串,缺省截去空格 
     select trim('a' from 'a bbabb abba=aa') from dual;--去除兩邊的a,截取集只能有一個字符。
   10 replace(x,old,new) 在x中查找old,並替換為new 
     select replace('abcABC','ab','x') from dual;--整體替換,區分大小寫 
   11 translate(expr,from_string,to_string) 替換字符與被替換字符一一對應關系 
     select translate('abcd','ab','d') from dual;--b對應空(相當於刪除),替換字符不能為空 
   12 substr(x,n1,n2) 返回x的字串,從n1開始,截去n2個字符,缺省n2,默認到結尾 
     select substr('abc',1,2) from dual; --從位置1開始,返回2個長度。
      13 initcap(x) 返回x字符串第一個字母變為大寫,其它字母小寫 
     select initcap('ab cde'),initcap(chr(97)) from dual; 
   14 lpad(x,n,y) 在字符串x左邊用y字符串填充,到長度為n為止。如果x長度大於n,返回x左邊n個字符,如小於n,x和y  連接后大於n,返回連接后的右邊n個字符。 
     select lpad('hello',10,'*') from dual;
   15 rpad(x,n,y) 在字符串x右邊用y字符串填充,到長度為n為止。 
     select rpad('hello',10,'*') from dual;
  數值函數 數值函數可以是表中的列,也可以是一個字符串表達式,常用的數值函數 
   1 abs(x) 返回x的絕對值 返回數字 
     select abs(100),abs(-100) from dual; 
   2 ceil(x) 大於或等於x的最小整數值 
        select ceil(5.3) from dual;--返回6 
      3 floor(x) 小於或等於x的最大整數值 
        select floor(5.9) from dual;--返回5 
      4 mod(x,y) 返回x除以y的余數 
        select mod(8,3) from dual; --返回2 
      5 round(x[,y]) x在第y位四舍五入 
        select round(55.66,2),round(55.66,-1),round(55.66) from dual; 
      6 trunc(x[,y]) x在第y位截斷 
        select trunc(55.66,2),trunc(55.66,-1),trunc(55.66) from dual; 
      7 sign(x) 判斷x的正負,只返回-10,1三個值 
        select sign(1.1),sign(-1.1),sign(0) from dual;  
   8 least(x,y) 返回x,y中最小的值 
        select least(23,-9,99) from dual;   
   9 greatest(x,y) 返回x,y中最大的值 
     select greatest(23,09,99,-68) from dual;
  日期函數 
   1 sysdate 系統當前時間,精確到秒 
     select sysdate from dual;
   2 current_date 當前會話時間 
     select current_date from dual;
      3 systimesamp 系統當前時間,精確到秒后9位(默認6位),包含時區 
   4 months_between(d1,d2) 返回d1,d2兩個日期的差值,單位為月 
     select months_between(date'2008-8-8',sysdate) from dual;
      5 add_months(d,n) 在日期d上增加n個月,返回新的日期 
     select add_months(sysdate,1) from dual;
      6 next_day(d,n) 返回從d這天開始算起,下一個周n的日期  
     select next_day(sysdate,2) from dual; --下一個周一的日期 
   7 last_day(d) 返回d這個月的最后一天 
     select last_day(sysdate) from dual; 
   8 round(d,fm) 返回d中的fm部分,四舍五入 
     select round(sysdate,'mm') from dual;
   9 trunc(d,fm) 返回d中的fm部分,直接截斷 
     select trunc(sysdate,'dd') from dual;
     轉換函數 主要用於各類數據類型之間的轉換 
   1 to_char(d/n[,fmt]) 把日期或數字轉換為fmt指定格式的字符串 
      select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;--系統時間轉換為字符串
         select to_char(systimestamp,'yyyy-mm-dd hh:mi:ss.ff tzh:tzm') from dual;--把時間戳轉換為字符串
         select to_char(sysdate,'mm') from dual;--系統時間轉換為顯示月份字符串
         select to_char(sal,'$999,999.00') from dual;--將數字轉換為字符串
   2 to_number(x[,frm]) 把一個字符串以fmt格式轉換為一個數字 
     select to_number('$125,136,366.00','$999,999,999.00') from dual;
  select to_number('1.23e+10','9.99eeee') from dual;
   3 to_date(x[,fmt]) 把一個字符串以fmt格式轉換為日期格式 
        select to_date('12-sep-2016  pm 02:49:29','dd-mon-yyyy  pm hh:mi:ss','nls_date_language=american') from dual;   
   4 to_timestamp 轉換為時間戳 
     select to_timestamp_tz('2016-09-12 03:45:36.894123456 pm +08:00','yyyy-mm-dd hh:mi:ss.ff am tzh:tzm','nls_date_language=american') from dual;
   5 cast(expr as data_type) 用於將某種數據類型的表達式顯式轉換為另一種數據類型 
     select cast(sysdate as timestamp) from dual;
   6 convert(char,dest_char_set[,source_char_set]) 字符集轉換
   7 case...when 條件轉換函數
     case when有兩種表現形式 
   1 case 變量 when 值1 then 結果1
               when 值2 then 結果2
    else '其它' end --else可以選擇不要
   示例:
      select ename,job,(
          case job when 'MANAGER' then job 
                when 'CLERK'   then job end) 
   from emp;
      2 case when 表達式1 then 結果1 
          when 表達式2 then 結果2 
   else '其它' end 
   示例: 
   select ename,sal,
          case when deptno=10 then '會計部' 
            when deptno=20 then '研究部'
      when deptno=30 then '銷售部'
    else '其它部門' end 
    from emp;
   8 decode函數 
     語法 
   decode (empression,search1,result1,
                      search2,result2,
       ...
       default)
  --如果expression=search1,返回result1 
  --如果expression=search2,返回result2
  --都不相等使用默認值
    示例:
       select ename,sal,
           decode(deptno,
            10,'會計部',
         20,'研究部',
         30,'銷售部',
         '其他部門')
    from emp;
        
   七 DDL語句
    DDL語句(數據定義語言data definition language) 
  常用的DDL語句 
   1 create 創建對象,如建表或視圖 
   2 alter 修改對象的結構,如修改表結構 
   3 drop 刪除對象, 如刪除表,索引,視圖,序列 
   4 truncate 清空表的數據 
  create 建表 
   1 普通建表
    create table t(id int,name varchar2(10));
   2 用其它表的結構和數據建表 
    create table t as select * from emp; --只能拷貝非空約束
    create table t as select * from emp where 1=2;--只拷貝結構
   3 表建在某個表空間 
    create table t (id int) tablespace users;  
    select tablespace_name,file_name from dba_data_files;--查看表空間及位置 
  列的相關操作 
   1 添加列 
    alter table t add (b number(10)); 
   2 刪除列 
    alter table t drop column t;
   3 修改列的數據類型 
    alter table t modify (name varchar2(20)); 
   4 修改列名 
    alter table t rename column id to idd; 
   5 將某列標記為不可用 
    alter table t set unused column b; 
    select * from dba_unused_col_tabs;--查詢那些標記為unused列
    select object_id from dba_objects where owner='SCOTT' and object_name='T';
    select name from col$ where obj#='object_id';
   6 將標記為不可用的列刪除 
    alter table t drop unused columns;
  表的相關操作 
   1 修改表名 
    alter table t rename to test; 
   2 將表改成只讀狀態 
    alter table t read only; 
   3 將表改成讀寫狀態 
    alter table t read write; 
   4 刪除表 
    drop table t; 
    drop table t purge; 
   5 清空表的數據 
    truncate table t; 
  查看表結構 
   1 desc t --查看列名和列類型describe 
   2 DBMS_METADATA.GET_DDL --獲取對象的元信息 
   3 SELECT DBMS_METADATA.GET_DDL('TABLE','T','SCOTT') FROM DUAL;--set long 500設置字符串長度
             
   八 DML語句
    DML語句(數據操作語言data manipulation language)
  1 select ... for update
  2 select
  3 insert 
  4 update 
  5 delete  
  6 merge into 
 select/select... for update 
  普通select不會阻塞其它讀寫
   select ename,sal from emp where empno=7839;
  select...for update會阻塞其它讀寫(有鎖)
   select ename,sal from emp where empno=7839 for update;
 insert插入語句
  insert可以插入一條記錄
   insert into t values(1,'hello');
   insert into t(id) values (2);
  插入多條記錄
   insert into t select empno,ename from emp;
  可以同時插入多個表
   insert all/insert first
    1 create table t1(a int primary key,b int);
      create table t2(x int primary key,y varchar2(10));
    insert all 
        when mod(rn,2)=1 then 
          into t1(a,b) values (rn,object_id) 
     when mod(rn,2)=0 then 
          into t2(x,y) values (rn,object_name) 
    select rownum rn,object_id,object_name from all_objects where rownum<=20; 
    2 有交叉數據時用insert first 
      insert first 
        when rn>=10 then 
          into t1(a,b) valuse (rn,object_id) 
     when fr<=15 then 
          into t2(x,y) values (rn,object_name)
   select rownum rn,object_id,object_name from all_objects where rownum<=20;
  update 
   update變更數據
    update t set ename='SMITH' where di=1;
   修改多列的值
    update t set ename='james',sal=3000 where id=12;
   用字查詢來變更
    1 update t set id=15,
      name=(select ename from emp where empno=7839) where id=12;
    2 update t set (id,name)=
      (select empno,ename from emp where empno=7839) where id=12;
 刪除數據
  delete刪除數據,可以刪除表中部分數據,或是所有數據
   1 delete from t where id=7839;
   2 delete from t;(或者delete t;) 
  truncate 刪除表中所有的數據
   truncate table t;
  drop 刪除表,視圖等
   1 drop table t;
   2 drop table t purge; 
  三者的區別
   1 delete可以刪除部分數據,也可以刪除全部數據,truncate清空數據。
   2 delete刪除記錄日志,可以回滾,刪除速度慢於truncate。truncate不能回滾。
   3 delete不移動高水位,truncate移動高水位。
   4 回收站查看刪除的表 show recyclebin
     FLASHBACK TABLE T TO BEFORE DROP;--閃回到刪除之前。
  purge recyelebin --清空回收站
  mgrge into語句
   1 merge into可以在一個sql語句中對一個表同時執行insert和update操作
   2 merge命令從一個或多個數據源中選擇行來update或insert到一個表或視圖中
   3 update或insert子句是可選的
   4 update或insert子句可以加where條件
   5 update子句后面可以跟delete子句去刪除一些不需要的行 
  merge intoy語法
   merge into                  --要插入或更新的表
   using                       --要匹配的表
   on                          --要匹配的條件
   when matched then           --匹配的時候
   update                      --更新
   delete                      --刪除  
   when not matched then       --不匹配時 
   insert                      --插入 
    示例:
     merge into oldemp o 
  using newemp n 
  on (o.empno=n.empno)  --此列有多個相同值時無法更新
  when matched then 
   update set o.sal=n.sal delete where (o.ename='KING') --此處后面不需要跟表名
   --delete where (o.ename='SMITH') --update后面跟delete時必須是更新后的數據才能刪除。 
  when not matched then 
   insert (o.empno,o.ename) values(n.empno,n.ename);
  --可以用minus進行檢驗 
  
   九 約束
    1 約束是強加在表上的規則或條件。確保數據滿足業務規則,保證數據的完整性。
    2 當對表進行DML或DDL操作時,如果此操作會造成表中的數據違反約束條件或規則的話,系統就會拒絕執行這個操作。
    3 約束可以是列一級別的 也可以是表級別的
    4 定義約束時沒有給出約束的名字,ORACLE系統將為該約束自動生成一個名字,其格式為SYS_Cn,其中n為自然數。
    5 建議在創建表或增加約束時,給約束定義有意義的名稱
   約束的作用
    1防止無效的垃圾數據進入數據庫,維護數據庫的完整性。完整性指正確性與一致性
 2使數據庫的開發和維護都更加容易
   約束分類
    1 NOT NULL 非空約束
   1.1 NOT NULL非空約束確保字段必須要輸入值,不能為空
   1.2 可以在建表時加NOT NULL約束
       CREATE TABLE T_NULL(ID NUMBER NOT NULL,NAME VARCHAR2(10));
   1.3 也可以先建表,然后再將列加上NOT NULL約束
       ALTER TABLE T_NULL MODIFY ID NOT NULL;
  2 UNIQUE 唯一約束
   2.1 表中每一行中所定義的這列或幾列的值都不能相同
   2.2 必須保證唯一性,即不能重復
   2.3 唯一約束允許有null值
   2.4 建表時添加唯一約束
       CREATE TABLE T_UN (ID NUMBER CONSTRAINT UK_T_UN_ID UNIQUE,NAME VARCHAR2(10));
   2.5 先建表,再加約束
       ALTER TABLE T_UN MODIFY ID CONSTRAINT UK_T_UN_ID UNIQUE;
 3 PRIMARY KEY 主鍵約束
   3.1 主鍵約束唯一的標識表中的每一行,不能重復
   3.2 主鍵約束不允許有NULL值
   3.3 PRIMARY KEY=NOT NULL + UNIQUE
   3.4 建表時添加主鍵
       CREATE TABLE T_PK (ID NUMBER(10) PRIMARY KEY,NAME VARCHAR2(10));
      3.5 先建表,再加主鍵
       ALTER TABLE T_PK MODIFY ID PRIMARY KEY;
   3.6 每個表只能有一個主鍵約束
 4 FOREIGN KEY 外鍵約束
   4.1 外鍵是一張表與另一個表之間聯接的字段
   4.2 外鍵必須是另一個表中的唯一約束列或主鍵列
   4.3 外鍵的用途是確保數據的完整性(確保每個實體是唯一,域完整性,關聯完整性)
   4.4 建表的時候加外鍵
       CREATE TABLE T_DEPT
          (DEPTNO NUMBER(2) CONSTRAINT PK_DEPT1 PRIMARY KEY,
          DNAME VARCHAR2(14) ,
          LOC VARCHAR2(13)) ;
    
    CREATE TABLE T_EMP
          (EMPNO NUMBER(4) CONSTRAINT PK_EMP1 PRIMARY KEY,
          ENAME VARCHAR2(10),
          JOB VARCHAR2(9),
          MGR NUMBER(4),
          HIREDATE DATE,
          SAL NUMBER(7,2),
          COMM NUMBER(7,2),
          DEPTNO NUMBER(2) CONSTRAINT FK_DEPTNO1
    REFERENCES T_DEPT(DEPTNO));
   4.5 先建表再加外鍵
       ALTER TABLE t_emp ADD CONSTRAINT FK_DEPT FOREIGN KEY(deptno) REFERENCES t_dept(deptno);
   4.6 級聯刪除
       alter table T_EMP
          add constraint FK_DEPTNO1 foreign key (DEPTNO1)
          references T_DEPT(DEPTNO) on delete cascade;
   4.7 級聯的數據設置為null
       alter table T_EMP
          add constraint FK_DEPTNO1 foreign key (DEPTNO1)
          references T_DEPT(DEPTNO) on delete set null;
 5 CHECK 檢查約束(條件約束)
   5.1 有特殊需求的地方,可以用check約束
       CREATE TABLE T_CK (ID NUMBER(10),NAME VARCHAR2(10),AGE INT CHECK(AGE>0 AND AGE<200));
   5.2 在一列上可以定義任意多個check約束   
   約束命名
    1 約束命名的一般規則
      1.1 非空約束 NN_表名_列名 
   1.2 唯一約束 UK_表名_列名
   1.3 主鍵約束 PK_表名_列名
   1.4 外鍵約束 FK_表名_列名
   1.5 條件約束 CK_表名_列名
   修改約束名字
    ALTER TABLE T_NULL RENAME CONSTRAINT  TO NN_T_NULL_ID  
   約束類型 CONSTRAINT TYPE 
    1.1 C (check constraint on a table)
 1.2 P (primary key)
 1.3 U (unique key)
 1.4 R (referential integrity)
 1.5 V (with check option, on a view)
 1.6 O (with read only, on a view)
   查看約束
    select table_name,constraint_name,constraint_type from user_constraints
 where table_name='emp';
   刪除約束
    1.1 根據約束名稱,刪除約束,通用
  ALTER TABLE T_EMP DROP CONSTRAINT FK_DEPTNO1;
    1.2 刪除主鍵約束
  ALTER TABLE T_EMP DROP PRIMARY KEY;
    1.3 刪除唯一約束
  ALTER TABLE T DROP UNIQUE(ID);
   約束生效和失效
    1.1 讓約束失效
  ALTER TABLE T_EMP DISABLE CONSTRAINT FK_DEPTNO1;
    1.2 讓約束生效
  ALTER TABLE T_EMP ENABLE CONSTRAINT FK_DEPTNO1;
   表
     DATAFILE 數據文件
  SELECT * FROM V$DATALILE --查看數據文件
   表空間
     DBA_TABLESPACES --DBA表空間
   SELECT * FROM DBA_TABLESPACES; --查看表空間
  DAB_DATA_FILES --數據文件
   SELECT * FROM DBA_DATA_FILES; --查看數據文件
   段 segment 由extent(區)組成,extent由black(塊)組成
     DBA_SEGMENTS DBA下面所有的段 OWNER用戶 SEGMENT_NAME表名
  SELECT * FROM DBA_SEGMENTS WHERE SEGMENT_NAME='EMP';
   區EXTENT 最低8個塊BLACK
     SELECT * FROM DBA_EXTENTS WHERE OWNER='MANDY';
   塊BLOCK 一個block=8kb
     SELECT DISTINCT BLACKS FROM DBA_EXTENTS WHERE BLACLS>8;
   建表語句
     查找DDL語句 METADATA 源數據 TABLESPACE USERS指定表空間
     SELECT DBMS_METADATA.GET_DDL('TABLE','EMP','MANDY') FROM DUAL;
   READ ONLY 只讀/ WRITE 讀寫
     ALTER TABLE EMP READ ONLY --只能讀 
     ALTER TABLE EMP WRITE    --讀寫狀態
   臨時表 temporary 只在當前會話窗口有效
     CREATE GLOBAL TEMPORARY TABLE TEST1 (ID NUMBER(10),NAME VARCHAR2(10)) ON COMMIT DELETE ROWS;--默認ON COMMIT DELETE ROWS
  CREATE GLOBAL TEMPORARY TABLE TEST2 (IN NUMBER(10),NAME VARCHAR2(10)) ON COMMIT PRESERVE ROWS;--提交保存
  
  十 查詢
     like 模糊查詢
      1.1 %表示任意多個字符
      1.2 _表示任意一個字符
      1.3 not like不匹配的
          select * from emp where ename like '_A%';
      1.4 查看%和_本身,使用轉義字符
          show escape 查看轉義字符(set escape on打開)
          自定義轉義字符
          select * from emp where ename like '\_%' escape '';將\設置為轉義字符
          單引號轉義  
     between and 求某個范圍內的
     not between and 求不在某個范圍內的
     in 求和in里面的列表中某一個或多個匹配的
     not in 和in相反,求不匹配的
     order by 排序子句
    select * from emp order by dbms_random.value();隨機排序
    select * from emp order by nlssort(ename,'NLS_SORT=SCHINESE_PINYIN_M');按拼音排序
    select * from v$nls_valid_values;數據字典
    1.1 分組后可以使用分組函數
    1.2 asc 升序排列 desc 降序排列
    1.3 可以跟列名,多列,組合,隨機
  group by 分組子句
    1.1 可以按一個字段分組,也可以按多個字段分組
    1.2 分組后可以使用分組函數(聚合函數)sum,avg,max,min,count
    1.3 group by 后面可以跟字段,不能跟別名和數字
       1.4 having 篩選分組以后的數據,where篩選分組以前的數據。    
  多表連接查詢
       內連接 inner join查詢兩張表相匹配的記錄
         select ename,emp.deptno,dname from emp inner join dept on emp.deptno=dept.deptno;select ename,emp.deptno,dname from emp,dept where emp.deptno=dept.deptno; 
         select ename,emp.deptno,dname from emp ,dept
           where emp.deptno=dept.deptno and (sal>1000 or emp.deptno=10);--此處需要加括號
         自然連接 natural join
           select ename,dname,deptno from emp natural join dept;   
        select e,ename,d,dname,deptno from emp e join dept d using(deptno);
   非等值連接
     select a.ename,a.sal,b.grade
     from emp a,salgrade b
     where a.sal between losal and hisal;
    自連接 self join將自身表的一個鏡像當作另一個表來對待
       select a.empno,a.ename,a.sal,b.empno mno,b.ename mname
    from emp a,emp b
    where a.mgr=b.empno;
       外連接
       左外連接left outer join(簡寫leftjoin)以左邊表為基礎,條件不匹配的,null補充
    右外連接right outer join(rightjoin)以右邊的表為基准,條件不匹配的,null補充
    全外連接full outer join(fulljoin)條件不匹配的,都用null補充
    select a.empno,a.ename,b.empno mno,b.ename mname
    from emp a,emp b
    where a.mgr=b.empno(+);
    
    SELECT * FROM EMP LEFT JOIN DEPT ON EMP.DEPTNO = DEPT.DEPTNO
    條件連接 
          select *
           from emp, salgrade a
          where a.hisal >= emp.sal
            and a.losal <= emp.sal;  
   
       反連接 antijoina not in
          select *
           from emp
          where comm not in (select comm from emp where ename = 'KING') --空值   
    
    
    標量子查詢
       標量子查詢出現在select從句,當使用到外部連接或使用到聚合函數時可以使用
          select ename,(select dname from dept where dept.deptno=emp.deptno) from emp;--相當於外連接
    
    相關子查詢 (兩個表相關) 關聯子查詢
          select *
           from emp a
          where sal > (select avg(sal) from emp b where a.deptno = b.deptno)  
    
    半連接 semijoins exists  where 字句中不能用or  
        select *
         from emp A
        where not exists
        (select *
                 from emp b
                where b.comm = a.comm
                  and (b.ename = 'SCOTT' or b.ename = 'ALLEN')); --and后面or條件需要加括號 
      
  --與not in 的區別    
     SELECT *
         FROM EMP
        WHERE COMM NOT IN (SELECT COMM
                  FROM EMP
                 WHERE ENAME = 'KING'
                    OR ENAME = 'ALLEN')
        /*not in與not exists在處理時有對空值的處理不一樣*/ 
  
    any ,all 用法與區別 
      --查找工資大於最低工資的員工信息
           select * from emp where sal>(select min(sal) from emp);
           select * from emp where sal<any (select sal from emp);
           select * from emp where sal>= all (select sal from emp)--注意空值
           SELECT * FROM EMP A WHERE SAL< ANY (SELECT SAL FROM EMP B WHERE B.DEPTNO=A.DEPTNO)
           
       集合查詢
       並集(union/union all)
       將兩張表的數據合並,union去除重復值,union all不去除重復值
       交集(intersect)
          獲取兩張表都有的記錄    
          差集(minus)
          從一張表中去除另一張表的記錄。表的順序不一樣結果不一樣。
  十一 null值專題
        1 當列沒有值時,可以表示為null,當列值未知或者無意義時也可以使用null
     2 由於null表示數據是不確定的,未知的,所以null不能等於或者不等於任何值或另一個null
    判斷null值
     1 判斷列值是否為nulls,只能使用is null與is not null
  2 如果使用其它條件對nulls進行判斷比較,得到的結果都是unknown
    select * form emp where comm is null;
    null運算
     1 null和任何值運算,結果為null
  2 連接符除外
    select null||'abc',''||'abc' from dual;
    nvl函數
     NVL (expr1, expr2)
          expr1不為NULL,返回expr1;expr1為NULL,則返回expr2。兩者類型要一致
    select ename,nvl(comm,0) from emp;
    nvl2函數
     NVL2 (expr1, expr2, expr3)
          expr1不為NULL,返回expr2;expr1為NULL,返回expr3。
    select ename,nvl2(comm,0,comm) from emp;
    coalesce函數
     coalesce(expression_1, expression_2, ...,expression_n)返回多個值中第一個不為空的
          select coalesce(comm,0) from emp;
    decode函數
     在decode函數判斷中,oracle認為null=null
    select ename,decode(comm,null,0,comm) from emp;
    case  when函數
       select ename,(case when comm is null then 0 else comm end) from emp;
    組合函數中的null
     組合函數中忽略空值
    select count(*),count(comm) from emp;
    子查詢中的null
       1 select ename,comm from emp
      where comm in (select comm from emp where ename='ALLEN' OR ename='SCOTT');
    2 select ename,comm from emp
      where comm not in (select comm from emp where ename='ALLEN' OR ename='SCOTT');
    3 select * from emp A
            where not exists (select * from emp b
                              where b.comm = a.comm
                              and (b.ename = 'SCOTT' or b.ename='ALLEN')); 
    --無返回結果 可以使用exists
    集合操作中的null
     集合運算中 null=null
    約束中的空值
     組合約束中,只要有一列是非null值 則 null=null
    NULL的排序
     null默認排在最后
    select ename,comm from emp order by comm;
  null排在最前
    select ename,comm from emp order by comm nulls first;
        null排在最后
    select ename,comm from emp order by comm nulls last;
       空值相等的函數 sys_op_map_nonnull(null)
       select * from emp
    where sys_op_map_nonnull(null)=sys_op_map_nonnull(null);
   十二 事務
       事務是指一組邏輯操作單元,使數據從一種狀態變換到另一種狀態,為確保數據庫中數據的一致性,數據的操縱應當是離散的成組的邏輯單元,當全部完成時,數據的一致性可以保持,當這個單元中的一部分操作失敗,整個事務應視為錯誤,所有從起始點以后的操作應當回退到開始狀態。
    為了有效的控制事務(transactions),oracle引入了兩個顯示的事務控制命令,一個是commit,一個是rollback。
    事務控制語句
      commit
   rollback
   savepoint
    可以設置DML語句自動提交事務
      set autocommit on
    事務開始和結束
      1 一個事務是以第一個可執行的sql語句開始
   2 當發生下列事件之一時結束
     commit語句提交
     rollback語句回滾
     執行DDL語句自動提交
     執行DCL語句自動提交
     用戶正常退出sqlplus自動提交
     用戶非正常退出sqlplus自動回滾
     系統崩潰,自動回滾
    鎖
      多用戶數據庫管理系統的一個主要任務是對並發(concurrency)進行控制,即對多個用戶同時訪問同一數據進行控制。當缺乏有效的並發控制時,修改數據的操作就不能保證正常,危害數據完整。
   oracle使用鎖(lock)來控制對數據的並發訪問,當更新數據時,數據庫服務器鎖定被修改的數據直到此更新被提交,這期間,任何用戶都不能修改被鎖定的數據,保證系統的數據完整性。
    DML鎖
     也稱作數據鎖(data lock),它鎖定DML語句操作的特定數據行(行鎖)或表中的所有數據行(表鎖)
    DDL鎖
     保護對象的結構(表或視圖的定義),也稱數據字典鎖
  排他DDL鎖
  共享DDL鎖
  可中斷解析鎖(breakable parse locks)
    系統鎖
      保護內部數據結構
    行鎖實驗
    表鎖實驗
    死鎖實驗
    
    行鎖和表鎖
    select sid from v$mystat where rownum=1;會話id。
    查看鎖
    select * from emp where ename='SCOTT' for update;
    
    select sid,
       type,
       id1,
       id2,
       decode(lmode,
              0,'none',
              1,'null',
              2,'row share',
              3,'row exclusive',
              4,'share',
              5,'share row exclusive',
              6,'exclusive') lock_type,
       request,
       ctime,
       block
       from v$lock
       where sid = 8;
        select * from emp where ename='SCOTT' for update nowait;--nowait不在等待
  select * from emp where ename='SCOTT' for update wait 20;--等待20秒
  
       update emp set sal=2000 where empno=7369;
       查看鎖
         select oracle_username username,
        session_id sid,
        decode(locked_mode,
               0,'none',
               1,'null',
               2,'row share',
               3,'row exclusive',
               4,'share',
               5,'share row exclusive',
               6, 'exlusive') lock_type,
        object_name,
        xidusn,
        xidslot,
        xidsqn
        from v$locked_object, dba_objects
        where v$locked_object.object_id = dba_objects.object_id;
  查看誰拿到鎖
   select decode(request, 0, 'holder', 'waiter:') || sid as sid,
        2,id1,
        3,id2,
        4,lmode,
        5,request,
        6,type,
        7,ctime
        from v$lock
        where (id1, id2) in (select id1, id2 from v$lock where request > 0)
        order by id1, ctime desc;
  
  select * from v%lock; --查看鎖情況
   十三 其他對象
     sequence 序列
    序列(sequence)是序列號生產器,可以為表中的行自動生成序列號,產生一組等間隔的數值(類型為數字)。主要用途是生產表的主鍵值,可以在插入語句中引用,也可以通過查詢檢查當前值,或使序列增至下一個值。
    創建序列需要create sequence 系統權限
    sequence序列語法
      CREATE SEQUENCE seq名
         [ INCREMENT BY n ] --每次增加多少,默認1
         [ START WITH n ] --從幾開始,默認1
         [ { MAXVALUE n | NOMAXVALUE }]
         --最大值 ,NOMAXVALUE,沒有上限(10 的27 次方 )
         [ { MINVALUE n | NOMINVALUE }]
         --最小值,NOMINVALUE ,沒有下限(10的-26次方)
         [ { CYCLE | NOCYCLE } ]
         --表示達到上限后,是否回頭再循環重新開始
         [ { CACHE n | NOCACHE } ]
         --為增加效率,將值放在緩存中,默認每次放20個. [ { ORDER | NOORDER } ] --是否順序產生值
  獲取原始創建語句
     select dbms_metadata.get_ddl('sequence','seq_a') from dual;
     SELECT * FROM USER_SEQUENCES WHERE SEQUENCE_NAME='SEQ_A';
    修改sequence
      alter sequence seq
   increment by 20
   maxvalue 9999
   nocache
   nocycle
   --start with 不能修改
       sequence 的值不一定連續
      1 多個用戶同時用一個sequence時,在某一個用戶看來,值是不連續的(或多個表)
   2 回滾的時候,因為sequence是一個獨立的對象,當你的數據回滾時,它並不回滾,所以回滾的那些值就表示已經用掉了,不會再重新生成。
   3 系統崩潰的時候,放在內存中的,即使是沒有使用的值,也會被丟棄掉,不再使用。
    sequence的偽列 nextval,currval
      1 nexval表示獲取下一個值。
   2 currval表示獲取當前值,在使用currval之前,必須使用nextval,否則當前值沒有。
     視圖view
    1 視圖是基於一個表或多個表或視圖的邏輯表,本身不包含數據
    2 視圖基於的表稱為基表。
  創建視圖
    create /*or replace*/ view v_emp_dept10 as select * from emp where deptno=10;
    添加約束只能更改20號部門的數據 with check option
    create view v_emp_dept20 as select * from emp where deptno=20 with check option;
    創建只讀視圖 with read only
    create view v_emp_dept30 as select * from emp where deptno=30 with read only;
    沒有基表創建視圖 前面加force
    create force view v_emp5 as select * from emp5 where deptno=20;
    數據字典里面查看視圖
    select view_name from all_views where view_name='v_emp5';
    查看視圖的列能否被修改
    select * from user_updatable_columns where table_name='v_emp_dept10';
    
   視圖的優點
    1 對數據庫的訪問,視圖可以有選擇性的選取數據庫里的一部分
    2 用戶通過簡單的查詢可以從復雜查詢中得到結果
    3 維護數據的獨立性,視圖可從多個表檢索數據
    4 對於相同的數據可產生不同的視圖
   視圖分為簡單視圖和復雜視圖
    1 簡單視圖只從表里獲取數據,復雜視圖從多表
    2 簡單視圖不包含函數和數據組,復雜視圖可以包含
    3 簡單視圖可以實現DML操作,復雜視圖不可以
   視圖中那些情況,不能進行DML操作
    1 包含組函數 +group by子句
    2 包含distinct關鍵字
    3 rownum列
    4 包含表達式的列
        
  物化視圖 materialized view 
    1 創建物化視圖日志 
      create materialized view log on emp with rowid;
         create materialized view log on emp with primary key ;
    2 創建物化視圖 
      create materialized view mv_emp 
         build immediate   --immediate 立即直接  deferred 推遲
         refresh complete     --刷新 fast增量刷新 complete 完全刷新 never不刷新
         on demand     --demand有需要時刷新 commit立即刷新 
         start with sysdate next to_date(to_char(sysdate+1,'yyyy-mm-dd')||'00:00:00','yyyy-mm-dd hh24:mi:ss')
         as select * from emp;
    3 刪除物化視圖 
      drop materialized view mv_emp 
    4 手動更新需要在命令窗口執行exec 需要提交 
      exec dbms_mview.refresh('MV_EMP','F') --f是增量刷新
    5 select * from user_segments; 查看視圖日志 MLOG$_EMP
         select * from mv_emp; --查看視圖 
   
  同義詞
    1 同義詞是數據庫方案對象的一個別名,用於簡化對象訪問和提高對象訪問安全性
    2 在使用同義詞時,oracle數據庫將它翻譯成對應方案對象的名字
    3 與視圖類似,同義詞並不占用實際存儲空間,只在數據字典中保存了同義詞的定義
    4 在oracle中的大部分數據庫對象,如表 視圖 同義詞 序列 存儲過程 包 都可以根據實際情況為他們定義同義詞。
    創建同義詞
    create synonym emp1 for emp;
    查看對象類型
    select object_name,object_type from all_objects where owner='HR' and object_name='EMP';
    刪除同義詞
    drop synonym emp1;
   十四 用戶和權限
    創建/刪除用戶
      CREATE USER TEST IDENTIFIED BY TEST;第一個test是用戶名,第二個登陸密碼。
  --查詢用戶屬性
   SELECT USERNAME,CREATED,ACCOUNT_STATUS
   FROM DBA_USERS WHERE USERNAME='TEST';
   SELECT USERNAME,ACCOUNT_STATUS,LOCK_DATE
   FROM DAB_USERS WHERE USERNAME='TEST';
    刪除用戶 
      DROP USER TEST;
    刪除用戶及該用戶下所有對象 
      DROP USER TEST CASCADE;
    鎖定/解鎖用戶
  用戶加鎖
      ALTER USER TEST ACCOUNT LOCK;
  用戶解鎖
   ALTER USER TEST ACCOUNT UNLOCK;
  用戶解鎖並重新設置密碼
   ALTER USER HR ACCOUNT UNLOCK IDENTIFIED BY HR;
   
  --如果裝完數據庫沒有該用戶,你可以用unistall重新把他裝上去的。程序運行執行dbca.bat
 權限
  1 權限是執行特殊sql語句的權利
  2 數據庫管理員(dba)是一個具有授予用戶訪問數據庫對象的能力的高級用戶。
  3 用戶需要系統權限來訪問數據庫,需要對象權限來操作數據庫中對象的內容。
 權限分類
  系統權限 如連接數據庫權限,建表權限
   1 CREATE SESSION
   2 CREATE TABLE 
   3 CREATE SEQUENCE
   4 CREATE VIEW
   5 CREATE PROCEDURE
 對象權限 如 某張表的查詢,刪除權限
   1 GRANT SELECT ON EMP TO HR;
   2 GRANT UPDATE,INSERT,DELETE ON EMP TO HR;
   3 GRANT ALL ON EMP TO HR;
   4 GRANT CONNECT TO TEST;
   5 GRANT SELECT ANY TABLE TO TEST;
   6 GRANT RESOURCE TO TEST;
   7 GRANT SELECT ANY DICTIONARY TO TEST;
 權限的授予和回收
  授予權限,用grant語句
   GRANT CREATE SESSION,CREATE TABLE TO TEST;
  回收權限,用revoke語句
   REVOKE CREATE TABLE FROM TEST;
  系統權限級聯授權,不能級聯收回
   WITH ADMIN OPTION
  對象權限級聯授權,可以級聯收回
   WITH GRANT OPTION 
 角色
  1 權限不僅可以授予用戶,也可以授予角色
  2 角色是命名的可以授予用戶的相關權限的組,該方法使得授予,撤回和維護權限容易的多。
  3 一個用戶可以使用幾個角色,並且幾個用戶也可以被指定相同的角色
  4 角色為數據庫應用程序創建
  5 用戶也可以將被授予的權限給其他用戶或者角色,角色是相關權限的命名分組。
  創建角色
    CREATE ROLE REMP;
  將權限授予角色
    GRANT SELECT ON SCOTT.EMP TO REMP;
  將角色授予用戶
    GRANT REMP TO TEST;
   --主要用來管理權限 
   GRANT CREATE SESSION TO PUBLIC --給所有連接權限
   SELECT * FROM USER_SYS_PRIVS; --用戶系統權限查看
   SELECT * FROM ROLE_ROLE_PRIVS; --角色權限查看
   SELECT * FROM USER_ROLE_PRIVE; --用戶有哪些角色查看
   SELECT ROLE,TABLE_NAEM,COLUMN_NAME,PRIVILEGE FROM ROLE_TAB_PRIVS; --角色里表和列的權限
   SELECT PRIVILEGE FROM ROLE_SYS_PRIVS WHERE ROLE='RESOURCE';--角色resource下面的權限
   SELECT TABLE_NAME FROM DICTIONARY WHERE TABLE_NAME LIKE '%PRIVS';--從數據字典里面查看帶有權限的
   查看當前用戶
   1 SHOW USER 
   2 SELECT SYS_CONTEXT('USERENV','SESSION_USER') FROM DUAL;
   3 SELECT SYS.LOGIN_USER FROM DUAL;
   4 SELECT USER FROM DUAL;
   CREATE PUBLIC SYNONYM EMP FOR V_DEPT_EMP; --創建一個公共同義詞
  
   十五 高級sql及應用 
    with語句的優點
     1 增加sql可讀性。如:對於特定with子查詢取個有意義的名字
     2 with子查詢只執行一次,將結果存儲在用戶臨時表空間中,可以引用多次,增強性能 
  --with語句主要用在select語句中
  示例:
    --查找emp表中的第五到第十行數據
    --先取emp表的rownum
    with emp_rn as (select rownum rn,emp.* from emp)
    select * from emp_rn e where e.rn>=5 and e.rn<=10;
    
    --查詢出部門總薪水大於所有部門平均總薪水的部門
     --step1:查詢出部門名和各部門的總薪水
  with dept_costs as 
  (select a.dname dname,sum(b.sal) dept_total from dept a,emp b 
  where a.deptno=b.deptno group by dname),
  --利用上一個with查詢的結果,計算部門的平均總薪水
  avg_costs as (select avg(dept_total) dept_avg from dept_costs)
  --avg_costs as (select sum(dept_total)/count(*) dept_avg from dept_costs)
  --從兩個with查詢中比較並輸出結果
  select dname,dept_total 
  from dept_costs 
  where dept_total>(select dept_avg from avg_costs)
  order by dname;
  --with 語句不能用在update delete 中。
      
    分析函數 處理一些復雜的需求 如: 
     1 查找上一年度各個銷售區排名前10的員工
  2 按區域查找上一年度訂單總額占區域訂單總額20%以上的客戶
  3 查找上一年度銷售最差的部門所在的區域
  4 查找上一年度銷售最好和最差的產品
 上面的查詢與我們日常查詢的區別
  1 需要對同樣的數據進行不同級別的聚合操作
  2 需要在表內將多條數據和同一條數據進行多次的比較
  3 需要在排序完的結果集上進行額外的過濾操作
    用分析函數排名
  1 dense_rank() 有重復的數字不跳着排列,如:兩個並列第一,后面是第二名
    示例:在emp表中查出每個部門工資前三的員工信息
    select * from 
    (select deptno,ename,sal,dense_rank() over(partition by deptno order by sal desc) drk from emp) 
    where rk<=3;
                            
  2 rank() 有重復的數字跳着排列,兩個並列第一,后面是第三名
    示例:在emp表中查出每個部門工資前三的員工信息
    select * from 
    (select deptno,ename,sal,rank() over(partition by deptno order by sal desc) rk from emp) 
    where rk<=3;
    
  3 row_number() 不管重復值,會依次按順序排序
    示例:在emp表中查出每個部門工資前三的員工信息
    select * from 
    (select deptno,ename,sal,row_number() over(partition by deptno order by sal desc) rn from emp) 
    where rk<=3;
   --聯合展示
        select * from 
        (select deptno,ename,sal,
           dense_rank() over(partition by deptno order by sal desc) drk,
     rank() over(partition by deptno order by sal desc) rk,
     row_number() over(partition by deptno order by sal desc) rn
     from emp )
        where drk<=3; 
   --用排名分析函數時 order by 子句不能少
   
   --在emp表中抽樣 每隔一行取數據
   select ename,sal,mod(rn,2) as m 
   from (select row_number() over(order by ename) rn,ename,sal from emp) x 
   where mod(rn,2)=1;
    聚合函數對應的分析函數
  1 sum()
    select empno,ename,sal,sum(sal) over(partition by deptno) from emp;
    
    select empno,ename,sal,sum(sal) over(partition by deptno order by sal) from emp;
    
    select deptno,ename,sal,sum(sal) over(order by ename) 連續求和,
           sum(sal) over() 總和,
     100*round(sal/sum(sal) over(),4) as 占總和比列 
    from emp;
    --查看執行計划 
    --step1 
       explain plan for 
       select ename,sal,sum(sal) over(order by empno) s 
       from emp 
       order by empno;
       --step2 
    select * from table(dbms_xplan.display(null,null,'all'));
       --默認窗口子句是 range between unbounded preceding and curent row     
  
 分析函數之窗口子句 --只能用在order by后面
  1 rows 表示以行來開窗,什么類型都可以,可以多列
    select e.empno,e.sal,
           sum(e.sal) over(order by e.sal) s1,
     sum(e.sal) over(order by e.sal rows between unbounded preceding and current row) s2 
    from emp e;
        
  2 range 表示以偏移量來開窗,與當前行的偏移量。只能用number和date類型,且只能有一列
     select e.empno,e.sal,
           sum(e.sal) over(order by e.sal) s1,
     sum(e.sal) over(order by e.sal range between unbounded preceding and current row) s2 
    from emp e;
   /*between unbounded preceding and unbounded following
             n preceding             n following 
    current row             current row */
    示例:
     select ename,sal,hiredate,sum(sal) over(order by hiredate 
  range between interval '2' day preceding 
  and interval '2' day following ) hd
  from emp;
  
  --求最后一個值和最開始一個值
   select deptno,ename,sal,
          first_value(sal) over(partition by deptno) deptsal,
    last_value(sal) over(partition by deptno) deptsal2 
   from emp;
    
     --求百分比
   select sal,ratio_to_report(sal) over() from emp;
        
  3 默認窗口子句是 range between unbounded preceding and curent row 
    --默認前面所有行到當前行
  4 lead(arg1,[n,arg3]) 向下,取下面第n行的記錄
    lag(arg1,[n,arg3]) 向上,取上面第n行的記錄
    三個參數:
     第一個參數列名,第二個參數偏移量,第三個參數是超出記錄窗口時的默認值(默認顯示為null,可以指定)。
  示例: 
   select ename,sal,lead(sal) over(order by sal) s from emp;
  
   select ename,sal,lead(sal,2,-1) over(order by sal) s from emp;
  
   select ename,sal,lag(sal,2,-1) over(order by sal) s from emp;
 增強型分組函數
  1 rollup 單向組合 --使用在group by子句后面
    select deptno,sal,sum(sal) from emp 
    group by rollup(deptno,sal);
    --后面的列依次遞減 deptno,sal  sal  null  
    
  2 cube 多向組合
    --cube(a,b,c)-->(a,b,c) (a,b) (a,c) (b,c) (a) (b) (c) 
    select deptno,job,sum(sal) from emp 
    group by cube(deptno,job);
      
  3 grouping 函數標識組合列 
    select deptno,job,grouping(deptno),grouping(job),sum(sal) from emp 
    group by rollup(deptno,job);
    --grouping 下面 1 表示匯總的列
        
  4 grouping sets 自定義組合方式
    select deptno,job,sum(sal) from emp 
    group by grouping sets ((deptno,job),());
    
 層次查詢(等級查詢hierarchical query)
  等級查詢/層次查詢語法
   select [level],column,expr...
   from table 
   [where condition] 
   start with condtion 
   connect by [prior column1=column2|column1=prior column2];
 層次查詢之SYS_CONNECT_BY_PATH
  1 sys_connect_by_path(column,char),其中column是字符型或能自動轉換成字符型的列名 
  2 它的主要目的是將父節點到當前節點的層次路徑按照指定的模式展現出現 
  3 這個函數只能用在層次查詢中
   示例:
       select level,sys_connect_by_path(ename,'|') full_name 
    from emp
          --where level=4
          start with mgr is null 
          connect by prior empno=mgr;  
    
          select ename,lpad(' ',2*level-1)||sys_connect_by_path(ename,'|') "path"  from emp 
          start with mgr is null 
          connect by prior empno=mgr; 
    
    --connect_by_isleaf 
    select ename,connect_by_isleaf isleaf, 
    lpad(' ',2*level-1)||sys_connect_by_path(ename,'|') "path" 
    from emp 
    start with mgr is null 
    connect by prior empno=mgr;
              
    
 行列轉換
  1 實際應用中,需要行轉成列或者需要列轉成行
  2 oracle 11g新特性 pivot:行轉列 unpivot:列傳行
  pivot語法-行轉列   
   select...
   from...
   pivot[xml]
   (pivot_clause
   pivot_for_clause
   pivot_in_clause) 
   where... 
   --pivot_clause:定義被聚合的列(pivot是一種聚合操作)聚合操作的函數和處理對象
   --pivot_for_clause:定義被分組和轉換的列,依據那個列進行行轉列
   --pivot_in_clause:定義pivot_for_clause子句中的列的過濾器(例如使用值的范圍來限制結果)
   --pivot_in_clause中每個值的聚合都將被轉換成單獨的列
   --因為要將數據行取值轉成列,我們需要告訴Oracle那些取值成列,並且這些取值成列的過程中,列順序是怎樣的。
   示例: 
     select * from score 
     pivot (sum(grade) 
          for subject 
    in('language','english','math'));
   --可以使用decode 
   示例: 
    --行轉列
         select name,
                sum(decode(subject, 'language', grade)) language,
                sum(nvl(decode(subject, 'math', grade), 0)) math,
                sum(nvl(decode(subject, 'english', grade), 0)) english
           from score
          group by name;
            
     unpivot語法-列轉行
   select...
   from...
   unpivot[include|exclude nulls] 
   (unpivot_clause
   pivot_for_clause
   unpivot_in_clause) 
   where...
      --include|exclude nulls:這個選項用來控制unpivot是否包含null的記錄,默認不包含nulls
   --unpivot_clause:對應的具體值
   --pivot_for_clause:對應轉換后列的名稱
   --unpivot_in_clause:具體列到行的列名
   
   --使用union all 進行列轉行 
     
  select name, 'language' subject, language grade
          from score2
        union all
        select name, 'math' subject, math grade
          from score2
        union                                 
        select name, 'english' subject, english grade from score2
  order by name;
   
   --使用insert all 進行列轉行 
   
   --創建一張表 
        create table score3(
        name varchar2(10),
        subject varchar(10),
        grade number(3));
        --插入數據
        insert all
        into score3 values(name,'language',language)
        into score3 values(name,'english',english)
        into score3 values(name,'math',math)
        select name,language,english,math 
        from score2;
   
   --使用unpivot
   select * from score2 
   unpivot 
   (grade for subject in(language,english,math));
  --列轉行 包 wmsys.wm_concat
       select deptno,wmsys.wm_concat(ename) from emp group by deptno;
       select wm_concat(ename) from emp;
  
   
   
    分頁 分頁就是取第n行到第m行的數據
 --第一種方法
  select * from 
  (select a.*,rownum rn from emp a)
  where rn>=5 and rn<=10;
 --第二種方法 
  select * from emp a 
  where rownum<=6 and a.empno not in (select b.empno from emp b where rownum<=4);--not in 先執行
 --第三種方法 
  select * from (
  select a.*,row_number() over(order by empno desc) rk from emp a) 
  where rk<=10 and rk>=5; 
 --第四種方法 
  select * from emp where rownum<=10 
  minus 
  select * from emp where rownum<=5;
  
   十六
          --2016-10-11
      --plsql圖標直接打開文件可以看到其相應的配置文件
      --工具--〉首選項 
      --sublime text軟件使用
      --
      --rowid 偽列 特殊情況下可以改變
      select rowid,emp.* from emp;
      dbms_rowid --包里面找到相應的列 
      --刪除插入過程中rowid不會重復利用,oracle自動管理 導致塊的利用率低
      --8kb I/O
      select dbms_rowid.rowid_object(rowid) object_id,
             dbms_rowid.rowid_relative_fno(rowid) rfile,
             dbms_rowid.ROWID_BLOCK_number(rowid) block,
             dbms_rowid.rowid_row_number(rowid) row#,
             emp.*
        from emp;
             
      --去重 
      select * from emp where rowid in (
      select min(rowid) from emp group by empno);
      
      delete from emp where rowid not in (select min(rowid) from emp group by empno)
      --刪除后增加改變rowid
      
      --merge 合並
      --update emp set sal=sal+1
      delete from emp where empno in 
      (select empno from ((select * from emp minus (select * from scott.emp)))) 
      
      insert into emp select * from scott.emp minus select * from emp;
      
      select * from emp;
      select * from newemp;
      
      --創建新表
      create table newemp as select * from emp where deptno=30;
      insert into newemp(empno,ename) values (1111,'scott');
      update newemp set sal=2000 where empno=7499;
      --用merge into更新emp表中數據
      merge into emp o
      using newemp n
      on (o.empno=n.empno)
      when matched then update set o.sal=n.sal delete where o.ename='JONES'
      when not matched then insert (o.empno,o.ename,o.sal) values (n.empno,n.ename,n.sal)
      
      --database link 主要用於數據庫之間的拷貝和傳送 link連接 
      select * from user_role_privs;
      select * from user_sys_privs;
      --where sqlplus /set oracle_home 查看oracle_home地址
      --sqlplus scott/scott@orcl_mandy 連接其它數據庫
      --只有當前用戶可以用這個數據連接
      grant create database link to mandy;--授權創建數據連接
      create database link dblink_mandy 
      connect to scott identified by "scott" using 'orcl_mandy';
      --創建公用的數據連接
      grant create public database link to mandy;--授權創建公用數據連接
      create public database link dblink_mandy
      connect to scott identified by "scott" using 'orcl_mandy';
      --刪除
      drop database link dblink_mandy --刪除數據連接
      drop public database link dblink_mandy--刪除公用數據連接
      select * from wzh_ods_emp@dblink_mandy;
      --創建拷貝表
      create table wzh_emp as select * from wzh_ods_emp@dblink_mandy
      select * from wzh_emp;
      
      --copy sqlplus命令
      copy from scott@orcl_mandy append emp_test using select * from emp;
      copy from scott@orcl_mandy create emp_test using select * from emp;
      copy from scott@orcl_mandy insert emp using select * from emp;--需要原表
      copy from scott/scott@orcl_mandy replace emp_tset using select * from emp;
      --在sqlplus命令窗口 可以不登陸用戶,登陸到sqlplus
      copy from scott@orcl_mandy to mandy@orcl_lf append emp_test using select * from emp;
      
      --hwm 高水位
      ANALYZE TABLE EMP COMPUTE STATISTICS;--統計信息 先執行然后執行下面sql語句
      select * from user_segments where segment_name='EMP';
      SELECT * FROM USER_TABLES WHERE TABLE_NAME='EMP';
      select * from emp;
      
      INSERT INTO EMP SELECT * FROM SCOTT.EMP;
      用delete刪除數據測試
      --降低高水位 兩種方法
      --重建表
      create table emp_t as select * from emp;
      drop table emp purge;
      alter table rename emp_t to emp;
      --truncate回收空間 數據全部刪除直接用truncate
      truncate table emp;
      --表里面有數據 
      --1 通過移動表空間需要雙倍的空間
      1 alter table emp move tablespace users; --修改表空間
      
      2 alter table emp enable row movement; --設置成行移動 行來移動 
        alter table emp shrink space; shrink 收縮
        alter table emp disable row movement;
      --ddl語句會改變rowid
      create table emp1 as select 1 id from dual;
      alter table emp move tablespace user;
   
 臨時表
  --臨時表 temporary 只在當前會話窗口有效
       SELECT DBMS_METADATA.GET_DDL('TABLE','T_EMP','MANDY') FROM DUAL;--查看建表語句
       --事務獨立 commit
       create global temporary table t_emp(id int,name varchar2(10));--默認ON COMMIT DELETE ROWS
       create global temporary table t_emp1(id int,name varchar2(10)) on commit delete rows;--提交刪除
       --會話獨立 session 一個連接
       create global temporary table t_emp2(id int,name varchar2(10)) on commit preserve rows;--提交保留
       insert into t_emp1 values (1,'a');
       insert into t_emp2 values (2,'b');
       
       select * from t_emp1;
       select * from t_emp2;
       
       commit;
       
       select * from t_emp1;--提交時刪除數據
       select * from t_emp2;--提交時保留數據
       
       create global temporary table t_emp3 as select * from scott.emp;--create為ddl語句
       create global temporary table t_emp4 on commit preserve rows as select * from scott.emp;--加提交保留
       select * from t_emp3;
       select * from t_emp4;
  
  表 表空間 表數據文件查看
    --
      select * from v$datafile;
      name中以dbf結尾的是數據文件
      --表空間
      select * from dba_tablespaces; --表空間 由數據文件組成
      select * from dba_data_files;  --數據文件
      --SYSTEM  SYSAUX系統 數據字典
      --UNDOTBS1 日志
      --TEMP 臨時 
      --創建alter tablespace users add datafile 'F:\ORACLE\ORADATA\ORCL\USERS02.DBF' size 10m;
      --刪除alter tablespace users drop datafile 'F:\ORACLE\ORADATA\ORCL\USERS02.DBF'
      --塊-區-段 段相當於表 以塊為單位存儲數據
      --數據文件
      select * from dba_data_files;
      select bytes/1024/8,blocks from dba_data_files;
      --段SQMENT 由extent組成,extent由block組成
      select * from dba_segments where owner='MANDY' or SEGMENT_NAME='EMP';
      SELECT SEGMENT_NAME,TABLESPACE_NAME,SEGMENT_TYPE,BYTES/1024/1024 MB FROM 
      dba_segments where owner='MANDY' or SEGMENT_NAME='EMP';
      --查看類型,表空間,
      --區EXTENT 最低8個塊
      select * from dba_extents where owner='MANDY' and SEGMENT_NAME='EMP';
      --塊BLOCK 一個block=8kb,數據倉庫block大點
      select DISTINCT BLOCKS from dba_extents WHERE BLOCKS > 8;
      
      SELECT DBMS_METADATA.GET_DDL('TABLE','EMP','MANDY') FROM DUAL;
    rowid 
   --rowid 偽列 特殊情況下可以改變
        select rowid,emp.* from emp;
        dbms_rowid --包里面找到相應的列 
        --刪除插入過程中rowid不會重復利用,oracle自動管理 導致塊的利用率低
        --8kb I/O
        select dbms_rowid.rowid_object(rowid) object_id,
               dbms_rowid.rowid_relative_fno(rowid) rfile,
               dbms_rowid.ROWID_BLOCK_number(rowid) block,
               dbms_rowid.rowid_row_number(rowid) row#,
               emp.*
          from emp;
               
        --去重 
        select * from emp where rowid in (
        select min(rowid) from emp group by empno);
        
        delete from emp where rowid not in (select min(rowid) from emp group by empno)
    database link 數據連接 
   --database link 主要用於數據庫之間的拷貝和傳送 link連接 
      select * from user_role_privs;
      select * from user_sys_privs;
      --where sqlplus /set oracle_home 查看oracle_home地址
      --sqlplus scott/scott@orcl_mandy 連接其它數據庫
      --只有當前用戶可以用這個數據連接
      grant create database link to mandy;--授權創建數據連接
      create database link dblink_mandy 
      connect to scott identified by "scott" using 'orcl_mandy';
      --創建公用的數據連接
      grant create public database link to mandy;--授權創建公用數據連接
      create public database link dblink_mandy
      connect to scott identified by "scott" using 'orcl_mandy';
      --在dba用戶下面授權 grant database link to mandy;
      drop database link dblink_mandy --刪除數據連接
      drop public database link dblink_mandy--刪除公用數據連接
      select * from wzh_ods_emp@dblink_mandy;
      --創建拷貝表
      create table wzh_emp as select * from wzh_ods_emp@dblink_mandy
      select * from wzh_emp;
    hwm 高水位 
   ANALYZE TABLE EMP COMPUTE STATISTICS;--統計信息 先執行后執行下面sql語句
      select * from user_segments where segment_name='EMP';
      SELECT * FROM USER_TABLES WHERE TABLE_NAME='EMP';
      select * from emp;
      
      INSERT INTO EMP SELECT * FROM SCOTT.EMP;
      用delete刪除數據測試
      --降低高水位 兩種方法
      --重建表
      create table emp_t as select * from emp;
      drop table emp purge;
      alter table rename emp_t to emp;
      --truncate回收空間 數據全部刪除直接用truncate
      truncate table emp;
      --表里面有數據 
      --1 通過移動表空間需要雙倍的空間
      alter table emp move tablespace users; --修改表空間
      
      alter table emp enable row movement; --設置成行移動 行來移動 
      alter table emp shrink space;
      alter table emp disable row movement;
      --ddl語句會改變rowid
      create table emp1 as select 1 id from dual;
      alter table emp move tablespace user;
 行連接與行遷移 
   --行連接跟行遷移
      --行連接 一個行存儲在多個塊中的情況
      --行遷移 一個數據行不適合放入當前塊而被重新定位到另一個塊,在原始塊中保留一個指針
      --行遷移:  當一個行上的更新操作(原來的數據存在且沒有減少)導致當前的數據不能在容納在當前塊,我們需要進行行遷移。一個行遷移意味着整
      --              行數據將會移動,僅僅保留的是一個轉移地址。因此整行數據都被移動,原始的數據塊上僅僅保留的是指向新塊的一個地址信息。
      --              產生:update
      --行鏈接:  當一行數據太大而不能在一個單數據塊容納時,行鏈接由此產生。舉例來說,當你使用了4kb的Oracle 數據塊大小,而你需要插入一行數據是8k,
      --              Oracle則需要使用3個數據塊分成片來存儲。因此,引起行鏈接的情形通常是,表上行記錄的大小超出了數據庫Oracle塊的大小。
      --              產生:insert
      --              表上使用了LONG 或 LONG RAW數據類型的時候容易產生行鏈接。其次表上多於255列時Oracle會將這些過寬的表分片而產生行鏈接
      
      --3.遷移行對索引讀產生額外的I/O,對全表掃描沒什么影響
      --   行鏈接則影響索引讀和全表掃描
      --每個塊預留10%的空間 pct free insert不能用,主要用在update
      
      --2016-10-12
      --查找表的行連接
      F:\ORACLE\product\11.2.0\dbhome_1\RDBMS\ADMIN\utlchain.sql
      --在sqlplus命令中@執行 創建表 CHAINED_ROWS

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM