Ø 簡介ide
本文介紹 Oracle 中的增刪改語句,即 INSERT、DELETE、UPDATE 語句的使用。是時候展示真正的技術了,快上車:測試
1. 插入數據(INSERT)spa
2. 修改數據(UPDATE)3d
3. 刪除數據(DELETE)日誌
4. 使用 MERGE INTO 語句完成增刪改操做orm
5. 回滾(rollback)的使用blog
6. 注意事項事務
1. 插入數據(INSERT)ip
u 語法:開發
INSERT INTO TABLE_NAME [(column1[, column2, …]] VALUES(value1[, value2, …]);
說明:
1) INSERT 數據時能夠指定列名,也可不指定列名。若是不指定列名,必須爲每一列都提供數據,而且順序必須與列名的順序一致;若是指定列名,提供的數據須要與指定的列名順序一致;
2) 插入數據時數字類型的列可直接寫入,字符或日期類型的列須要加單引號;
3) 插入的數據必須知足約束規則,主鍵和 NOT NULL 的列必須提供數據。
u 插入數據的方式
1) 首先,能夠在 PL/SQL Developer 中使用 FOR UPDATE 語句
1. 首先執行 SELECT 語句
SELECT * FROM Table01 FOR UPDATE;
2. 點擊鎖表按鈕
3. 編輯數據 -> 記入改變 -> 表解鎖按鈕
4. 最後點擊提交
l 說明:低版本的 PL/SQL Developer 操做與以上相似。
2) 使用 INSERT INTO 語句,插入一條數據
INSERT INTO Table01(Id, Name) VALUES(2, '李四'); --指定全部列
COMMIT; --必須執行提交命令
提示:在日常開發中,建議顯示指定插入的列名,有助於提升代碼的可讀性。
INSERT INTO Table01(Id) VALUES(3); --指定部分列,其餘未指定的列表必須能夠爲空(即 NULL)
COMMIT;
INSERT INTO Table01 VALUES(4, '王五'); --不指定任何列,必須按順序插入全部列
COMMIT;
3) 使用 INSERT INTO SELECT 語句,插入多條數據
INSERT INTO Table02 SELECT * FROM Table01; --將 Table01 中的全部數據插入 Table02 中(注意:能夠指定插入的列;Table02 必須存在;可指定 Table01 的查詢條件)
COMMIT;
4) 另外,還可使用 PL/SQL Developer 中使用變量的方式(該方式不怎麼實用,不作詳細介紹)
INSERT INTO Table01 VALUE(&Id, &Name);
5) 同時插入多條(支持多表插入)
INSERT ALL
INTO Table01 VALUES(10, '張10')
INTO Table01 VALUES(11, '張11')
INTO Table02 VALUES(20, '李20') --同時插入 Table02
SELECT * FROM DUAL;
COMMIT;
注意:
1. INSERT ALL INTO 在效率上,比逐條執行 INSERT INTO 語句要高不少;
2. 在使用 INSERT ALL INTO 語句插入數據時,對於主鍵使用序列插入式,多條 INTO 會違反約束條件(即對於同一個序列的多條 INTO 會產生相同的序列號),因此使用序列插入時,並不適用使用 INSERT ALL INTO 同時插入多條數據!
n 注意事項:
1. 在插入數值(number)和字符(char)類型時,Oracle 支持數值與字符相互轉換,例如:
字符轉數值:
INSERT INTO Tab01(id) VALUES('12a'); --ORA-01722:無效數字
INSERT INTO Tab01(id) VALUES('123'); --插入成功,結果爲123
INSERT INTO Tab01(id) VALUES('456.56'); --插入成功,結果爲457(四捨五入)
數值轉字符:
INSERT INTO Tab01(name) VALUES(123); --插入成功,結果爲123
INSERT INTO Tab01(name) VALUES(123.56); --插入成功,結果爲123.56
提示:雖然 Oracle 支持這種轉換,可是並不建議使用該方式去寫入數據,不利於理解和閱讀。
2. 插入字符類型字段時,超過指定長度直接報錯,例如:
CREATE TABLE Tab02(name varchar2(2) NOT NULL);
INSERT INTO Tab02(name) VALUES('abcd'); --插入失敗(並不會截斷,而是直接報錯)
INSERT INTO Tab02(name) VALUES('ab'); --插入成功,結果爲ab
3. 插入字符和日期類型時,必須加上單引號,例如:'中國', '22-08-2018'。
4. 插入的字符類型能夠爲空(NULL)時,也能夠指定爲空字符串,例如:
CREATE TABLE Tab03(id number(3) NOT NULL, name varchar2(10) NULL);
INSERT INTO Tab03(id, name) VALUES(1, null); --插入成功,結果爲NULL
INSERT INTO Tab03(id, name) VALUES(2, ''); --插入成功,結果也爲NULL
INSERT INTO Tab03(id, name) VALUES(3, ' '); --插入成功,結果爲' '
SELECT * FROM Tab03 WHERE name IS NULL;
SELECT t.*, dump(name) FROM Tab03 t;
由以上兩個查詢能夠看出,在 Oracle 中對於字符類型,''(空字符串)也將以 NULL 對待,即:空字符串就是 NULL, NULL 也是空字符串。
5. 插入 DATE 類型的字段時,須要對日期格式進行轉換,例如:
to_date('1985/10/22', 'yyyy/mm/dd')
2. 修改數據(UPDATE)
u 語法:
UPDATE TABLE_NAME SET column1 = value1[, column2 = value2…] [WHERE 條件];
說明:規則與 INSERT 語句相似。
u 修改數據的方式
1) 一樣,也能夠在 PL/SQL Developer 中使用 FOR UPDATE 語句,進行修改操做
SELECT * FROM Table01 FOR UPDATE;
說明:操做步驟與插入數據相似,只是一個是修改原有的數據,一個是新增數據。
2) 使用 UPDATE 語句更新
UPDATE Table01 SET Name='張山' WHERE Id=1; --更新多個字段,使用「,」逗號分隔
COMMIT;
3) 子查詢更新(多列)
UPDATE Table02 SET(Id, Name) = (SELECT Id, Name FROM Table01 WHERE Id=1) WHERE Id=1; --將 Table02 中的 Id, Name 列更新爲 Table01 中的 Id, Name,這裏沒有其餘列,就以 Id 列代替了
COMMIT;
3. 刪除數據(DELETE)
u 語法:
DELETE FROM TABLE_NAME or VIEW_NAME [WHERE <condition>];
注意:刪除數據前,該記錄若是存在外鍵關聯,須要先刪除外鍵表中的關聯數據。
u 刪除數據的方式
1) 一樣,也能夠在 PL/SQL Developer 中使用 FOR UPDATE 語句,進行刪除操做
SELECT * FROM Table01 FOR UPDATE;
說明:操做步驟與插入數據相似,點擊「刪除記錄」按鈕便可。
2) 使用 DELETE 語句
DELETE FROM Table01 WHERE Id=3;
COMMIT;
3) 使用 TRUNCATE 語句
TRUNCATE TABLE Table02;
n 注意事項
TRUNCATE 語句具備如下特徵:
1. 不能加 WHERE 條件,清除整表數據;
2. 不須要 COMMIT 提交,不支持事務回滾,而且會結束 SAVEPOINT(回滾點);
3. 效率高於 DELETE 語句(速度較快);
4. 不記錄日誌,並清除所佔用的空間;
5. 不會觸發 DELETE 出發器等特色。
而 DELETE 語句的特徵:
1. 能夠根據條件刪除數據;
2. 須要顯示 COMMIT 提交,支持事務回滾;
3. 會記錄更新日誌,刪除後仍然佔用物理空間;
4. 會觸發 DELETE 觸發器等。
4. 使用 MERGE INTO 語句完成增刪改操做
MERGE INTO 是 Oracle 9i 中新增的語句,MERGE 語句能夠從一個或多個源表中選擇數據,並將其更新或插入到目標表中。MERGE 語句容許指定條件,以肯定是從目標表更新數據仍是向目標表中插入數據。到 Oracle 10g 中又對 MERGE INTO 進行了改進,改進以下:
1) UPDATE 或 INSERT 子句能夠是可選的;
2) UPDATE 和 INSERT 子句能夠加 WHERE 子句;
3) UPDATE 後面能夠跟 DELETE 子句來刪除記錄(此時不會更新記錄);
n 完整語法
MERGE INTO target_table
USING source_table
ON search_condition
WHEN MATCHED THEN
UPDATE SET col1 = value1, col2 = value2,...
WHERE <update_condition>
[DELETE WHERE <delete_condition>]
WHEN NOT MATCHED THEN
INSERT (col1,col2,...)
values(value1,value2,...)
WHERE <insert_condition>;
n 示例
1) 單獨使用 THEN UPDATE 子句,將 A 表的數據更新至 B 表
在 SQL Server 中支持如下語法將 A 表的數據更新到 B 表(固然 SQL Server 也是支持 MERGE 語句):
UPDATE Tab04 SET [money]=t5.[money] FROM Tab05 AS t5
WHERE Tab04.id = t5.id; --Tab04 遇到 t5 相同的記錄,只會更新爲 t5 第一個記錄的值,並不會報錯
在 Oracle 中不支持以上的更新語法,但可使用 MERGE INTO 子句來完成,看示例:
--建立表
CREATE TABLE Tab04(id number(3), money number(8,2));
CREATE TABLE Tab05(id number(3), money number(8,2));
--插入數據
TRUNCATE TABLE Tab04;
TRUNCATE TABLE Tab05;
INSERT ALL
INTO Tab04 VALUES(1, 100)
INTO Tab04 VALUES(2, 200)
INTO Tab04 VALUES(6, 600)
INTO Tab04 VALUES(6, 610)
INTO Tab04 VALUES(7, 700)
INTO Tab04 VALUES(9, 900)
INTO Tab05 VALUES(1, 1000)
INTO Tab05 VALUES(2, 2000)
--INTO Tab05 VALUES(2, 2100)
INTO Tab05 VALUES(6, 6000)
INTO Tab05 VALUES(8, 8000)
INTO Tab05 VALUES(9, 9000)
SELECT 1 FROM DUAL;
COMMIT;
--更新數據
MERGE INTO Tab04 t4
USING Tab05 t5 ON(t4.id = t5.id)
WHEN MATCHED THEN UPDATE SET t4.money = t5.money WHERE t1.id < 9; --id=9的記錄將不會更新
--查詢結果
SELECT * FROM Tab04;
注意事項:
1. Tab04 能夠被匹配到多條記錄,匹配到多條記錄將一同更新;
2. Tab04 沒有匹配的記錄將不會更新,保持原來的值;
3. Tab05 多條記錄與 Tab04 中匹配時,將報錯:ORA-30926:沒法在原表中得到一組穩定的行(與 SQL Server 不同)。由於 MERGE 是肯定性語句,因此不能在同一條語句中屢次更新目標表的同一行 MERGE。
4. Tab05 的記錄與 Tab04 未匹配時,不會報錯。
當我但願 Tab05 中相同 Id 中金額最大的一條更新到 Tab04 時,能夠這樣寫:
MERGE INTO Tab04 t4
USING (SELECT id, MAX(money) money FROM Tab05 GROUP BY id) t5 ON(t4.id = t5.id)
WHEN MATCHED THEN UPDATE SET t4.money = t5.money WHERE t4.id < 9; --加了一個被處理過的派生表(t5)
提示:先取消 --INTO Tab05 VALUES(2, 2100) 的註釋
--再次查詢
SELECT * FROM Tab04;
2) 單獨使用 THEN INSERT 子句,不存在則插入數據
1. 首先,建立目標表,並寫入兩條記錄
CREATE TABLE tar_dept1 AS SELECT * FROM dept WHERE rownum <= 2;
SELECT * FROM tar_dept1;
2. 插入源表的記錄在目標表中不存在的記錄
MERGE INTO tar_dept1 t1
USING dept t2 ON(t1.deptno = t2.deptno)
WHEN NOT MATCHED THEN
INSERT (deptno, dname, loc) VALUES(t2.deptno, t2.dname, t2.loc);
SELECT * FROM tar_dept1;
DROP TABLE tar_dept1; --刪除測試表
3) 同時更新(存在)或插入(不存在)數據
1. 建立目標表,並寫入兩條記錄
CREATE TABLE tar_dept1 AS SELECT * FROM dept WHERE rownum <= 2;
SELECT * FROM tar_dept1;
2. 修改源表中的數據(用於測試)
UPDATE dept SET loc = loc || 'new';
SELECT * FROM dept;
3. 同時更新或插入
MERGE INTO tar_dept1 t1
USING dept t2 ON(t1.deptno = t2.deptno)
WHEN MATCHED THEN
UPDATE SET t1.dname = t2.dname, t1.loc = t2.loc
WHEN NOT MATCHED THEN
INSERT (deptno, dname, loc) VALUES(t2.deptno, t2.dname, t2.loc);
SELECT * FROM tar_dept1;
DROP TABLE tar_dept1; --刪除測試表
4) DELETE WHERE 子句的使用
DELETE 子句通常用的很少,該 DELETE 子句僅刪除目標表中與 ON 和 DELETE WHERE 子句同時匹配的行(此時,將忽略更新語句)。例如,將以上代碼改成下面代碼時,從新執行將獲得以下結果:
MERGE INTO tar_dept1 t1
USING dept t2 ON(t1.deptno = t2.deptno)
WHEN MATCHED THEN
UPDATE SET t1.dname = t2.dname, t1.loc = t2.loc
DELETE WHERE t1.deptno > 10 --這裏將刪除大於10的記錄,並忽略更新
WHEN NOT MATCHED THEN
INSERT (deptno, dname, loc) VALUES(t2.deptno, t2.dname, t2.loc);
SELECT * FROM tar_dept1;
n 總結
1. MERGE 一般用於數據同步的場景,將一個數據源中的數據同步到另外一個數據源(表)中,同時執行更新或插入操做;
2. 注意,在 MERGE 語句中只有當源表中存在查詢出記錄時,纔會執行更新或刪除操做。能夠這樣理解,若是不分析執行計劃,根據推理 MERGE 的執行順序應該是:
1) 首先,查詢源表中的數據;
2) 再根據源表中的每行記錄,去匹配目標表中進行匹配;
3) 匹配到記錄,則執行 THEN UPDATE(更新),不然執行 THEN INSERT(插入);
4) 因此,在源表中不能出現相同的記錄,去屢次更新目標表中的同一條記錄。
5. 回滾(rollback)的使用
當咱們在編寫 SQL 代碼進行 CUD 時,能夠設置回滾點,將當前操做數據回滾到某一個狀態下。建立回滾點使用 SAVEPOINT savepoint_name 語句,回滾到指定位置使用 ROLLBACK TO savepoint_name 語句,示例以下:
--建立表
CREATE TABLE Tab06(id number(3), money number(8,2));
--建立回滾點:SAVE_INSERT
SAVEPOINT SAVE_INSERT;
--插入數據
--TRUNCATE TABLE Tab06;
INSERT ALL
INTO Tab06 VALUES(1, 100)
INTO Tab06 VALUES(2, 200)
SELECT * FROM DUAL;
--建立回滾點:SAVE_UPDATE
SAVEPOINT SAVE_UPDATE;
--更新數據
UPDATE Tab06 SET money = money * 10;
--建立回滾點:SAVE_DELETE
SAVEPOINT SAVE_DELETE;
--刪除數據
DELETE FROM Tab06 WHERE id=2;
--能夠混滾到任意個回滾點(但只能依次往前回滾):
ROLLBACK TO SAVE_INSERT;
SELECT * FROM Tab06;
ROLLBACK TO SAVE_UPDATE;
SELECT * FROM Tab06;
ROLLBACK TO SAVE_DELETE;
SELECT * FROM Tab06;
n 注意:
當在設置回滾點以後,執行了 TRUNCATE 語句,回滾點將失效;
當在執行過程當中,建立了多個回滾點後,若是回滾到前一個回滾點後,就不能再回滾到後一個回滾點了,只能依次往前回滾。
6. 注意事項
1) 在 Oracle 中,全部有關對數據更改的操做(即:INSERT、UPDATE、DELETE)語句,執行完成後,都必須執行提交命令(COMMIT)。
2) 當使用 FRO UPDATE 語句增刪改時,並點擊鎖表按鈕後會進行鎖表,鎖表後其餘會話將不能進行增刪改操做,因此不建議使用該方式。