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 i开发者_Go百科nserted 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.
精彩评论