SQL:从包含外键的表中的另一个表中插入数据

时间:2012-05-24 16:14:11

标签: sql database sql-server-2008 insert

在SQL DATABASE

我有一个表用户

 Id   Name   Age    AddressId
----+------+------+-----------

其中AddressId是表名地址的外键

地址表:

 Id   Country   State  City   ZipCode
----+---------+------+------+---------

这是一对一的关系:每个用户有1个地址,每个地址都有一个用户

我有一个名为NEWUsers的新表

Id   Name  
----+------

它只有Id和Name。

我想做的是:

编写脚本以将所有记录从NEWUSers表插入用户表。

  • 我希望所有新用户的年龄为默认值
  • 对于插入的每个新用户,我需要为他创建一个新的地址记录
  • 新地址记录的所有值(国家,城市,州,邮政编码)等于“abcd”,但用于为新用户设置外键AddressId的Id除外)

我该怎么做?

我尝试了以下内容:

INSERT INTO Users(Name, Age)
Values((SELECT Name FROM NewUsers),20)

但我不知道如何为每个插入的用户创建一个新的地址记录,并相应地指定外键。

非常感谢您的帮助

5 个答案:

答案 0 :(得分:6)

一种方法是使用两个查询,形成如下:

INSERT INTO Addresses (Country, State, City, ZipCode)
SELECT 'abcd', 'abcd', 'abcd', 'abcd' FROM NewUsers

INSERT INTO Users (Name, Age, AddressId)
SELECT Name, 20, ?? FROM NewUsers

修改:将用户链接到地址的一种简单方法是临时将国家/地区设置为用户名。然后你会有一个确定addressId的链接。填充并正确链接用户表后,您可以将国家/地区设置回默认值abcd

insert addresses (country, state, city, zipcode)
select name, 'abcd', 'abcd', 'abcd' from newusers;

insert users (name, age, addressid)
select u.name, 20, a.id from newusers u
join addresses a on a.country = u.name;

update a
set a.country = 'abcd'
from addresses a join newusers u on a.country = u.name;

演示:http://www.sqlfiddle.com/#!3/1f09b/8

如果您想要保证事务一致性,如果多个插入可以同时发生,或者如果您想允许重复的名称等,有更复杂的方法可以做到这一点。但是根据您给出的示例和目前为止的详细信息,这种方法应该有效。

答案 1 :(得分:2)

这有点hacky,但在两个语句中做了你想要的 - 假设没有用户将拥有名称'abcd'或为他们的国家输入,并且在此操作之后清除NewUsers表:

INSERT dbo.Addresses(Country, State, City, ZipCode)
OUTPUT inserted.Country, 20, inserted.id
INTO dbo.Users
SELECT Name, 'abcd', 'abcd', 'abcd'
FROM dbo.NewUsers;

UPDATE a SET Country = 'abcd'
FROM dbo.Addresses AS a
INNER JOIN dbo.NewUsers AS nu
ON a.Country = nu.Name;

答案 2 :(得分:2)

您必须使用外键在用户和地址表中插入光标

DECLARE @AddressID INT,
        @ID INT,
        @Name NVARCHAR(50)

DECLARE UserCursor CURSOR FOR
SELECT ID, NAME
FROM NewUsers
OPEN UserCursor

FETCH NEXT FROM UserCursor INTO @ID, @Name
WHILE @@FETCH_STATUS =0 BEGIN
    INSERT INTO Addresses(Country, State, City, ZipCode)
    VALUES ('abcd', 'abcd', 'abcd', 'abcd')

    SET @AddressID = SCOPE_IDENTITY()

    INSERT INTO Users(Name, Age, AddressID)
    VALUES (@Name, 20, @AddressID)
    FETCH NEXT FROM UserCursor INTO @ID, @Name
END
CLOSE UserCursor
DEALLOCATE UserCursor

答案 3 :(得分:0)

假设你可以设置AddressId但是你想要......

INSERT Addresses
(
    Id,
    Country,
    State,
    City,
    ZipCode
)
SELECT
    Id,
    'abcd',
    'abcd',
    'abcd',
    'abcd'
FROM NEWUsers

INSERT Users
(
    Id,
    Name,
    Age,
    AddressId
)
SELECT
    Id,
    Name,
    20,
    Id
FROM NEWUsers

如果AddressId是标识列,则可以先暂时禁用标识。有关信息和示例,请参阅SET IDENTITY_INSERT

答案 4 :(得分:0)

老实说,答案是你不想做你想做的事。如果用户只有一个地址,如您所述,那么您应该只有一个包含地址字段的表(用户)。正确建模数据会使这个问题本质上消失。