Tôi tự hỏi nếu có cách chèn bản ghi vào bảng chỉ khi bảng không chứa bản ghi đó?Chỉ chèn bản ghi nếu bản ghi chưa tồn tại trong bảng
Có truy vấn nào sẽ thực hiện việc này hay tôi sẽ cần một thủ tục được lưu trữ?
Tôi tự hỏi nếu có cách chèn bản ghi vào bảng chỉ khi bảng không chứa bản ghi đó?Chỉ chèn bản ghi nếu bản ghi chưa tồn tại trong bảng
Có truy vấn nào sẽ thực hiện việc này hay tôi sẽ cần một thủ tục được lưu trữ?
Bạn không nói phiên bản SQL Server nào. Nếu SQL Server 2008 bạn có thể sử dụng MERGE
NB: Thông thường, hãy sử dụng Kết hợp cho Upsert, đó là điều tôi cho là câu hỏi ban đầu nhưng nó hợp lệ mà không có mệnh đề WHEN MATCHED
và chỉ với mệnh đề WHEN NOT MATCHED
. cho trường hợp này cũng vậy. Sử dụng ví dụ.
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);
Xét về thực hiện chi phí hai trông tương đương khi Insert là việc phải làm ...
Link to plan images for first run
nhưng trên đường chạy trốn thứ hai khi không có chèn phải làm Matthêu câu trả lời có vẻ thấp hơn chi phí. Tôi không chắc liệu có cách cải thiện điều này không.
Link to plan images for second run
Script Test
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
Tôi thực sự không chắc chắn mình đang sử dụng phiên bản nào. Hợp nhất sẽ hoạt động như thế nào? –
@Mega - Tôi đã cập nhật câu trả lời của mình với ví dụ về cách 'MERGE' có thể được sử dụng cho trường hợp này. Tôi sẽ kiểm tra số liệu thống kê thực hiện để xem liệu có bất kỳ sự khác biệt nào giữa 2 cách tiếp cận hay không. –
Vấn đề là chính xác, không phải hiệu suất. 'IF NOT EXISTS (SELECT ...) INSERT' sẽ gây ra lỗi trùng lặp dưới tải, được bảo đảm. –
IF NOT EXISTS
(SELECT {Columns}
FROM {Table}
WHERE {Column1 = SomeValue AND Column2 = SomeOtherVale AND ...})
INSERT INTO {Table} {Values}
-1 vì đây là cách ** ** sureshot bị lỗi trùng lặp khi tải cao. SELECT và INSERT chạy vào các thời điểm khác nhau và không có gì để ngăn chặn hai luồng đồng thời cố gắng chèn cùng một giá trị. MERGE, như được đăng bởi Martin, là một giải pháp thích hợp –
Tóm lại, bạn cần một bảng đảm bảo để cung cấp cho bạn khả năng quay trở lại một dòng:
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 ....
)
Tôi đã nhìn thấy sự thay đổi này trong tự nhiên:
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 ....
)
Tôi phải bỏ phiếu để thêm CONSTRAINT
. Đó là câu trả lời đơn giản và mạnh mẽ nhất. Ý tôi là, nhìn vào những câu trả lời khác phức tạp như thế nào, tôi muốn nói rằng họ sẽ khó hơn nhiều để có được quyền (và giữ đúng).
Những nhược điểm: [1] không rõ ràng khi đọc mã mà tính duy nhất được thực thi trong DB [2] mã máy khách phải biết để bắt ngoại lệ. Nói cách khác, anh chàng đến sau khi bạn có thể tự hỏi "làm thế nào điều này đã bao giờ làm việc?"
Điều đó sang một bên: Tôi đã từng lo lắng rằng việc ném/bắt ngoại lệ là hiệu suất nhưng tôi đã thực hiện một số thử nghiệm (trên SQL Server 2005) và không đáng kể.
Bạn có cân nhắc thêm ràng buộc duy nhất không? – bmm6o