2013-03-07 31 views
22

Tôi có một thủ tục được lưu trữ cần chèn vào ba bảng khác nhau, nhưng tôi cần lấy ID được tạo từ đầu vào và sử dụng để chèn vào bảng tiếp theo. Tôi quen thuộc với cấu trúc INSERT-OUTPUT, nhưng tôi không chắc chắn về cách sử dụng nó trong trường hợp cụ thể này.INSERT-OUTPUT bao gồm cột từ bảng khác

DECLARE @guids TABLE ([GUID] UNIQUEIDENTIFIER); 
DECLARE @contacts TABLE ([ContactID] INT, [GUID] UNIQUEIDENTIFIER); 
DECLARE @mappings TABLE ([TargetID] INT, [GUID] UNIQUEIDENTIFIER); 

INSERT @guids ([GUID]) ... 

INSERT [Contacts] ([FirstName], [LastName], [ModifiedDate]) 
OUTPUT [inserted].[ContactID], g.[GUID] 
INTO @contacts 
SELECT [First_Name], [Last_Name], GETDATE() 
FROM [SourceTable] s 
JOIN @guids g ON s.[GUID] = g.[GUID] 

INSERT [TargetTable] ([ContactID], [License], [CreatedDate], [ModifiedDate]) 
OUTPUT [inserted].[TargetID], c.[GUID] 
INTO @mappings 
SELECT c.[ContactID], [License], [CreatedDate], [CreatedDate] 
FROM [SourceTable] s 
JOIN @contacts c ON s.[GUID] = c.[GUID] 

INSERT [Mappings] ([TargetID], [SourceGUID]) 
SELECT [TargetID], [GUID] 
FROM @mappings 

Nhưng tôi nhận được các lỗi sau đây:

Từ định đa phần "g.GUID" có thể không bị ràng buộc.

Mã định danh nhiều phần "c.GUID" không thể bị ràng buộc.

Tôi sẽ gặp lỗi tương tự nếu tôi sử dụng s.GUID thay thế. Có thể thực hiện một loại tham gia trong mệnh đề OUTPUT không?

+1

Bạn đang gặp lỗi bởi vì bạn không thể sử dụng bất cứ điều gì khác hơn là chèn hoặc DELETED tài liệu tham khảo về chèn (có nghĩa là bạn chỉ có thể sử dụng INSERTED, tất nhiên). Với các bản cập nhật và xóa, bạn có thể tham khảo các bảng khác được sử dụng trong truy vấn của bạn. Tùy chọn hợp nhất bên dưới sẽ hoạt động miễn là bạn đang sử dụng SQL Server 2008 trở lên. Cách duy nhất tôi đã tìm thấy để làm điều đó bằng cách khác là tìm một cột không sử dụng trên bảng tôi chèn vào và đặt giá trị (trong trường hợp của bạn, guid) vào cột đó, sau đó quay trở lại và kéo ra khỏi cột sau (và cập nhật nó trở lại null để nó không ở lại đó). –

+0

thử tính năng chèn này.GUID – user123456

Trả lời

30

Tôi không chắc chắn nếu đó là lựa chọn tốt nhất, nhưng có vẻ như bạn có thể làm các trick sử dụng MERGE:

MERGE [Contacts] trgt 
USING 
( 
    SELECT [First_Name], [Last_Name], g.[GUID] as [GUID] 
    FROM [SourceTable] s 
    JOIN @guids g ON s.[GUID] = g.[GUID] 
)src ON (1=0) 
WHEN NOT MATCHED THEN INSERT ([FirstName], [LastName], [ModifiedDate]) 
VALUES (src.[First_Name],src.[Last_Name], GETDATE()) 
OUTPUT [inserted].[ContactID], src.[GUID] 
INTO @contacts 
+0

Hãy tha thứ cho sự thiếu hiểu biết của tôi. Tôi chưa bao giờ sử dụng 'MERGE' hoặc thậm chí thấy nó được sử dụng trong tự nhiên. Bạn có thể giải thích mã này một chút không? –

+4

[Dr. OUTPUT hoặc: Cách tôi đã học để dừng lo lắng và yêu mến MERGE] (http://sqlblog.com/blogs/adam_machanic/archive/2009/08/24/dr-output-or-how-i-learned-to-stop -worrying-and-love-the-merge.aspx) –

+4

Đó là một bài viết tuyệt vời. Nhưng, câu trả lời ngắn cho câu hỏi của bạn là MERGE cho phép một kết hợp bất kỳ sự kết hợp nào của INSERT, UPDATE và DELETE trong một câu lệnh đơn (mã này buộc một INSERT). MERGE rất hữu ích cho bạn ở đây vì nó cho phép sử dụng các cột từ các bảng khác nhau trong mệnh đề OUTPUT, trong khi INSERT thì không. – GilM

Các vấn đề liên quan