2013-08-26 68 views
0

我想在父/子關係中插入一些行。我知道如何在.NET中做到這一點,但不能退出T-SQL。多表插入與合併?

這將是基本查詢我會用它來查找信息,我會被插入:

SELECT * FROM parentTable p 
INNER JOIN childTable c 
    ON p.ID = c.ParentTableID 
WHERE p.PlanID = 123456 

需要採取什麼是我第一次插入ParentTable行這真的只是一個副本匹配的行,但具有新的PlanID和創建日期。然後,我從插入的行中獲取該ParentTable ID,並將其用於相同的過程,但用於子表。

因此,我需要在.Net中說至少是我循環所有父表匹配的位置,併爲每個匹配創建一個childTable行。

我試圖使用MERGE和OUTPUT子句,但它似乎我可能使用一個圓形孔的方形釘。使用某種CURSOR會更好嗎?


所以這就是我迄今爲止基於下面的答案。不幸的是,它並沒有抓住SCOPE_IDENTITY() ...有沒有一個竅門呢?因爲這是返回NULL,我得到插入FK錯誤。

USE MemberCenteredPlan 

DECLARE @NewPlanID BIGINT;--49727690 
DECLARE @OldPlanID BIGINT;--49725211 
DECLARE @NewSWReAssID BIGINT; 

SET @NewPlanID = 49727690 
SET @OldPlanID = 49725211 

BEGIN 
INSERT INTO tblSocialWorkerReAssessment 
SELECT 
    @NewPlanID 
    ,[Discussed] 
    ,Discussion 
    ,NULL 
    ,NULL 
    ,NULL 
    ,CreatedBy 
    ,GETDATE() 
    ,NULL 
    ,NULL 
    FROM tblSocialWorkerReAssessment 
    WHERE PlanID = @OldPlanID 

SELECT @NewSWReAssID = SCOPE_IDENTITY(); 

INSERT INTO tblPlanDomain 
SELECT 
    @NewPlanID 
    ,[DomainTypeID] 
    ,[MemberOutcomes] 
    ,[MemberPreferences] 
    ,[DomainDate] 
    ,[Steps] 
    ,[ClinicalFunctionalConcerns] 
    ,[ReportWageES] 
    ,[ReportWageSSA] 
    ,@NewSWReAssID 
    ,[CreatedBy] 
    ,GETDATE() 
    ,NULL 
    ,NULL 
    ,NEWID() 
FROM tblPlanDomain 
WHERE planID = @OldPlanID 

END 

回答

2

你不需要MERGE,你肯定不需要遊標。並且INSERT(或MERGE)一次只能影響一個表,因此無論如何您都需要執行多個語句。如果您需要引用多個新計劃

DECLARE @NewPlanID INT; 

INSERT dbo.ParentTable(cols...) 
    SELECT cols... 
    FROM dbo.ParentTable WHERE PlanID = 123456; 

SELECT @NewPlanID = SCOPE_IDENTITY(); 

INSERT dbo.ChildTable(ParentTableID, cols...) 
    SELECT @NewPlanID, cols... 
    FROM dbo.ChildTable WHERE PlanID = 123456; 

,它變得有點複雜,在這種情況下,你需要使用:如果你只曾經與一個計劃處理的時間,你可以這樣做MERGE(目前,INSERT的可組合DML在光線方面略顯不足 - 您不能參考OUTPUT子句中的源表)。

DECLARE @p TABLE(OldPlanID INT, NewPlanID INT); 

MERGE dbo.ParentTable WITH (HOLDLOCK) 
USING 
(
    SELECT ID, cols... FROM dbo.ParentTable 
    WHERE ID IN (123456, 234567) 
) AS src ON src.ID IS NULL 
WHEN NOT MATCHED THEN INSERT(cols...) 
VALUES(src.cols...) 
OUTPUT src.ID, inserted.ID INTO @p; 

