sql >> Databáze >  >> RDS >> Sqlserver

POKUD EXISTUJE, PAK VYBERTE JINÉ VLOŽENÍ A POTOM VYBERTE

Musíte to udělat v transakci, abyste zajistili, že dva simultánní klienti nevloží stejnou hodnotu pole dvakrát:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
    DECLARE @id AS INT
    SELECT @id = tableId FROM table WHERE [email protected]
    IF @id IS NULL
    BEGIN
       INSERT INTO table (fieldValue) VALUES (@newValue)
       SELECT @id = SCOPE_IDENTITY()
    END
    SELECT @id
COMMIT TRANSACTION

můžete také použít Double-checked zamykání snížit režii zamykání

DECLARE @id AS INT
SELECT @id = tableID FROM table (NOLOCK) WHERE [email protected]
IF @id IS NULL
BEGIN
    SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
    BEGIN TRANSACTION
        SELECT @id = tableID FROM table WHERE [email protected]
        IF @id IS NULL
        BEGIN
           INSERT INTO table (fieldValue) VALUES (@newValue)
           SELECT @id = SCOPE_IDENTITY()
        END
    COMMIT TRANSACTION
END
SELECT @id

Pokud jde o to, proč je nezbytná SERIALIZAČNÍ ÚROVEŇ IZOLACE, když jste uvnitř serializovatelné transakce, první SELECT, který zasáhne tabulku, vytvoří zámek rozsahu pokrývající místo, kde by měl být záznam, takže nikdo jiný nemůže vložit stejný záznam, dokud tato transakce neskončí.

Bez IZOLACE LEVEL SERIALIZABLE by výchozí úroveň izolace (READ COMMITTED) neuzamkla tabulku v době čtení, takže mezi SELECT a UPDATE by někdo stále mohl vkládat. Transakce s úrovní izolace READ COMMITTED nezpůsobí uzamčení SELECT. Transakce s REPEATABLE READS uzamknou záznam (pokud byl nalezen), ale ne mezeru.



  1. převádění řádků tabulky na sloupce v mysql

  2. Codeigniter nemůže odstranit řádky z databázové tabulky pomocí metody spojení

  3. Doporučený systém zálohování za provozu pro MySQL?

  4. Vybíráte všechny sloupce, které začínají XXX pomocí zástupného znaku?