복붙노트

[SQL] 행이 존재하는 경우, 그렇지 않으면 삽입, 확인

SQL

행이 존재하는 경우, 그렇지 않으면 삽입, 확인

나는 테이블의 행을 업데이트하는 T-SQL 저장 프로 시저를 작성해야합니다. 행이 존재하지 않는 경우, 삽입합니다. 트랜잭션 래핑이 모든 단계.

이 원자하고 신뢰할 수 있어야하기 때문에 이러한 현상이 예약 시스템입니다. 트랜잭션이 커밋과 비행 받았습니다 경우는 true를 반환해야합니다.

나는하지 있는지 @@ ROWCOUNT를 사용하는 방법에 대한, T-SQL에 새로운 해요. 이것은 내가 지금까지 쓴 것입니다. 나는 바른 길에 있습니까? 나는 확실히 당신을위한 쉬운 문제입니다.

-- BEGIN TRANSACTION (HOW TO DO?)

UPDATE Bookings
 SET TicketsBooked = TicketsBooked + @TicketsToBook
 WHERE FlightId = @Id AND TicketsMax < (TicketsBooked + @TicketsToBook)

-- Here I need to insert only if the row doesn't exists.
-- If the row exists but the condition TicketsMax is violated, I must not insert 
-- the row and return FALSE

IF @@ROWCOUNT = 0 
BEGIN

 INSERT INTO Bookings ... (omitted)

END

-- END TRANSACTION (HOW TO DO?)

-- Return TRUE (How to do?)

