2014-02-06 56 views
0

我試圖從一個批量插入中獲取插入的每一行的ID,並使用我的臨時表#InsertedClients中的一個ID創建一個映射表。我爲初始插入使用相同的臨時表,但PDATClientID不是插入的一部分。我似乎無法弄清楚如何正確地做到這一點。當我使用SCOPE_IDENTITY插入Client_Mapping表時,它只會從第一個插入中獲取ID,並將其與所有PDATClientID一起放入。做了很多谷歌搜索後,我相信我應該使用OUTPUT,但似乎無法計算出如何將每條記錄的INSERTED.CLID與每個PDATClientID一起使用。我也應該說,我不能使用遊標太多的行。任何幫助是極大的讚賞!SQL SCOPE_IDENTITY或OUTPUT與來自另一個表的數據

  IF NOT EXISTS (
          SELECT ID 
          FROM sysobjects 
          WHERE id = object_id(N'[Client_Mapping]') 
           AND OBJECTPROPERTY(id, N'IsUserTable') = 1 
          ) 
         CREATE TABLE [Client_Mapping] (
          ClientMappingID INT Identity(1, 1) NOT NULL 
          ,PDATClientID INT NOT NULL 
          ,CLID INT NOT NULL 
          ,AUDITDATE DATETIME NOT NULL 
          ,CONSTRAINT [PK_Client_Mapping] PRIMARY KEY (ClientMappingID) 
          ) 

      -- Begin Inserts 

      SELECT 
       First_Name 
       ,Middle_Name 
       ,Last_Name 
       ,CONVERT(DATETIME, Date_Of_Birth) AS DOB 
       ,a.Address_Line as Address1 
       ,a.Address_Line_2 as Address2 
       ,a.Zip_Code as ZipCode -- ??? Do I need to account for zipcode + 4 
       ,REPLACE(REPLACE(REPLACE(cphp.Number_Or_Address, '(', ''), ')', '-'), ' ', '') AS HomePhone 
       ,REPLACE(REPLACE(REPLACE(cpcp.Number_Or_Address, '(', ''), ')', '-'), ' ', '') AS CellPhone 
       ,cpem.Number_Or_Address AS EMAIL 
       ,c.Client_ID as PDATClientID 
       ,c.Action AS [ClientAction] 
       ,ca.Action as [ClientAddressAction] 
       ,a.Action AS [AddressAction] 
       ,cphp.Action AS [HomePhoneAction] 
       ,cpcp.Action AS [CellPhoneAction] 
       ,cpem.Action AS [EmailAction] 

      INTO #InsertClients 

      FROM Client c 
      LEFT JOIN Client_Address ca ON ca.Client_ID = c.Client_ID 
      LEFT JOIN Address a ON a.Address_ID = ca.Address_ID 
      LEFT JOIN Client_Phone cphp ON cphp.Client_ID = c.Client_ID 
       AND cphp.Phone_Email_Type = 'HP' 
       AND cphp.Start_Date = (
        SELECT MAX(Start_Date) 
        FROM Client_Phone 
        WHERE Client_ID = c.Client_ID 
        ) 
      LEFT JOIN Client_Phone cpcp ON cpcp.Client_ID = c.Client_ID 
       AND cpcp.Phone_Email_Type = 'CP' 
       AND cpcp.Start_Date = (
        SELECT MAX(Start_Date) 
        FROM Client_Phone 
        WHERE Client_ID = c.Client_ID 
        ) 
      LEFT JOIN Client_Phone cpem ON cpem.Client_ID = c.Client_ID 
       AND cpem.Phone_Email_Type = 'EM' 
       AND cpem.Start_Date = (
        SELECT MAX(Start_Date) 
        FROM Client_Phone 
        WHERE Client_ID = c.Client_ID 
        ) 
      where c.action ='I' 


      BEGIN TRY 
        BEGIN TRAN 

        INSERT INTO [dbo].[Clients] (
         [FName] 
         ,[MiddleInitial] 
         ,[LName] 
         ,[DOB] 
         ,[Address1] 
         ,[Address2] 
         ,[ZipCode] 
         ,[HomePhone] 
         ,[CellPhone] 
         ,[Email] 
         ,[AuditStaffID] 
         ,[AuditDate] 
         ,[DateCreated] 
         ) 
         Select 
         First_Name 
         ,CASE when Middle_Name = '' THEN NULL ELSE Middle_Name END 
         ,Last_Name 
         ,DOB 
         ,Address1 
         ,Address2 
         ,ZipCode 
         ,HomePhone 
         ,CellPhone 
         ,EMail 
         ,496 AS [AuditStaffID] 
         ,CURRENT_TIMESTAMP AS [AuditDate] 
         ,CURRENT_TIMESTAMP AS [DateCreated] 
         FROM 
         #InsertClients 
         Where 
         [ClientAction] = 'I' 



         INSERT INTO [Client_Mapping] 
         (
         PDATClientID 
         ,CLID 
         ,AUDITDATE 
         ) 
         SELECT 
         PDATClientID 
         ,SCOPE_IDENTITY() 
         ,CURRENT_TIMESTAMP 
         FROM #InsertClients 


        COMMIT 

        END TRY 

        BEGIN CATCH 

         ROLLBACK 

        SELECT ERROR_NUMBER() AS ErrorNumber 
         ,ERROR_SEVERITY() AS ErrorSeverity 
         ,ERROR_STATE() AS ErrorState 
         ,ERROR_PROCEDURE() AS ErrorProcedure 
         ,ERROR_LINE() AS ErrorLine 
         ,ERROR_MESSAGE() AS ErrorMessage 

        END CATCH 
+0

