it-swarm.com.de

WENN EXISTIERT, WÄHLEN SIE ANDERES EINFÜGEN UND WÄHLEN SIE DANN AUS

Wie sagt man das folgende in Microsoft SQL Server 2005:

IF EXISTS (SELECT * FROM Table WHERE FieldValue='') THEN
   SELECT TableID FROM Table WHERE FieldValue=''
ELSE
   INSERT INTO TABLE(FieldValue) VALUES('')
   SELECT TableID FROM Table WHERE TableID=SCOPE_IDENTITY()
END IF

Ich versuche zu überprüfen, ob bereits ein leerer Feldwert vorhanden ist. Wenn dann diese TableID zurückgegeben wird, fügen Sie einen leeren Feldwert ein und geben Sie den entsprechenden Primärschlüssel zurück.

49
Phillip Senn

Sie müssen dies in der Transaktion tun, um sicherzustellen, dass zwei gleichzeitige Clients nicht zweimal denselben fieldValue einfügen:

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

sie können auch doppelt geprüftes Sperren verwenden, um den Sperraufwand zu verringern

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

Wenn Sie sich in einer serialisierbaren Transaktion befinden und ISOLATION LEVEL SERIALIZABLE erforderlich ist, erstellt das erste SELECT, das auf die Tabelle trifft, eine Bereichssperre, die die Stelle abdeckt, an der sich der Datensatz befinden soll, sodass niemand den gleichen Datensatz einfügen kann, bis diese Transaktion endet.

Ohne ISOLATION LEVEL SERIALIZABLE würde die Standardisolationsstufe (READ COMMITTED) die Tabelle zum Zeitpunkt des Lesens nicht sperren, sodass zwischen SELECT und UPDATE immer noch jemand einfügen kann. Transaktionen mit der Isolationsstufe READ COMMITTED führen nicht zum Sperren von SELECT. Transaktionen mit REPEATABLE READS sperren den Datensatz (falls gefunden), aber nicht die Lücke.

60
zvolkov
IF EXISTS (SELECT 1 FROM Table WHERE FieldValue='') 
BEGIN
   SELECT TableID FROM Table WHERE FieldValue=''
END
ELSE
BEGIN
   INSERT INTO TABLE(FieldValue) VALUES('')
   SELECT SCOPE_IDENTITY() AS TableID
END

Siehe hier für weitere Informationen zu IF ELSE

Hinweis: geschrieben ohne eine SQL Server-Installation praktisch, um dies zu überprüfen, aber ich denke, es ist richtig

Außerdem habe ich das EXISTS-Bit geändert, um SELECT 1 anstelle von SELECT * auszuführen, da es Ihnen egal ist, was in einem EXISTS-Bit zurückgegeben wird, solange ich auch das SCOPE_IDENTITY () -Bit geändert habe, um nur die Identität zurückzugeben Angenommen, TableID ist die Identitätsspalte

32
Jane

Du warst nah:

IF EXISTS (SELECT * FROM Table WHERE FieldValue='')
   SELECT TableID FROM Table WHERE FieldValue=''
ELSE
BEGIN
   INSERT INTO TABLE (FieldValue) VALUES ('')
   SELECT TableID FROM Table WHERE TableID=SCOPE_IDENTITY()
END
7
David

Sie müssen nur die Struktur des if...else..endif etwas:

if exists(select * from Table where FieldValue='') then begin
  select TableID from Table where FieldValue=''
end else begin
  insert into Table (FieldValue) values ('')
  select TableID from Table where TableID = scope_identity()
end

Sie könnten auch tun:

if not exists(select * from Table where FieldValue='') then begin
  insert into Table (FieldValue) values ('')
end
select TableID from Table where FieldValue=''

Oder:

if exists(select * from Table where FieldValue='') then begin
  select TableID from Table where FieldValue=''
end else begin
  insert into Table (FieldValue) values ('')
  select scope_identity() as TableID
end
2
Guffa

Es klingt so, als hätte dein Tisch keinen Schlüssel. Sie sollten es einfach mit dem INSERT versuchen können: Wenn es sich um ein Duplikat handelt, wird die Schlüsselbeschränkung durchbrochen und das INSERT schlägt fehl. Keine Sorge: Sie müssen nur sicherstellen, dass die Anwendung den Fehler nicht sieht/ignoriert. Wenn Sie 'Primärschlüssel' sagen, meinen Sie vermutlich IDENTITY Wert. Das ist alles sehr gut, aber Sie benötigen auch eine Schlüsselbeschränkung (z. B. UNIQUE) für Ihren natürlichen Schlüssel.

Ich frage mich auch, ob Ihr Verfahren zu viel bewirkt. Erwägen Sie, getrennte Verfahren für die Aktionen 'Erstellen' und 'Lesen' zu verwenden.

2
onedaywhen
DECLARE @t1 TABLE (
    TableID     int         IDENTITY,
    FieldValue  varchar(20)
)

--<< No empty string
IF EXISTS (
    SELECT *
    FROM @t1
    WHERE FieldValue = ''
) BEGIN
    SELECT TableID
    FROM @t1
    WHERE FieldValue=''
END
ELSE BEGIN
    INSERT INTO @t1 (FieldValue) VALUES ('')
    SELECT SCOPE_IDENTITY() AS TableID
END

--<< A record with an empty string already exists
IF EXISTS (
    SELECT *
    FROM @t1
    WHERE FieldValue = ''
) BEGIN
    SELECT TableID
    FROM @t1
    WHERE FieldValue=''
END
ELSE BEGIN
    INSERT INTO @t1 (FieldValue) VALUES ('')
    SELECT SCOPE_IDENTITY() AS TableID
END
1
Rob Garrison
create schema tableName authorization dbo
go
IF OBJECT_ID ('tableName.put_fieldValue', 'P' ) IS NOT NULL 
drop proc tableName.put_fieldValue
go
create proc tableName.put_fieldValue(@fieldValue int) as
declare @tableid int = 0
select @tableid = tableid from table where fieldValue=''
if @tableid = 0 begin
   insert into table(fieldValue) values('')
   select @tableid = scope_identity()
end
return @tableid
go
declare @tablid int = 0
exec @tableid = tableName.put_fieldValue('')
1
Phillip Senn