Hai bisogno di fare questo in un'operazione per garantire due connessioni simultanee non inserirà stesso fieldValue due volte:
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
è anche possibile utilizzare Double-checked locking per ridurre il blocco sovraccarico
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
per quanto riguarda il motivo per cui ISOLATION LEVEL SERIALIZABLE è necessario, quando si è all'interno di una transazione serializzabile, la prima tha SELEZIONA t colpisce la tabella crea un blocco dell'intervallo che copre il punto in cui deve essere il record, in modo che nessun altro possa inserire lo stesso record fino al termine della transazione.
Senza LIVELLO DI ISOLAMENTO SERIALIZZABILE, il livello di isolamento predefinito (READ COMMITTED) non bloccava la tabella in fase di lettura, quindi tra SELECT e UPDATE, qualcuno potrebbe ancora essere in grado di inserire. Le transazioni con il livello di isolamento READ COMMITTED non causano il blocco di SELECT. Le transazioni con REPEATABLE READS bloccano il record (se trovato) ma non il gap.
Quale linguaggio di programmazione stai utilizzando? Questo potrebbe essere fatto meglio all'interno di una transazione. –
possibile duplicato di [Inserire solo una riga se non è già lì] (http://stackoverflow.com/questions/3407857/only-inserting-a-row-if-its-not-already-there) –
Questo è il vecchia domanda; la domanda "Solo inserendo una riga" dovrebbe essere chiusa come duplicato di questo, non il contrario. –