簡體   English   中英

僅當表中尚不存在記錄時才插入記錄

[英]Insert record only if record does not already exist in table

我想知道是否有辦法只在表中沒有包含該記錄的情況下將記錄插入表中?

是否有查詢會執行此操作,還是需要存儲過程?

你沒有說什么版本的SQL Server。 如果SQL Server 2008可以使用MERGE

注意:通常使用Merge作為Upsert,這是我最初認為的問題,但它沒有WHEN MATCHED子句並且只是WHEN NOT MATCHED子句有效,所以也適用於這種情況。 示例用法。

CREATE TABLE #A(
 [id] [int] NOT NULL PRIMARY KEY CLUSTERED,
 [C] [varchar](200) NOT NULL)


    MERGE #A AS target
    USING (SELECT 3, 'C') AS source (id, C)
    ON (target.id = source.id)
    /*Uncomment for Upsert Semantics
       WHEN MATCHED THEN 
        UPDATE SET C = source.C */
    WHEN NOT MATCHED THEN    
        INSERT (id, C)
        VALUES (source.id, source.C);

就執行成本而言,當要完成插入時,兩者看起來大致相等......

鏈接到第一次運行的計划圖像

但是在第二次運行時,沒有插件可以完成馬修的答案看起來成本更低。 我不確定是否有辦法改善這一點。

鏈接到計划第二次運行的圖像

測試腳本

select * 
into #testtable
from master.dbo.spt_values

CREATE UNIQUE CLUSTERED INDEX [ix] ON #testtable([type] ASC,[number] ASC,[name] ASC)


declare @name nvarchar(35)= 'zzz'
declare @number int = 50
declare @type nchar(3) = 'A'
declare @low int
declare @high int
declare @status int = 0;



MERGE #testtable AS target
USING (SELECT @name, @number, @type, @low, @high, @status) AS source (name, number, [type], low, high, [status])
ON (target.[type] = source.[type] AND target.[number] = source.[number] and target.[name] = source.[name] )
WHEN NOT MATCHED THEN    
INSERT (name, number, [type], low, high, [status])
VALUES (source.name, source.number, source.[type], source.low, source.high, source.[status]);

set @name = 'yyy'

IF NOT EXISTS 
    (SELECT *
    FROM #testtable
    WHERE [type] = @type AND [number] = @number and name = @name)
    BEGIN
INSERT INTO #testtable
(name, number, [type], low, high, [status])
VALUES (@name, @number, @type, @low, @high, @status);
END
IF NOT EXISTS 
    (SELECT {Columns} 
    FROM {Table} 
    WHERE {Column1 = SomeValue AND Column2 = SomeOtherVale AND ...}) 
INSERT INTO {Table} {Values}

簡而言之,您需要一個保證為您提供返回一行的表:

Insert dbo.Table (Col1, Col2, Col3....
Select 'Value1', 'Value2', 'Value3',....
From Information_Schema.Tables
Where Table_Schema = 'dbo'
    And Table_Name = 'Table'
    And Not Exists  (
                    Select 1
                    From dbo.Table
                    Where Col1 = 'Foo'
                        And Col2 = 'Bar'
                        And ....
                    )

我也看到了野外的這種變化:

Insert Table (Col1, Col2, Col3....
Select 'Value1', 'Value2', 'Value3'....
From    (
        Select 1 As Num
        ) As Z
Where Not Exists    (
                    Select 1
                    From Table
                    Where Col1 = Foo
                        And Col2 = Bar
                        And ....
                    ) 

我必須投票支持添加CONSTRAINT 這是最簡單,最強大的答案。 我的意思是,看看其他答案有多復雜,我會說他們更難做到(並保持正確)。

缺點:[1]通過閱讀代碼並不明顯,在DB [2]中強制執行唯一性客戶端代碼必須知道捕獲異常。 換句話說,那個追隨你的人可能會想知道“這是怎么回事?”

除此之外:我曾擔心拋出/捕獲異常是一個性能損失,但我做了一些測試(在SQL Server 2005上)並且它並不重要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM