MySQL 5.5.14 पर परीक्षण किया गया।
CREATE TABLE db (a INT PRIMARY KEY, b TEXT);
DELIMITER //
CREATE PROCEDURE merge_db(k INT, data TEXT)
BEGIN
DECLARE done BOOLEAN;
REPEAT
BEGIN
-- If there is a unique key constraint error then
-- someone made a concurrent insert. Reset the sentinel
-- and try again.
DECLARE ER_DUP_UNIQUE CONDITION FOR 23000;
DECLARE CONTINUE HANDLER FOR ER_DUP_UNIQUE BEGIN
SET done = FALSE;
END;
SET done = TRUE;
SELECT COUNT(*) INTO @count FROM db WHERE a = k;
-- Race condition here. If a concurrent INSERT is made after
-- the SELECT but before the INSERT below we'll get a duplicate
-- key error. But the handler above will take care of that.
IF @count > 0 THEN
UPDATE db SET b = data WHERE a = k;
ELSE
INSERT INTO db (a, b) VALUES (k, data);
END IF;
END;
UNTIL done END REPEAT;
END//
DELIMITER ;
CALL merge_db(1, 'david');
CALL merge_db(1, 'dennis');
कुछ विचार:
- आप पहले अपडेट नहीं कर सकते और फिर
@ROW_COUNT()
क्योंकि यह वास्तव में बदली गई पंक्तियों की संख्या लौटाता है। यह 0 हो सकता है यदि पंक्ति में पहले से ही वह मान है जिसे आप अपडेट करने का प्रयास कर रहे हैं। - साथ ही,
@ROW_COUNT()
प्रतिकृति सुरक्षित नहीं है। - आप उपयोग कर सकते हैं
REPLACE...INTO
। - यदि आप InnoDB या लेन-देन समर्थन वाली तालिका का उपयोग कर रहे हैं, तो आप
SELECT...FOR UPDATE
का उपयोग करने में सक्षम हो सकते हैं (परीक्षण नहीं किया गया)।
मुझे केवल INSERT...ON DUPLICATE KEY UPDATE
का उपयोग करने पर इस समाधान का कोई लाभ नहीं दिखता .