sql >> Database teknologi >  >> RDS >> Sqlserver

HVIS FINDER, SÅ VÆLG ANDET INDSÆT OG SÅ VÆLG

Du skal gøre dette i transaktionen for at sikre, at to samtidige klienter ikke indsætter samme fieldValue to gange:

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 også bruge Dobbeltkontrolleret låsning for at reducere overhead ved låsning

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

Med hensyn til hvorfor ISOLATION LEVEL SERIALIZABLE er nødvendigt, når du er inde i en serialiserbar transaktion, skaber den første SELECT, der rammer bordet, en intervallås, der dækker det sted, hvor posten skal være, så ingen andre kan indsætte den samme post, før denne transaktion slutter.

Uden ISOLATIONSNIVEAU SERIALIZABLE, ville standardisolationsniveauet (READ COMMITTED) ikke låse tabellen på læsetidspunktet, så mellem SELECT og UPDATE ville nogen stadig være i stand til at indsætte. Transaktioner med READ COMMITTED isolationsniveau får ikke SELECT til at låse. Transaktioner med GENTAGBARE LÆSNINGER låser posten (hvis den findes), men ikke hullet.



  1. Hvad er makroer, og hvordan bruger jeg dem?

  2. Simpel PL/SQL-funktion til at teste om en streng er et tal

  3. Python MySQLdb undtagelser

  4. Tjek, om tilknytning eksisterer uden at pådrage sig et databasehit