sql >> Databáze >  >> RDS >> Mysql

Jak přeložit funkci PostgreSQL merge_db (aka upsert) do MySQL

Testováno na 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ěkteré myšlenky:

  • Nemůžete nejprve provést aktualizaci a poté zkontrolovat @ROW_COUNT() protože vrací počet skutečně změněných řádků. Může to být 0, pokud řádek již má hodnotu, kterou se pokoušíte aktualizovat.
  • Také @ROW_COUNT() není replikace bezpečná.
  • Můžete použít REPLACE...INTO .
  • Pokud používáte InnoDB nebo tabulku s podporou transakcí, možná budete moci použít SELECT...FOR UPDATE (netestováno).

Nevidím žádnou výhodu tohoto řešení oproti pouhému použití INSERT...ON DUPLICATE KEY UPDATE .




  1. PHP mysql PDO odmítá nastavit hodnotu NULL

  2. Provádění spojení napříč více heterogenními databázemi, např. PostgreSQL a MySQL

  3. SailsJS - Jak zadat délku atributu řetězce, aniž by došlo k chybě při vytváření záznamu?

  4. Chyba při použití shody vzorů, která není podobná žádné v PostgreSQL