如何从表变量插入带有标识列的表,同时更新表变量上的标识?

时间:2011-01-27 21:07:12

标签: sql sql-server-2008

我正在编写一个SQL脚本来为我们的数据库生成测试数据。我正在表变量中生成数据(所以我可以稍后跟踪它),然后将其插入到真实的表中。问题是,我需要跟踪我添加到父表中的哪些行,以便稍后我可以在脚本中生成其子数据。例如:

CREATE TABLE Customer (
    CustomerId INT IDENTITY,
    Name       VARCHAR(50)
)

CREATE TABLE Order (
    OrderId    INT IDENTITY,
    CustomerId INT,
    Product    VARCHAR(50)
)

因此,在我的脚本中,我创建了等效的表变量:

DECLARE @Customer TABLE (
    CustomerId INT IDENTITY,
    Name       VARCHAR(50)
) -- populate customers

DECLARE @Order TABLE (
    OrderId    INT IDENTITY,
    CustomerId INT,
    Product    VARCHAR(50)
) -- populate orders

我生成并将样本数据插入到每个表变量中。

现在,当我将来自我的表变量的客户插入到真实表中时,表变量中的CustomerId列将变得毫无意义,因为真实表具有其{{1}的自己的标识种子}专栏。

有没有办法可以跟踪插入到真实表中的每一行的新标识,在我的表变量中,所以我可以使用适当的CustomerId作为订单记录?或者,我有更好的方法来解决这个问题吗?

(注意:我最初使用的应用程序来生成测试数据,但在插入过程中运行得太慢,因为需要生成> 1,000,000条记录。)

4 个答案:

答案 0 :(得分:2)

您为什么需要表变量的标识值?如果只使用int,则在插入完成后可以使用is。使用output子句抓取它们。你可能需要一个输入值和一个输出值表来变量,这样就可以了:

DECLARE @CustomerInputs TABLE (Name VARCHAR(50) ) 
DECLARE @CustomerOutputs TABLE (CustomerId INT ,Name VARCHAR(50) ) 

INSERT INTO CUSTOMERS (name)
    OUTPUT inserted.Customerid, inserted.Name  INTO  @CustomerOutputs
SELECT Name FROM @CustomerInputs

SELECT * from @CustomerOutputs 

答案 1 :(得分:0)

您可以使用游标将数据插入表中,并使用内置函数SCOPE_IDENTITY()获取当前作用域中插入的最后一个ID(通过脚本)。

有关SCOPE_IDENTITY的详细信息,请参阅this MSDN article

答案 2 :(得分:0)

这是一种做法。如果你可以使用它取决于你的情况。当用户使用您的数据库时,您不应该在生产环境中执行此操作。

-- Get the next identity values for Customer and Order
declare @NextCustomerID int
declare @NextOrderID int
set @NextCustomerID = IDENT_CURRENT('Customer')+1
set @NextOrderID = IDENT_CURRENT('Order')+1

-- Create tmp tables
create table #Customer (CustomerID int identity, Name varchar(50))
create table #Order (OrderID int identity, CustomerID int, Product varchar(50))

-- Reseed the identity columns in temp tables
dbcc checkident(#Customer, reseed, @NextCustomerID) 
dbcc checkident(#Order, reseed, @NextOrderID) 

-- Populate #Customer
-- Populate #Order

-- Allow insert to identity column on Customer
set identity_insert Customer on

-- Add rows to Customer
insert into Customer(CustomerId, Name)
select CustomerID, Name
from #Customer

-- Restore identity functionality on Customer
set identity_insert Customer off

-- Add rows to Order
set identity_insert [Order] on
insert into [Order](OrderID, CustomerID, Product)
select OrderID, CustomerID, Product
from #Order
set identity_insert [Order] off

-- Drop temp tables
drop table #Customer
drop table #Order

-- Check result
select * from [Order]
select * from Customer

答案 3 :(得分:-1)

我这样做的方式是首先从您的客户表中获取MAX(CustomerId)。然后我将摆脱变量表上的IDENTITY列,并使用ROW_NUMBER()和MaxCustomerId执行我自己的CustomerId。它应该是这样的:

DECLARE @MaxCustomerId INT

SELECT @MaxCustomerId = ISNULL(MAX(CustomerId),0)
FROM Customer

DECLARE @Customer TABLE (
    CustomerId INT,
    Name       VARCHAR(50)
)

INSERT INTO @Customer(CustomerId, Name)
SELECT @MaxCustomerId + ROW_NUMBER() OVER(ORDER BY SomeColumn), Name
FROM YourDataTable

或者在临时表中插入值,这样您就可以使用相同的ID来填充Order表。