Oracle筆記(七) 數據更新、事務處理、數據偽列


一、數據的更新操作

DML操作語法之中,除了查詢之外還有數據的庫的更新操作,數據的更新操作主要指的是:增加、修改、刪除數據,但是考慮到emp表以后還要繼續使用,所以下面先將emp表復制一份,輸入如下指令:

CREATE TABLE myemp AS SELECT * FROM emp;

這種語法是Oracle中支持的操作,其他數據庫不一樣。

1、數據增加

如果現在要想實現數據的增加操作,則可以使用如下的語法完成:

INSERT INTO 表名稱 [(字段1,字段2,…)] VALUES(值1,值2,…);

如果要想進行增加數據的話,則以下的幾種數據類型要分別處理:

  • 增加數字:直接編寫數字,例如:123;
  • 增加字符串:字符串應該使用“’“聲明;
  • 增加DATE數據:
    • 第一種:可以按照已有的字符串的格式編寫字符串,例如“’17-12月-80’”;
    • 第二種:利用TO_DATE()函數將字符串變為DATE型數據;
    • 第三種:如果設置的時間為當前系統時間,則使用SYSDATE;

可是對於數據的增加也有兩種操作格式:完整型、簡便型;

范例:增加數據 —— 完整語法編寫

INSERT INTO myemp(empno,ename,hiredate,sal,mgr,job,comm)
VALUES(8888,'張三',TO_DATE('1960-08-17','yyyy-mm-dd'),8000,7369,'清潔工',1000);
INSERT INTO myemp(empno,ename,hiredate,sal,mgr,job,deptno)
VALUES(8889,'李四',SYSDATE,3000,7369,'清潔工',30);

范例:增加數據 —— 簡便語法,不寫增加的列名稱

INSERT INTO myemp VALUES(8889,'李四','清潔工',7369,SYSDATE,3000,null,30);

很明顯雖然簡便語法代碼少了,可是這種操作並不可取,所以在實際的開發之中,沒有任何一個人會寫簡便語法,這樣根本就不利於程序的維護,都編寫完整的操作。

2、數據修改

如果要想修改表中已有的數據,則可以按照如下的語法進行:

UPDATE 表名稱 SET 更新字段1=更新值1,更新字段2=更新值2,… [WHERE 更新條件(s)];

范例:更新雇員編號是7369的基本工資為5000,獎金為2000,職位修改為MANAGER,雇佣日期修改為今天

UPDATE myemp SET sal=5000,comm=2000,job='MANAGER',hiredate=SYSDATE WHERE empno=7369;

范例:所有人的工資改為7500

UPDATE myemp SET sal=7500;

如果更新時候不加上更新操作,則意味着更新全部的數據,但是這種做法絕對不可取,如果現在表中的數據量較大的話,這種更新所耗費的時間是相當長的,而且性能也會明顯降低。

3、數據刪除

當數據不再需要之后,就可以使用以下的語法刪除數據:

DELETE FROM 表名稱 [WHERE 刪除條件(s)];

與更新一樣,如果沒有寫刪除條件的話,則表示刪除全部數據;

范例:刪除所有在1987年雇佣的雇員

DELETE FROM myemp WHERE TO_CHAR(hiredate,'yyyy')=1987;

一定要記住,如果刪除的時候沒有匹配條件的數據存在,則更新的記錄為“0”,包括更新操作也是一樣的。

范例:刪除表中的全部記錄

DELETE FROM myemp;

一般對於刪除的操作而言,盡可能少去使用,包括以后在進行系統開發的時候,對於所有的刪除操作之前實際上都建議大家先給出一個確認的提示框,以防止用戶誤刪除。

二、事務處理

對於數據表的操作,很明顯查詢要比更新操作更加的安全,因為更新操作有可能會出現錯誤,以導致沒有按照既定的要求正確的完成更新操作。

但是在很多時候更新有可能會有多條指令共同完成,例如:以銀行轉帳的方式為例:

  1. 判斷A的賬戶上是否有5000W;
  2. 判斷B賬戶是否存在並且狀態是否正常;
  3. 從A的賬戶上移走5000W;
  4. 向B的賬戶之中增加5000W;
  5. 向銀行支付手續費用5000;

