如何批量将数据插入两个SQL表

时间:2015-02-09 17:48:11

标签: sql database sql-server-2008

我有一个任务是读取一个大文件并将包含的数据插入到SQL数据库中。在"真实"任务,几个表中有10列,但为了便于讨论,我将使用更简单的模式。

数据如下所示: FName,LName,Address。

因此,我声明一个SQL类型BulkInsertData来保存这三个字段,以便它们可以作为表值参数传入。

以下是我的表格:

dbo.Person
---+-------+-------+----------+
Id | Fname | Lname | AddressId|
---+-------+-------+----------+
 1 | Bob   | Smith |      42  |
 2 | Sue   | Baker |     234  |
---+-------+-------+----------+

dbo.Address
----+----------------------+
 Id | Address              |
----+----------------------+
 42 | 1600 Pennsylvania Ave|
234 | 10 Downing St        |
----+----------------------+

我的目标是在dbo.Person表中插入名字和姓氏,在dbo.Address表中插入地址,以及正确的外键。将数据插入多个表格很简单,但我仍然坚持使用外键关系。

如果我只插入一条记录,我可能会将地址插入dbo.Address表中,然后使用SELECT @@IDENTITY获取要插入dbo.Person的新地址的ID以及名字和姓氏。

这里,Does SQL Server have something like @@IDENTITY that returns multiple values?,另一个Stacker向我解释说INSERT语句与OUTPUT语句一起使用来保存有关多个插入行的信息。

我认为我想做的就是拥有一个临时表,不仅可以保存传入的数据,还可以保存与每个人相关的主键和外键:一个可以保存Fname,Lname的表, Address,PersonId和AddressId。

但是,据我所知,我可以使用OUTPUT关键字在临时表中创建新行,但我不知道如何使用它来修改现有行。

我觉得这个任务应该不难,所以我该怎么做?

我的SQL服务器是MS SQL Server 2008。

如果我采用以下数据......

Adam, Dumas, 300 Broadway
Greg, Ho, 213 Main St

并将其大量插入上述表格中,结果如下:

dbo.Person
---+-------+-------+----------+
Id | Fname | Lname | AddressId|
---+-------+-------+----------+
 1 | Bob   | Smith |      42  |
 2 | Sue   | Baker |     234  |
 3 | Adam  | Dumas |     501  |
 4 | Greg  | Ho    |     502  |
---+-------+-------+----------+

dbo.Address
----+----------------------+
 Id | Address              |
----+----------------------+
 42 | 1600 Pennsylvania Ave|
234 | 10 Downing St        |
501 | 300 Broadway         |
502 | 213 Main St          |
----+----------------------+

1 个答案:

答案 0 :(得分:5)

CREATE TABLE TVP_ADDRESS
(
 ID INT IDENTITY(1,1) PRIMARY KEY,ADDRESS VARCHAR(100)
)

CREATE TABLE TVP_PERSON
(
 ID INT IDENTITY(1,1) PRIMARY KEY,FNAME VARCHAR(100),LNAME VARCHAR(100),ADDRESS_ID INT,CONSTRAINT fk_address_id_tvp_address FOREIGN KEY(address_id) REFERENCES tvp_address(id) ON DELETE CASCADE
)

CREATE TYPE TVPDATA
AS 
TABLE
(
 FNAME VARCHAR(100),LNAME VARCHAR(100),ADDRESS VARCHAR(100)
)
GO
CREATE PROCEDURE inser_tvpdata
(
 @TVP  TVPDATA READONLY
)
AS 
BEGIN
    DECLARE @T TABLE(ID INT,ADDRESS VARCHAR(100))

--first insert address get ids

    INSERT INTO TVP_ADDRESS(address) OUTPUT Inserted.* INTO @T
    SELECT DISTINCT
     t.address
    FROM @TVP t --LEFT OUTER JOIN TVP_address td ON t.address = td.address
    --WHERE td.address IS NULL 
    -- insert persons and get new ids 

    INSERT INTO tvp_person(Fname,lname,address_id)
    SELECT t.fname,t.lname,temp.id
    FROM @TVP t
    INNER JOIN @T temp ON temp.ADDRESS=t.address
END
GO
DECLARE @t  TVPDATA

INSERT INTO @t(fname,lname,address) VALUES ('john','r','test'),('steve','r','test2')

EXEC inser_tvpdata @t

SELECT *
FROM TVP_ADDRESS

SELECT *
FROM TVP_PERSON