sql >> Databasteknik >  >> RDS >> Mysql

Hur man översätter PostgreSQL merge_db (aka upsert) funktion till MySQL

Testad på 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');

Några tankar:

  • Du kan inte göra en uppdatering först och sedan kontrollera @ROW_COUNT() eftersom det returnerar antalet rader som faktiskt ändrats. Detta kan vara 0 om raden redan har värdet som du försöker uppdatera.
  • Också @ROW_COUNT() är inte replikeringssäker.
  • Du kan använda REPLACE...INTO .
  • Om du använder InnoDB eller en tabell med transaktionsstöd kanske du kan använda SELECT...FOR UPDATE (otestad).

Jag ser ingen fördel med den här lösningen jämfört med att bara använda INSERT...ON DUPLICATE KEY UPDATE .




  1. Hur man återställer MySQL-databas från fysiska filer

  2. XML-fel vid et-tecken (&)

  3. SQL Server Ändra databasnamn

  4. Hur lagrar jag beställningar?