這可能也有幫助:[使用merge..output獲取source.id和target.id之間的映射](http://stackoverflow.com/questions/5365629/using-merge-output- to-get-mapping-source-id-and-target-id) –

回答

0

通過使用此處找到的示例解決了問題:http://sqlserverplanet.com/tsql/match-identity-columns-after-insert。下面是該網站的示例。

  -- Drop temp tables if they already exist 
     IF OBJECT_ID('TempDB..#source', 'U') IS NOT NULL DROP TABLE #source; 
     IF OBJECT_ID('TempDB..#target', 'U') IS NOT NULL DROP TABLE #target; 
     IF OBJECT_ID('TempDB..#xref', 'U') IS NOT NULL DROP TABLE #xref; 
     GO 

     -- Create the temp tables 
     CREATE TABLE #source (id INT PRIMARY KEY IDENTITY(1, 1), DATA INT); 
     CREATE TABLE #target (id INT PRIMARY KEY IDENTITY(1, 1), DATA INT); 
     CREATE TABLE #xref (ROW INT PRIMARY KEY IDENTITY(1, 1), source_id INT, target_id INT); 
     GO 

     -- If xref table is being reused, make sure to clear data and reseed by truncating. 
     TRUNCATE TABLE #xref; 

     -- Fill source table with dummy data (even numbers) 
     INSERT INTO #source (DATA) 
     SELECT 2 UNION SELECT 4 UNION SELECT 6 UNION SELECT 8; 
     GO 

     -- Fill target table with dummy data (odd numbers) to simulate existing records 
     INSERT INTO #target (DATA) 
     SELECT 1 UNION SELECT 3 UNION SELECT 5; 
     GO 

     -- Insert source table data into target table. IMPORTANT: Inserted data must be sorted by the source table's primary key. 
     INSERT INTO #target (DATA) 
     OUTPUT INSERTED.id INTO #xref (target_id) 
     SELECT DATA 
     FROM #source 
     ORDER BY id ASC; 
     GO 

     -- Update the xref table with the PK of the source table. This technique is used for data not captured during the insert. 
     ;WITH src AS (SELECT id, ROW = ROW_NUMBER() OVER (ORDER BY id ASC) FROM #source) 
     UPDATE x 
     SET x.source_id = src.id 
     FROM #xref AS x 
      JOIN src ON src.ROW = x.ROW; 
     GO 

     -- Verify data 
     SELECT * FROM #source; 
     SELECT * FROM #target; 
     SELECT * FROM #xref; 
     GO 

     -- Clean-up 
     IF OBJECT_ID('TempDB..#source', 'U') IS NOT NULL DROP TABLE #source; 
     IF OBJECT_ID('TempDB..#target', 'U') IS NOT NULL DROP TABLE #target; 
     IF OBJECT_ID('TempDB..#xref', 'U') IS NOT NULL DROP TABLE #xref; 
     GO 
0

你在你的問題中有一個地獄的代碼我可以在幾行解釋你如何檢索所有插入的ID。

是SCOPE_IDENTITY()爲您提供由標識列生成的最後一個IDENTITY值。在你情況下,你需要使用表變量的插入過程中得到所有生成的標識值

/* Declare a table Vairable */ 

DECLARE @NewValues TABLE (IDs INT); 

/* In Your Insert Statement use OUTPUT clause */ 

INSERT INTO Table_Name (Column1,Column2,Column3,....) 
OUTPUT inserted.Identity_Column INTO @NewValues (IDs) 
SELECT Column1,Column2,Column3,.... 
FROM Table_Name2 

/* Finally Select values from your table variable */ 

SELECT * FROM @NewValues 

您的查詢

在你的情況你插入語句應該是這個樣子......

INSERT INTO [dbo].[Clients] (
[FName] 
,[MiddleInitial] 
,[LName] 
,[DOB] 
,[Address1] 
,[Address2] 
,[ZipCode] 
,[HomePhone] 
,[CellPhone] 
,[Email] 
,[AuditStaffID] 
,[AuditDate] 
,[DateCreated] 
) 
OUTPUT inserted.[FName], inserted.[MiddleInitial] ,.... INTO @TableVarible(First_Name,[MiddleInitial].....) 

Select 
First_Name 
,CASE when Middle_Name = '' THEN NULL ELSE Middle_Name END 
,Last_Name 
,DOB 
,Address1 
,Address2 
,ZipCode 
,HomePhone 
,CellPhone 
,EMail 
,496 AS [AuditStaffID] 
,CURRENT_TIMESTAMP AS [AuditDate] 
,CURRENT_TIMESTAMP AS [DateCreated] 
FROM 
#InsertClients 
Where 
[ClientAction] = 'I' 
+0

感謝您的回覆!對不起,我知道這是很多代碼。使用OUTPUT將所有新的ID放在變量表中,這很好,但我怎樣才能讓它們與原始的#inserted表中的PDATClientID聯合起來。 PDATClient與OUTPUT不是同一個插入的一部分,所以我沒有辦法將它選入變量或將它加入到該表中。我需要與同一個表中的OUTPUT INSERTED.ID在同一行中的PDATCLientID。讓我知道如果這沒有意義。 – Moose21

+1

@ user3176061 - 我用一篇名爲[MERGE AND OUTPUT - T-SQL的瑞士軍刀]的文章進行了類似的工作(http://sqlblog.com/blogs/jamie_thomson/archive/2010/01/06/merge -and-output-the-swiss-army-knife-of-t-sql.aspx)有關使用新插入的ID將FK引用更新到另一個表。非常適合基於集合的操作。 –

+0

嘿穆斯先生,謝謝抽空回答!不幸的是我正在使用運行SQL Server 2005的數據庫,並且2005年合併不起作用。但是我確實發現了這一點。 – Moose21

相關問題