SQL經典實例(四)插入、更新和刪除

插入默認值

定義表的某些列的默認值:數據庫

create table D (id integer default 0);

全部的數據庫都支持使用default關鍵字來顯式地爲某一列指定默認值:服務器

insert into D values(default);

Oracle 8i數據庫及更早的版本不支持default關鍵字,所以沒辦法爲某一列顯式地插入默認值。
若是全部的列都預設了默認值,MySQL容許制定一個空白的values列表爲全部列建立預設的默認值:測試

MySQLspa

insert into D values();

若是數據表中某些列沒有設定默認值,而某些列設定了默認值,那麼在插入數據的時候之喲啊不把預設了默認值的列寫入insert列表,就能夠方便地爲其插入默認值。考慮以下表:翻譯

create table DD (id integer default 0, foo varchar(10));

insert列表中只指定foo列:code

insert into DD (foo) values ('Bar');

clipboard.png
也可使用null值覆蓋默認值:ip

insert into DD (id, foo) values (null, 'Brighten');

clipboard.png

複製數據到另外一個表

insert into dept_east (deptno, dname, loc)
select deptno, dname, loc
    from dept
where loc in ('NEW YORK', 'BOSTON');

注意在insert列表後沒有values關鍵字。it

複製表定義

DEPT表建立一個副本DEPT_2,可是隻要表結構,不復制數據:io

create table dept_2
as
select * from dept
    where 1=0;

多表插入

Oracle可使insert all或者insert first語法
Oracletable

insert all
    when loc in ('NEW YORK', 'BOSTON') then
        into dept_east (deptno, dname, loc) values (deptno, dname, loc)
    when loc in ('CHICAGO') then
        into dept_mid (deptno, dname, loc) values (deptno, dname, loc)
    else 
        into dept_west (deptno, dname, loc) values (deptno, dname, loc)
select deptno, dname, loc
    from dept;

insert allinsert first的區別就是:一旦WHEN-THEN-ELSE的結果爲真,insert first會當即結束評估,insert all則會逐一評估全部的條件,而不論前面的測試結果是否爲真,因此使用insert all可能把同一行數據插入到多個表中。
也就是說,當使用insert first時,若是知足某一個whenelse條件,判斷過程就會當即返回,不會再繼續評估其餘判斷條件是否成立,保證每次過程都只有一條記錄插入到一張表中。

禁止插入特定列

若是想要阻止用戶或者錯誤的軟件應用程序在某些列中插入數據,能夠建立一個視圖,只暴露那些你但願暴露的列,而後強制全部的insert語句都被傳送到該視圖。向一個簡單視圖插入數據,數據庫服務器會把它轉換爲針對基礎表的插入操做。
例如,建立以下視圖:

create view new_emps as
select empno, ename, job
    from emp;

執行下列插入語句

insert into new_emps (empno, ename, job)
    values (1, 'Jonathan', 'Editor');

會被翻譯成:

insert into emp (empno, ename, job)
    values (1, 'Jonathan', 'Editor');

當相關行存在時更新記錄

例如,若是一個員工出如今EMP_BONUS表中, 將他的工資(在EMP表中)上漲20%。

update emp
    set sal = sal*1.2
  where empno in (select empno from emp_bonus);

也可使用exists關鍵字:

update emp
    set sal = sal*1.2
  where exists (select null 
                    from emp_bonus
                 where emp.empno = emp_bonus.empno);

使用另外一個表的數據更新記錄

MySQL & Oracle

update emp set (e.sal, e.comm) = (select ns.sal, ns.sal/2
                                    from new_sal ns
                                  where ns.deptno = e.deptno)
    where exists (select null
                    from new_sal ns
                  where ns.deptno = e.deptno);

Oracle 更新內嵌視圖

update (
    select e.sal as emp_sal, e.comm as emp_comm,
        ns.sal as ns_sal, ns.sal/2 as ns_comm
      from emp e, new_sal ns
    where e.deptno = ns.deptno
) set emp_sal = ns_sal, emp_comm = ns_comm;

合併記錄

若是想根據相關記錄是否已經存在來插入、更新或刪除一個表的記錄,例如,若是記錄存在,則更新它,若是不存在,則插入一條新紀錄;若是更新以後的記錄不知足某個條件,則刪除它。
考慮以下條件來修改emp_commission表:
1) 若是emp_commission表的員工數據在emp表裏也存在相關記錄,則更新業務提成comm爲1000;
2)對於全部可能會把comm列更新爲1000的員工,若是他們的sal低於2000,則刪除相關記錄(他們不該該存在於emp_commission表中;
3)不然,就要從emp表中取出相應的empnoenamedeptno並插入到emp_commission表。

Oracle

merge into emp_commission ec
using (select * from emp) emp
   on (ec.empno = emp.empno)
 when matched then
      update set ec.comm = 1000
      delete where (sal < 2000)
 when not matched then
      insert (ec.empno, ec.ename, ec.deptno, ec.comm)
      values (emp.empno, emp.ename, emp.deptno, emp.comm);

刪除違反參照完整性的記錄

想從表裏刪除一些記錄,由於在另外一個表裏不存在與這些記錄相匹配的數據。例如,一些員工所屬的部門其實並不存在,你但願刪除這些員工。

delete from emp
    where not exists (
        select * from dept
          where dept.deptno = emp.deptno;
    );

或者

delete from emp 
    where deptno not in (select deptno from dept);

刪除重複記錄

考慮以下表dupes數據:

clipboard.png

對於每一組重複的名字,你但願保留任意一個ID,並刪除其他的。

delete from dupes
where id not in (
    select min(id) from dupes
        group by name);

clipboard.png

《SQL經典實例》第四章
相關文章
相關標籤/搜索