INSERT dbo.ChildTable(ParentTableID, cols...) 
SELECT p.NewPlanID, t.cols... 
FROM dbo.ChildTable AS t 
INNER JOIN @p AS p 
ON t.ParentTableID = p.OldPlanID; 

但是,你應該對此非常謹慎......我在this answer over on dba.SE鏈接到幾個問題和未解決的錯誤與MERGE。我也posted a cautionary tip here

+0

嚴格地說,您可以使用可更新的分區視圖在一個語句中插入到多個表中......只是在這裏挑剔。 – usr

0

我認爲這是你以後。

Use Northwind 
GO 

SET NOCOUNT ON 


IF OBJECT_ID('tempdb..#OrderAuditHolder') IS NOT NULL 
begin 
     drop table #OrderAuditHolder 
end 


CREATE TABLE #OrderAuditHolder 
( 
    [OriginalOrderID] [int] NOT NULL, 
    [NewOrderID] [int] NOT NULL, 
    [CustomerID] [nchar](5) NULL, 
    [EmployeeID] [int] NULL, 
    [OrderDate] [datetime] NULL, 
    [RequiredDate] [datetime] NULL, 
    [ShippedDate] [datetime] NULL, 
    [ShipVia] [int] NULL, 
    [Freight] [money] NULL, 
    [ShipName] [nvarchar](40) NULL, 
    [ShipAddress] [nvarchar](60) NULL, 
    [ShipCity] [nvarchar](15) NULL, 
    [ShipRegion] [nvarchar](15) NULL, 
    [ShipPostalCode] [nvarchar](10) NULL, 
    [ShipCountry] [nvarchar](15) NULL, 
) 


declare @ExampleOrderID int 
select @ExampleOrderID = (select top 1 OrderID from dbo.Orders ords where exists (select null from dbo.[Order Details] innerOD where innerOD.OrderID = ords.OrderID)) 

print '/@ExampleOrderID/' 
print @ExampleOrderID 
print '' 


insert into dbo.Orders (CustomerID,EmployeeID,OrderDate,RequiredDate,ShippedDate,ShipVia,Freight,ShipName,ShipAddress,ShipCity,ShipRegion,ShipPostalCode,ShipCountry) 
output @ExampleOrderID , inserted.OrderID,inserted.CustomerID,inserted.EmployeeID,inserted.OrderDate,inserted.RequiredDate,inserted.ShippedDate,inserted.ShipVia,inserted.Freight,inserted.ShipName,inserted.ShipAddress,inserted.ShipCity,inserted.ShipRegion,inserted.ShipPostalCode,inserted.ShipCountry 
into #OrderAuditHolder 
Select 
CustomerID,EmployeeID,OrderDate,RequiredDate,ShippedDate,ShipVia,Freight,ShipName,ShipAddress,ShipCity,ShipRegion,ShipPostalCode,ShipCountry 
from dbo.Orders where OrderID = @ExampleOrderID 

print '/#OrderAuditHolder/' 
Select * from #OrderAuditHolder 
print '' 

Insert into dbo.[Order Details] (OrderID , ProductID , UnitPrice , Quantity , Discount) 
Select 
holder.NewOrderID , od.ProductID , od.UnitPrice , od.Quantity , od.Discount 
from #OrderAuditHolder holder 
join dbo.[Order Details] od on holder.OriginalOrderID = od.OrderID 
/* Note, the "join" is on the OriginalOrderID, but the inserted value is the NewOrderID */ 


/* below is not needed, but shows results */ 
declare @MaxOrderID int 
select @MaxOrderID = (select MAX(OrderID) from dbo.Orders ords where exists (select null from dbo.[Order Details] innerOD where innerOD.OrderID = ords.OrderID)) 
select * from dbo.[Order Details] where OrderID = @MaxOrderID order by OrderID desc 
/**/ 



IF OBJECT_ID('tempdb..#OrderAuditHolder') IS NOT NULL 
begin 
     drop table #OrderAuditHolder 
end 



SET NOCOUNT OFF