以上的五個操作是一個整體,可以理解為一個完整的業務,如果這之中第三點出錯了,那么其他的操作呢?所有的操作都應該不再執行,並且回歸到最原始的狀態,而這個操作流程就是事務的操作。

所有的事務處理操作都是針對於每一個session進行的,在Oracle數據庫之中,把每一個連接到數據庫上的用戶都稱為一個session,每一個session之間彼此獨立,不會有任何的通訊,而每一個session獨享自己的事務控制,而事務控制之中主要使用兩個命令:

  • 事務的回滾:ROLLBACK,更新操作回到原點;
  • 事務的提交:COMMIT,真正的發出更新的操作,一旦提交之后無法回滾;

但是這樣一來也會出現一些問題,例如:某一個session在更新數據表的時候還沒有提交事務,其他session是無法更新的,必須等待之前的session提交后才可以;

這種問題從大的方面講可以稱為死鎖,但是在Oracle之中死鎖有很多的種類,這些與開發者沒有太大的關系,是由DBA負責的。

所有的數據更新一定都會受到事務的控制。

三、數據偽列

數據偽列指的是用戶不需要處理的列,而是由Oracle自行維護的數據列,在Oracle之中有兩個數據偽列:ROWNUM、ROWID;

1、 ROWNUM

ROWNUM從單詞含義上講應該表示的是行號,實際上ROWNUM為每一個顯示的記錄都會自動的隨着查詢生成行號,例如,下面通過兩個代碼觀察:

SELECT ROWNUM,empno,ename,job,hiredate,sal FROM emp;

此時的ROWNUM行號並不是永久固定的;

SELECT ROWNUM,empno,ename,job,hiredate,sal FROM emp WHERE deptno=30;

是每次動態的重新生成的,那么既然有了ROWNUM之后,下面就可以實現數據的部分顯示;

范例:查詢前5條記錄

SELECT ROWNUM,empno,ename,job,hiredate,sal FROM emp
WHERE ROWNUM<=5;

范例:查詢6-10條記錄

按照正常的思維肯定是直接進行BETWEEN…AND的判斷;

SELECT ROWNUM,empno,ename,job,hiredate,sal FROM emp
WHERE ROWNUM BETWEEN 6 AND 10;

這個時候並沒有返回任何的數據,因為ROWNUM不是真實列,而要想真正的實現這種查詢,思路是:先查詢前10條記錄,之后再顯示后5條記錄,要依靠子查詢完成。

SELECT * FROM(
      SELECT ROWNUM m,empno,ename,job,hiredate,sal FROM emp
      WHERE ROWNUM<=10) temp
WHERE temp.m>5;

如果現在按照這個思路,下面就可以給出日后程序中所需要分頁的功能實現。

范例:顯示前5條記錄

當前所在頁(currentPage)為1;

每頁顯示的記錄長度(lineSize)為5;

第一頁:

SELECT * FROM(
      SELECT ROWNUM m,empno,ename,job,hiredate,sal FROM emp
      WHERE ROWNUM<=5) temp
WHERE temp.m>0;

范例:顯示中間的5條記錄

當前所在頁(currentPage)為2;

每頁顯示的記錄長度(lineSize)為5;

第二頁:

SELECT * FROM(
      SELECT ROWNUM m,empno,ename,job,hiredate,sal FROM emp
      WHERE ROWNUM<=10) temp
WHERE temp.m>5;

范例:顯示第三頁的內容,currentPage=3,lineSize=10;

SELECT * FROM(
      SELECT ROWNUM m,empno,ename,job,hiredate,sal FROM emp
      WHERE ROWNUM<=15) temp
WHERE temp.m>10;

以上的程序就是分頁顯示操作的核心代碼。

2、 ROWID

ROWID表示的是每一行數據保存的物理地址的編號,例如,觀察如下的查詢:

SELECT ROWID,deptno,dname,loc FROM dept;

此時返回許多的記錄:

