UPDATE table_name SET col1 = val1, col2 = val2, ... [WHERE condition];
-- 將 New York 改為 L.A. UPDATE Employee SET City = 'L.A.' WHERE City = 'New York'; -- 2 rows updated.
UPDATE test SET name = 'zhurhyme1', code = '007' WHERE i_d = '1';
-- 錯誤寫法
UPDATE test SET (name, code) = ('zhurhyme2', '007') WHERE i_d = '1'; -- ORA-00971
-- 正確:使用子查詢
UPDATE test
SET (name, code) = (SELECT 'zhurhyme3', '007' FROM dual)
WHERE i_d = '1';
UPDATE target t SET (t.col1, t.col2) = ( SELECT s.col1, s.col2 FROM source s WHERE s.id = t.id ) WHERE EXISTS (SELECT 1 FROM source s WHERE s.id = t.id);
`SELECT ... FOR UPDATE` 在查詢階段對符合條件的行加排他鎖 (行級鎖),直到交易 `COMMIT/ROLLBACK` 釋放,防止併發修改衝突。
| 語句 | 鎖定範圍 |
|---|---|
SELECT * FROM test FOR UPDATE | 全表所有行 |
SELECT * FROM test WHERE i_d = 1 FOR UPDATE | 僅 i_d=1 的行 |
SELECT * FROM test a JOIN t ON a.i_d=t.dept_id FOR UPDATE | 兩表所有符合連接條件的行 |
SELECT * FROM test a JOIN t ON a.i_d=t.dept_id WHERE a.i_d=1 FOR UPDATE | 兩表符合條件的行 |
SELECT * FROM test a JOIN t ON a.i_d=t.dept_id WHERE a.i_d=1 FOR UPDATE OF a.i_d | 僅鎖定 test 表 條件行,不鎖定 t 表 |
兩個 Session 同時對同一行執行 `FOR UPDATE` + `UPDATE ... WHERE CURRENT OF`:
-- Session 1
DECLARE
CURSOR cur_test IS
SELECT name, code FROM test WHERE i_d = 1 FOR UPDATE OF name;
BEGIN
FOR rec IN cur_test LOOP
UPDATE test SET name = 'TTTT1' WHERE CURRENT OF cur_test;
END LOOP;
-- 故意不 COMMIT
END;
/
-- Session 2 (同時執行)
DECLARE
CURSOR cur_test IS
SELECT name, code FROM test WHERE i_d = 1 FOR UPDATE OF name;
BEGIN
FOR rec IN cur_test LOOP
UPDATE test SET name = 'TTTT2' WHERE CURRENT OF cur_test;
END LOOP;
END;
/
-- Session 2 將阻塞等待 Session 1 釋放鎖
-- 若 Session 1 長時間不提交/回滾,Session 2 永久阻塞 → 應用層面死鎖
SELECT ... FOR UPDATE NOWAIT; -- 立即返回 ORA-00054 SELECT ... FOR UPDATE WAIT 5; -- 等待 5 秒後報錯
CREATE OR REPLACE TRIGGER trigger1
BEFORE INSERT OR DELETE OR UPDATE ON triggertest
FOR EACH ROW
BEGIN
testpro1; -- 呼叫存儲過程
END;
/
CREATE OR REPLACE PROCEDURE testpro1 AS
BEGIN
INSERT INTO tab1 (id, name, score) VALUES ('AAA', 'BBB', 200);
END;
/
-- 觸發器執行後,tab1 自動新增一筆
-- triggertest.name 變更時,同步更新 tab1.name CREATE OR REPLACE TRIGGER trigger1 AFTER UPDATE OF name ON triggertest FOR EACH ROW BEGIN UPDATE tab1 SET name = :NEW.name WHERE name = :OLD.name; END; / -- 執行:UPDATE triggertest SET name = '水兒' WHERE name = '月兒'; -- tab1 中 name='月兒' 的行同步改為 '水兒'