해결법

  1. ==============================

    1.MERGE 명령을 살펴보십시오. 당신은 UPDATE, INSERT 수행 및 하나 개의 문장에서 삭제할 수 있습니다.

    MERGE 명령을 살펴보십시오. 당신은 UPDATE, INSERT 수행 및 하나 개의 문장에서 삭제할 수 있습니다.

    다음은 MERGE를 사용하는 방법에 대한 작업 구현은 - 비행 다른, 업데이 트를 수행하기 전에 가득 삽입을 수행 여부를 확인합니다.

    if exists(select 1 from INFORMATION_SCHEMA.TABLES T 
                  where T.TABLE_NAME = 'Bookings') 
    begin
        drop table Bookings
    end
    GO
    
    create table Bookings(
      FlightID    int identity(1, 1) primary key,
      TicketsMax    int not null,
      TicketsBooked int not null
    )
    GO
    
    insert  Bookings(TicketsMax, TicketsBooked) select 1, 0
    insert  Bookings(TicketsMax, TicketsBooked) select 2, 2
    insert  Bookings(TicketsMax, TicketsBooked) select 3, 1
    GO
    
    select * from Bookings
    

    그리고 ...

    declare @FlightID int = 1
    declare @TicketsToBook int = 2
    
    --; This should add a new record
    merge Bookings as T
    using (select @FlightID as FlightID, @TicketsToBook as TicketsToBook) as S
        on  T.FlightID = S.FlightID
          and T.TicketsMax > (T.TicketsBooked + S.TicketsToBook)
      when matched then
        update set T.TicketsBooked = T.TicketsBooked + S.TicketsToBook
      when not matched then
        insert (TicketsMax, TicketsBooked) 
        values(S.TicketsToBook, S.TicketsToBook);
    
    select * from Bookings
    
  2. ==============================

    2.나는 각 항공편에 대해 하나의 행을 것 같은데요? 그렇다면:

    나는 각 항공편에 대해 하나의 행을 것 같은데요? 그렇다면:

    IF EXISTS (SELECT * FROM Bookings WHERE FLightID = @Id)
    BEGIN
        --UPDATE HERE
    END
    ELSE
    BEGIN
       -- INSERT HERE
    END
    

    나는 10 티켓 최대가있는 경우는 새로운 행을 삽입하므로, 비행기를 초과 예약 할 수있는 일을 당신의 방법으로, 말을 가정하면 20을 예약하고 있습니다.

  3. ==============================

    3.행의 존재 여부를 테스트 할 때 UPDLOCK, 노 걸이, HOLDLOCK 힌트를 전달합니다.

    행의 존재 여부를 테스트 할 때 UPDLOCK, 노 걸이, HOLDLOCK 힌트를 전달합니다.

    begin tran /* default read committed isolation level is fine */
    
    if not exists (select * from Table with (updlock, rowlock, holdlock) where ...)
        /* insert */
    else
        /* update */
    
    commit /* locks are released here */
    

    이미 존재하는 경우 UPDLOCK 힌트 힘은 쿼리가 커밋 또는 롤 다시 때까지 수정하는 다른 트랜잭션을 방지 행에 대한 업데이트 잠금을 촬영합니다.

    HOLDLOCK 힌트 힘 쿼리는 커밋 또는 롤 다시 때까지 필터 기준과 일치하는 행을 추가하는 다른 거래를 방지 범위 잠금을 촬영합니다.

    트랜잭션이 같은 페이지에 관련이없는 행을 업데이트하려고 다른 트랜잭션을 차단 (그러나 트레이드 오프 감소 된 경쟁과 증가 사이의 알 수 없습니다 그래서 노 걸이 힌트 힘은, 대신 기본 페이지 수준의 행 레벨로 세분화 잠금 잠금 오버 헤드 - 당신은) 하나의 트랜잭션에서 행 수준 잠금 많은 수의 복용하지 않도록해야합니다.

    자세한 내용은 http://msdn.microsoft.com/en-us/library/ms187373.aspx를 참조하십시오.

    트란을 시작 호출하는 것은 당신에게 당신이 그것에 도착하기 전에 뭔가에 잠금을 곤란 다른 트랜잭션에 대한 면역을 제공하지 않습니다 - 잠금 그들이 실행되는 걸릴 문으로 촬영합니다. 당신은 (초기 출시, 후반 획득) 가능한 한 빨리 트랜잭션을 커밋하여 최단 시간에 대한 잠금을 보유로 SQL을 시도하고 요소해야한다.

    하여 PK가 BIGINT 경우 SQL 서버의 내부 해시는 64 비트 값 (다른 키 값이 동일한 로크 ID로 해싱 수 있음)에 대한 축퇴 같이 행 레벨 잠금 덜 효과적 일 수 있음을 유의해야한다.

  4. ==============================

    4.난 내 솔루션을 쓰고 있어요. 또는 '병합'가 '내 방법은 서 있지 않습니다. 내 방법은 간단합니다.

    난 내 솔루션을 쓰고 있어요. 또는 '병합'가 '내 방법은 서 있지 않습니다. 내 방법은 간단합니다.

    INSERT INTO TableName (col1,col2)
    SELECT @par1, @par2
       WHERE NOT EXISTS (SELECT col1,col2 FROM TableName
                         WHERE col1=@par1 AND col2=@par2)
    

    예를 들면 :

    INSERT INTO Members (username)
    SELECT 'Cem'
       WHERE NOT EXISTS (SELECT username FROM Members
                         WHERE username='Cem')
    

    설명:

    (1) SELECT COL1, COL2 TABLENAME FROM WHERE COL1 = @ PAR1 AND COL2 = @ PAR2 그것은 TABLENAME 값을 검색으로부터 선택

    존재합니다 WHERE (2) @ PAR1, @ PAR2를 선택 하지 (1) 서브 쿼리에서 존재하는 경우는 소요

    (3)에 삽입 TABLENAME (2) 단계 값

  5. ==============================

    5.나는 마지막으로 이미 다음과 같은 모델을 사용하여, 존재하지 않는 것을 조건으로, 행을 삽입 할 수 있었다 :

    나는 마지막으로 이미 다음과 같은 모델을 사용하여, 존재하지 않는 것을 조건으로, 행을 삽입 할 수 있었다 :

    INSERT INTO table ( column1, column2, column3 )
    (
        SELECT $column1, $column2, $column3
          WHERE NOT EXISTS (
            SELECT 1
              FROM table 
              WHERE column1 = $column1
              AND column2 = $column2
              AND column3 = $column3 
        )
    )
    

    난에서 발견되는 :

    http://www.postgresql.org/message-id/87hdow4ld1.fsf@stark.xeocode.com

  6. ==============================

    6.이것은 내가 최근에해야 할 일을했을 뭔가 :

    이것은 내가 최근에해야 할 일을했을 뭔가 :

    set ANSI_NULLS ON
    set QUOTED_IDENTIFIER ON
    GO
    ALTER PROCEDURE [dbo].[cjso_UpdateCustomerLogin]
        (
          @CustomerID AS INT,
          @UserName AS VARCHAR(25),
          @Password AS BINARY(16)
        )
    AS 
        BEGIN
            IF ISNULL((SELECT CustomerID FROM tblOnline_CustomerAccount WHERE CustomerID = @CustomerID), 0) = 0
            BEGIN
                INSERT INTO [tblOnline_CustomerAccount] (
                    [CustomerID],
                    [UserName],
                    [Password],
                    [LastLogin]
                ) VALUES ( 
                    /* CustomerID - int */ @CustomerID,
                    /* UserName - varchar(25) */ @UserName,
                    /* Password - binary(16) */ @Password,
                    /* LastLogin - datetime */ NULL ) 
            END
            ELSE
            BEGIN
                UPDATE  [tblOnline_CustomerAccount]
                SET     UserName = @UserName,
                        Password = @Password
                WHERE   CustomerID = @CustomerID    
            END
    
        END
    
  7. ==============================

    7.당신은 달성하기 위해 병합 기능을 사용할 수 있습니다. 그렇지 않으면 당신은 할 수 있습니다 :

    당신은 달성하기 위해 병합 기능을 사용할 수 있습니다. 그렇지 않으면 당신은 할 수 있습니다 :

    declare @rowCount int
    
    select @rowCount=@@RowCount
    
    if @rowCount=0
    begin
    --insert....
    
  8. ==============================

    8.전체 솔루션 (커서 구조를 포함) 이하입니다. 에 대한 카시우스 Porcus에 많은 감사 ... 트랜스 시작 위의 게시물에서 코드를 커밋합니다.

    전체 솔루션 (커서 구조를 포함) 이하입니다. 에 대한 카시우스 Porcus에 많은 감사 ... 트랜스 시작 위의 게시물에서 코드를 커밋합니다.

    declare @mystat6 bigint
    declare @mystat6p varchar(50)
    declare @mystat6b bigint
    
    DECLARE mycur1 CURSOR for
    
     select result1,picture,bittot from  all_Tempnogos2results11
    
     OPEN mycur1
    
     FETCH NEXT FROM mycur1 INTO @mystat6, @mystat6p , @mystat6b
    
     WHILE @@Fetch_Status = 0
     BEGIN
    
     begin tran /* default read committed isolation level is fine */
    
     if not exists (select * from all_Tempnogos2results11_uniq with (updlock, rowlock, holdlock)
                         where all_Tempnogos2results11_uniq.result1 = @mystat6 
                            and all_Tempnogos2results11_uniq.bittot = @mystat6b )
         insert all_Tempnogos2results11_uniq values (@mystat6 , @mystat6p , @mystat6b)
    
     --else
     --  /* update */
    
     commit /* locks are released here */
    
     FETCH NEXT FROM mycur1 INTO @mystat6 , @mystat6p , @mystat6b
    
     END
    
     CLOSE mycur1
    
     DEALLOCATE mycur1
     go
    
  9. ==============================

    9.

    INSERT INTO [DatabaseName1].dbo.[TableName1] SELECT * FROM [DatabaseName2].dbo.[TableName2]
     WHERE [YourPK] not in (select [YourPK] from [DatabaseName1].dbo.[TableName1])
    
  10. ==============================

    10.이 문제에 대한 가장 좋은 방법은 먼저 데이터베이스 컬럼 UNIQUE를하고있다

    이 문제에 대한 가장 좋은 방법은 먼저 데이터베이스 컬럼 UNIQUE를하고있다

    ALTER table_name 테이블의 ADD UNIQUE KEY

    THEN INSERT가 중복 키를 초래하는 경우 값이 삽입되지 않습니다 INTO를 TABLE_NAME 무시 / 테이블에 이미 존재한다.

  11. ==============================

    11.

    INSERT INTO table ( column1, column2, column3 )
    SELECT $column1, $column2, $column3
    EXCEPT SELECT column1, column2, column3
    FROM table
    
  12. from https://stackoverflow.com/questions/639854/check-if-a-row-exists-otherwise-insert by cc-by-sa and MIT license