2009-07-31 65 views
15

的價值,我想有一個觸發器用於插入記錄執行以下操作:MySQL的觸發器來現場升級到ID

# pseudocode 
if new.group_id is null 
    set new.group_id = new.id 
else 
    # don't touch it 
end 

更清楚:說我有一個表有三列:id主鍵,group_id int,value varchar。

當我與group_id這樣的插入:

INSERT INTO table(value, group_id) VALUES ('a', 10) 

我想有:

id | group_id | value 
---+----------+------ 
1 |  10 | a 

但是當我忽略group_id

INSERT INTO table(value) VALUES ('b') 

應該自動設置爲該記錄的id

id | group_id | value 
---+----------+------ 
2 |  2 | b 

觸發器可能嗎? (我知道插入,但有觸發的還要好後我可以更新記錄。)

回答

25

我不知道有什麼辦法在一個語句中做到這一點,即使使用觸發器。

是@Lucky建議看起來像這樣在MySQL中,引發劑溶液:

CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable 
FOR EACH ROW BEGIN 
    SET NEW.group_id = COALESCE(NEW.group_id, NEW.id); 
END 

然而,有一個問題。在BEFORE INSERT階段,自動生成的id值尚未生成。所以,如果group_id爲null,則默認爲NEW.id這始終是0

但是,如果你改變了這個觸發器在AFTER INSERT相火,所以你必須訪問的NEW.id所產生的價值,不能修改列值。

MySQL不支持列的DEFAULT的表達式,因此您無法在表定義中聲明此行爲。

唯一的解決辦法是做INSERT,然後立即做一個UPDATE更改group_id如果它沒有設置。

INSERT INTO MyTable (group_id, value) VALUES (NULL, 'a'); 
UPDATE MyTable SET group_id = COALESCE(group_id, id) WHERE id = LAST_INSERT_ID(); 
+0

這很糟糕。即使在2016年 – 2017-01-05 08:52:17

+0

@AA_PV,這可以通過獨立的序列對象來解決,就像他們在Oracle中一樣。自2003年以來,這一直是MySQL的一項開放功能請求:https://bugs.mysql.com/bug.php?id = 1625但是在Oracle中,要使用序列,您必須*在應用程序代碼中調用它,意味着將* every * INSERT的代碼寫入您想擁有auto-inc主鍵的表中。或者爲每個*這樣的表寫一個觸發器。 MySQL用戶喜歡能夠跳過寫這麼多觸發器,而只是聲明`AUTO_INCREMENT`作爲列選項。 – 2017-01-05 15:31:49

0

我相信,這會爲你工作

我有兩個表

test_b: a_id, value 
test_c: a_id, value 

這裏是一個觸發測試插入b。它會檢查a_id是否爲空,如果是,則插入0

CREATE TRIGGER test_b AFTER INSERT ON test_b 
    FOR EACH ROW 
    INSERT INTO test_c (a_id, value) VALUES (IFNULL(NEW.a_id, 0),NEW.value) 
+0

如果你告訴我更多關於你的表的結構,我可以修改這個查詢爲你工作。 – 2009-07-31 15:27:27

-2

此觸發器應該按照您的要求做。

CREATE TRIGGER mytrigger BEFORE INSERT ON mytable 
      IF new.group_id IS NULL 
      SET new.group_id = new.id 
      END IF 
     END; 

它從MYSQL documentation頁面中的一個非常類似的示例中複製而來。

+0

在MySQL上不起作用: 您在SQL語法中有錯誤;檢查與您的MySQL服務器版本相對應的手冊,以獲取在第1行'WHERE new.group_id IS NULL END'附近使用的正確語法 – szeryf 2009-09-25 11:12:25

+0

您應該能夠從http://dev.mysql上的示例中獲得確切的語法.com/doc/refman/5.1/en/create-trigger.html - 我沒有測試。我會嘗試編輯 – Lucky 2009-09-27 08:35:16

-2

在這種情況下觸發器看起來像是矯枉過正。只需應用默認值即可。

CREATE TABLE `test` (
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 
    `value` varchar(100) NOT NULL, 
    `group_id` TINYINT(3) UNSIGNED NOT NULL DEFAULT '2' 
) 
0

我回答在這裏,作爲公認的答案Bill Karwin狀態:

在BEFORE INSERT階段,值自動生成的ID沒有被 產生呢。所以,如果GROUP_ID爲null,則默認爲NEW.id這是 始終爲0


我有它的答案 - 爲OP(和遊客來),這裏有幾個要點: 您無法更新從該觸發被調用的表,因爲你會得到錯誤1442

Error Code: 1442 
Can't update table 'MyTable' in stored function/trigger because it is already used by statement which invoked this stored function/trigger. 

1.to更新的新行 使用BEFORE INSERT ON觸發,這樣你可以更新爲新行的所有字段,它可以是通過新的運營商即訪問

set NEW.group_id = NEW.id 

2.註冊AUTO_INCREMENT值前插入

SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='MyTable' 

綜上所述up - 觸發SQL爲'd是如下:

DELIMITER // 
DROP TRIGGER IF EXISTS MyTrigger// 
CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable 
FOR EACH ROW BEGIN 
    IF new.group_id IS NULL 
     set @auto_id := (SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES 
         WHERE TABLE_NAME='MyTable' AND TABLE_SCHEMA=DATABASE()); 
     set NEW.group_id = @auto_id; 
    ENF IF; 
END; 
// 
DELIMITER ;