programing

존재하는 경우, 다른 삽입을 선택한 다음 선택

padding 2023. 9. 5. 19:44
반응형

존재하는 경우, 다른 삽입을 선택한 다음 선택

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

내가 하려는 것은 빈 필드 값이 이미 있는지 확인하고 해당 표를 반환하는 것입니다.ID를 입력하지 않으면 빈 필드 값을 삽입하고 해당 기본 키를 반환합니다.

트랜잭션에서 이 작업을 수행하여 두 클라이언트가 동일한 필드 값을 두 번 삽입하지 않도록 해야 합니다.

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

이중 체크 잠금을 사용하여 잠금 오버헤드를 줄일 수도 있습니다.

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

분리 레벨 직렬화가 필요한 이유에 대해 말하자면, 직렬화 가능한 트랜잭션 내부에 있을 때 테이블을 처음으로 치는 선택은 레코드가 있어야 하는 위치를 커버하는 범위 잠금을 생성하므로 이 트랜잭션이 끝날 때까지 다른 사용자가 동일한 레코드를 삽입할 수 없습니다.

분리 레벨 직렬화가 없으면 기본 분리 레벨(READ COMMITED)이 읽기 시간에 테이블을 잠그지 않으므로 SELECT와 UPDATE 사이에 다른 사용자가 계속 삽입할 수 있습니다.READ COMMITED 분리 수준의 트랜잭션은 SELECT를 잠그지 않습니다.반복 가능 읽기를 사용하는 트랜잭션은 레코드를 잠그지만(찾은 경우) 공백은 잠기지 않습니다.

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

IF ELSE에 대한 자세한 내용은 여기를 참조하십시오.

참고: SQL Server 설치 없이 작성되어 이중으로 확인할 수 있습니다. 하지만 맞는 것 같습니다.

또한 기존 비트를 SELECT가 아닌 SELECT 1로 변경했습니다*. 기존 비트 내에서 반환되는 것은 상관없기 때문입니다. 무언가가 존재하는 한 SCOPE_IDENITY() 비트도 다음 표를 가정하여 ID만 반환하도록 변경했습니다.ID는 ID 열입니다.

당신은 가까웠습니다.

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

당신은 단지 구조를 바꾸기만 하면 됩니다.if...else..endif다소:

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

다음 작업도 수행할 수 있습니다.

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

또는:

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

당신의 테이블에 열쇠가 없는 것처럼 들립니다.당신은 간단히 시도할 수 있어야 합니다.INSERT만약 그것이 복제된다면, 핵심 제약 조건은 물릴 것이고 그리고.INSERT실패합니다.걱정할 필요 없습니다. 응용 프로그램이 오류를 인식하거나 무시하지 않도록 해야 합니다.'기본 키'라는 말은 아마도IDENTITY값. 그것은 모두 매우 좋지만, 당신은 또한 핵심 제약 조건)도 필요합니다.UNIQUE) 자연 키에 있습니다.

또한 당신의 시술이 너무 많은 것은 아닌지 궁금합니다.각각 '만들기' 및 '읽기' 작업에 대해 별도의 절차를 갖는 것을 고려합니다.

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
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('')

언급URL : https://stackoverflow.com/questions/1488355/if-exists-then-select-else-insert-and-then-select

반응형