ROWID                  DEPTNO DNAME          LOC
------------------ ---------- -------------- -------------
AAAL+XAAEAAAAANAAA         10 ACCOUNTING     NEW YORK
AAAL+XAAEAAAAANAAB         20 RESEARCH       DALLAS
AAAL+XAAEAAAAANAAC         30 SALES          CHICAGO
AAAL+XAAEAAAAANAAD         40 OPERATIONS     BOSTON

每一條記錄的ROWID都不會重復,所以即便表中所有列的數據內容都重復了,ROWID也是不會重復的,而且以一個ROWID為例,說明ROWID組成,例如:AAAL+XAAEAAAAANAAA

  • 數據對象號:AAAL+X;
  • 相對文件號:AAE;
  • 數據塊號:AAAAAN;
  • 數據行號:AAA;

面試題:請刪除表中的重復記錄

現在項目之中由於管理不善,所以導致出現了許多重復的信息,為了說明問題,下面為表中增加若干條記錄。

INSERT INTO dept(deptno,dname,loc) VALUES (21,'RESEARCH','DALLAS');
INSERT INTO dept(deptno,dname,loc) VALUES (31,'SALES','CHICAGO');
INSERT INTO dept(deptno,dname,loc) VALUES (32,'SALES','CHICAGO');
INSERT INTO dept(deptno,dname,loc) VALUES (41,'OPERATIONS','BOSTON');
INSERT INTO dept(deptno,dname,loc) VALUES (42,'OPERATIONS','BOSTON');
INSERT INTO dept(deptno,dname,loc) VALUES (43,'OPERATIONS','BOSTON');
COMMIT;

此時的數據顯示是:

SQL> select * from dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON
        21 RESEARCH       DALLAS
        31 SALES          CHICAGO
        32 SALES          CHICAGO
        41 OPERATIONS     BOSTON
        42 OPERATIONS     BOSTON
        43 OPERATIONS     BOSTON

已選擇10行。

現在要求刪除掉所有重復的記錄,保留最早增加的記錄內容。

最終顯示效果:

SQL> select * from dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

先按照查詢的方式做,首先找到所有重復的數據,重復的數據就比較容易了,按照部門名稱及位置分組,之后統計個數,如果個數大於1,則表示重復。

SELECT dname,loc,MIN(ROWID)
FROM dept
GROUP BY dname,loc
HAVING COUNT(deptno)>1;

此時返回的三個ROWID,與最早的ROWID比較一下。

ROWID                  DEPTNO DNAME          LOC
------------------ ---------- -------------- -------------
AAAL+XAAEAAAAANAAA         10 ACCOUNTING     NEW YORK
AAAL+XAAEAAAAANAAB         20 RESEARCH       DALLAS
AAAL+XAAEAAAAANAAC         30 SALES          CHICAGO
AAAL+XAAEAAAAANAAD         40 OPERATIONS     BOSTON
SQL> SELECT dname,loc,MIN(ROWID)
  2  FROM dept
  3  GROUP BY dname,loc
  4  HAVING COUNT(deptno)>1;

DNAME          LOC           MIN(ROWID)
-------------- ------------- ------------------
SALES          CHICAGO       AAAL+XAAEAAAAANAAC
RESEARCH       DALLAS        AAAL+XAAEAAAAANAAB
OPERATIONS     BOSTON        AAAL+XAAEAAAAANAAD

數據插入的早,ROWID就小,所以下一步首先必須確定的是不能刪除的ROWID,去掉之前的限制(COUNT()>1),表示按照部門名稱及位置分組,取出每一個最小的ROWID;

SELECT MIN(ROWID)
FROM dept
GROUP BY dname,loc;

以上的數據是刪除的,所以下面編寫DELETE語句:

DELETE FROM dept
WHERE ROWID NOT IN(
      SELECT MIN(ROWID)
      FROM dept
      GROUP BY dname,loc);
COMMIT;

此時就是根據ROWID完成的,而這道題目也就是ROWID現在為止的唯一可以看的見的作用。

在所有的偽列之中,只有ROWNUM是以后開發之中最為重要的部分,一定要掌握,而對於ROWID知道就行了,不必做太深入的了解。


免責聲明!

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



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