直接来自手册,这是PostgreSQL中merge_db的规范示例:
CREATE TABLE db (a INT PRIMARY KEY, b TEXT); CREATE FUNCTION merge_db(key INT, data TEXT) RETURNS VOID AS $$ BEGIN LOOP -- first try to update the key UPDATE db SET b = data WHERE a = key; IF found THEN RETURN; END IF; -- not there, so try to insert the key -- if someone else inserts the same key concurrently, -- we could get a unique-key failure BEGIN INSERT INTO db(a,b) VALUES (key, data); RETURN; EXCEPTION WHEN unique_violation THEN -- Do nothing, and loop to try the UPDATE again. END; END LOOP; END; $$ LANGUAGE plpgsql; SELECT merge_db(1, 'david'); SELECT merge_db(1, 'dennis');
可以在MySQL中将其表示为用户定义的函数吗?如果可以,该如何表达?会比MySQL的标准有优势INSERT...ON DUPLICATE KEY UPDATE吗?
INSERT...ON DUPLICATE KEY UPDATE
注意:我专门在寻找用户定义的函数,而不是INSERT...ON DUPLICATE KEY UPDATE。
在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()
REPLACE...INTO
SELECT...FOR UPDATE
与仅使用相比,我认为此解决方案没有任何优势INSERT...ON DUPLICATE KEY UPDATE。