sql >> Databasteknik >  >> RDS >> Sqlserver

OM FINNS, VÄLJ ANNAT INSERT OCH VÄLJ SEDAN

Du måste göra detta i transaktionen för att säkerställa att två samtidiga klienter inte kommer att infoga samma fieldValue två gånger:

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

du kan också använda Dubbelkontrollerad låsning för att minska låsningsoverhead

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

Angående varför ISOLATION LEVEL SERIALIZABLE är nödvändigt, när du är inne i en serialiserbar transaktion, skapar den första SELECT som träffar tabellen ett intervalllås som täcker platsen där posten ska vara, så att ingen annan kan infoga samma post förrän denna transaktion avslutas.

Utan ISOLATION LEVEL SERIALIZABLE, skulle standardisoleringsnivån (READ COMMITTED) inte låsa tabellen vid läsningstidpunkten, så mellan SELECT och UPDATE skulle någon fortfarande kunna infoga. Transaktioner med READ COMMITTED isoleringsnivå orsakar inte att SELECT låses. Transaktioner med REPEATABLE READS låser posten (om den hittas) men inte gapet.



  1. fel i GWT Hibernate-program 2

  2. Mysql:Skapa inline-tabell inom select-satsen?

  3. Två kolumner i underfrågan i where-satsen

  4. Ignorera apostrof i mysql-sökningar