简体   繁体   中英

How do I insert from a table variable to a table with an identity column, while updating the the identity on the table variable?

I'm writing a SQL script to generate test data for our database. I'm generating the data in table variables (so I can track it later) and then inserting it into the real tables. The problem is, I need to track which rows I've added to the parent table, so that I can generate its child data later on in the script. For example:

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

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

So, in my script, I create equivalent table variables:

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

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

And I generate and insert sample data into each table variable.

Now, when I go to insert customers from my table variable into the real table, the CustomerId column in the table variable will become meaningless, as the real table has its own identity seed for its CustomerId column.

Is there a way I can track the new identity of each row inserted into the real table, in my table variable, so I can use a proper CustomerId for the order records? Or, is there a better way I should be going about this?

(Note: I originally started with an application to generate the test data, but it ran too slow during insert as > 1,000,000 records need to be generated.)

WHy do you need identity values on the table variables? If you use just int, you can isnert the ids after the insert is done. Grab them using the output clause. YOu might need an input values and an output values table varaiable to get this just right like this:

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 

You can insert the data to the table with a cursor and use the built-in function SCOPE_IDENTITY() to get the last id which was inserted in the current scope (by your script).

See this MSDN article for more information on SCOPE_IDENTITY .

Here is one way of doing it. If you can use it depends on your situation. You should not do it in production environment when users use your db.

-- 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

The way I'd do it its first obtain the MAX(CustomerId) from your Customer Table. Then I'd get rid of the IDENTITY column on your variable table and do my own CustomerId using ROW_NUMBER() and the MaxCustomerId. It should be something like this:

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

Or insert the values on a temp table, so you can use the same ids to fill your Order table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM