2017-08-05 123 views
4

我使用MySQL的5.7節點JS 6.11.0,我試圖每當我插入一個衝突行更新UNIQUE MySQL的列。但是,當我嘗試插入衝突記錄時,只有現有記錄更新爲NULL,並且沒有發生insert。這裏是我的代碼節點MySQL在重複鍵更新更新唯一行

 pool.getConnection(function(err, connection) { 
     var newClass = req.body; 
     var query = `INSERT INTO classes SET ? ON DUPLICATE KEY UPDATE teacher_id = NULL`; 

     connection.query(query, newClass, function(err, result) { 
      console.log(result); 
      if(result.affectedRows >= 1) { 
       res.status(201).end(); 
       res.json(result); 
      } 
     }); 
     connection.release(); 
    });` 

我有兩次被插入的行運行查詢;第一次將衝突列設置爲空,那麼當我再次運行相同的查詢時,由於沒有衝突,因此插入了行。

我已經採取了生成的SQL並直接從MySql控制檯運行它,我仍然必須運行查詢兩次插入新行。我不明白爲什麼它會這樣做。

SQL語句

INSERT INTO classes SET `stream` = 'Red', `form` = '1', `teacher_id` = '7' ON DUPLICATE KEY UPDATE teacher_id = NULL 

我創建表的SQL是

| classes | CREATE TABLE `classes` (
     `id` int(11) NOT NULL AUTO_INCREMENT, 
     `form` varchar(10) NOT NULL, 
     `stream` varchar(15) NOT NULL, 
     `teacher_id` int(11) DEFAULT NULL, 
     PRIMARY KEY (`id`), 
     UNIQUE KEY `teacher_id` (`teacher_id`), 
     CONSTRAINT `classes_ibfk_1` FOREIGN KEY (`teacher_id`) REFERENCES `teachers` 
     (`id`) 
    ) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=latin1 |` 

爲什麼MySQL的行爲這種方式?

回答

4
INSERT INTO classes 
     SET stream = 'Red', form = '1',teacher_id = '7' 
    ON DUPLICATE KEY UPDATE teacher_id = NULL; 

告訴MySQL時有衝突記錄(複製唯一或主鍵),對違規行的teacher_id列設置爲null和停止。

你有幾個選項來實現你想要的結果。

首先,您可以使用REPLACE語法。

REPLACE INTO classes SET stream = 'Red', form = '1', teacher_id = '7'; 

哪個會先刪除與UNIQUE或PRIMARY KEY約束違規行,插入新行與指定的值。缺點是任何省略的列值將丟失並設置爲其默認值。如果在查詢中沒有指定,也會創建一個新的自動生成的(如果有的話)ID。 如果沒有違規記錄,則會發生正常INSERT

否則,您可以在UPDATE條款中使用VALUES

INSERT INTO classes 
     SET stream = 'Red', form = '1', teacher_id = '7' 
    ON DUPLICATE KEY UPDATE stream = VALUES(stream), 
          form = VALUES(form); 

這將代替,更新違規行查詢的INSERT部分指定的值的記錄。

參考文獻:


基於新的意向

爲了創造一個新的紀錄,同時離開原來RO更新w,在使用INSERT之前,您需要首先使現有行上的UNIQUE約束失效。 目前沒有方法可以在單個查詢中對MySQL進行此操作。

由於INSERT的限制,完成所需操作的最簡單方法是在INSERT查詢之前運行UPDATE查詢。

UPDATE classes 
    SET teacher_id = NULL 
    WHERE teacher_id = '7'; 
INSERT INTO classes 
    SET stream = 'Red', 
    form = '1', 
    teacher_id = '7'; 

這將首先檢查衝突teacher_id記錄並將其設置爲null。如果不存在衝突記錄,則不會發生更新。然後INSERT會創建所需的記錄,而不會發生衝突。

+0

我想達到的目標是先更新違規行,然後再插入新行。是否有可能做到這一點? –

+0

@DennisWanyonyi用新的意圖更新。 – fyrye

+0

所以@fyrye意味着我必須在MySQL中爲您建議的查詢啓用'multiple statements'。 –

2

如果要插入基於條件數據,如果你想嘗試這種

INSERT INTO table1 SELECT 'Red',1,7 FROM table2 where teacher_id IS NULL; 

其他更新基於此嘗試。

update table1 SET stream = 'Red', form = '1', teacher_id = '7' where teacher_id IS NULL; 

注意:NULL = NULL不是真FALSE - 它再次爲NULL。但它也不是TRUE,所以IF(NULL = NULL)將不會執行 例如,即使對NULL本身,NULL也會測試FALSE。因此,只有使用上述函數(和IS NULL())才能使用NULL。您的查詢可以如上所述重寫。

+0

'table2'從哪裏來? –

+0

只看到它的table1,我的錯誤。但是,如果我們可以設置主鍵和外鍵關係,您還可以使用該查詢更新父nd子表。 – HariKishore