8

在 SQL 数据库中

我有一个表用户

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

其中 AddressId 是表名称 Addresses 的外键

地址表:

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

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

我有一个名为 NEWUsers 的新表

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

它只有 Id 和 Name。

我想做的是:

编写一个脚本,将 NEWUSers 表中的所有记录插入到用户表中。

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

我怎样才能做到这一点?

我尝试了以下方法:

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

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

非常感谢您的帮助

4

5 回答 5

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。一旦 users 表被填充并正确链接,您可以将 country 设置回默认值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

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

于 2012-05-24T16:20:43.950 回答
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;
于 2012-05-24T16:33:17.007 回答
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
于 2012-05-24T18:10:33.820 回答
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

于 2012-05-24T16:21:28.133 回答
0

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

于 2012-05-24T18:32:22.393 回答