SQL:垂直拆分table和create/populate键,外键关系
SQL: vertically split table and create/populate keys, foreign key relationship
我想垂直拆分现有的(已经填满数据)。
假设我的起始 table (trip
) 看起来像这样:
ID Person Age Trip_to Date
... Alice 21 Los Angeles 2015-04-01
... Bob 35 New York 2015-03-15
... Bob 35 Chicago 2015-03-20
... Bob 35 San Francisco 2015-03-29
... Carol 29 Miami 2015-03-30
... Carol 29 Boston 2015-04-05
我想将这个 table 分成两个 table,因为它应该是,每个 person
和 trip
。
将每个唯一的人复制到 table person
时,我想要自动创建的 uniqueidentifier
列 table person.pId
(主键) 复制到原始 table 中新创建的 uniqueidentifier
列 trip.personid
并将其转换为外键。 (然后我会从原来的 table 中删除 trip.person
和 trip.age
列,并按照我想要的方式组织数据。)
当我将人员行插入新的 table 时,我想我可以为此使用触发器,如下所示:
CREATE TRIGGER tr_person
on person
after INSERT
as
begin
UPDATE Trip
SET personId=(SELECT i.pId from inserted i)
WHERE person=(SELECT i.person from inserted i) and age=(SELECT i.age from inserted i)
END
但是,我明白了:
Subquery returned more than 1 value.
This is not permitted when the subquery follows =, !=, <, <= , >, >=
or when the subquery is used as an expression.
显然,触发器仅在执行了所有(可能是多个!)插入后才执行,到那时,我的 SET
语句不再允许查询插入。
我也考虑过在 INSERT
语句中使用 OUTPUT
子句,但这也行不通
Insert into person (Driver, Age)
OUTPUT inserted.pId INTO trip.personId WHERE trip.person=inserted.person AND trip.Age=inserted.Age
(Select DISTINCT Person, Age FROM Trip)
所以我现在想知道,这一切都错了吗?还有另一种方法可以自动创建两个新拆分的 table 之间的键和关系吗?
编辑想要的结果:
Table行程:
ID Trip_to Date PersonId
... Los Angeles 2015-04-01 xxxx1
... New York 2015-03-15 xxxx2
... Chicago 2015-03-20 xxxx2
... San Francisco 2015-03-29 xxxx2
... Miami 2015-03-30 xxxx3
... Boston 2015-04-05 xxxx3
Table人
pId Person Age
xxxx1 Alice 21
xxxx2 Bob 35
xxxx3 Carol 29
(ID字段当然应该都是uniqueidentifiers)
这是一个想法:
首先,您插入所有不同的 Person
从 Trip
table 到 Person
table:
CREATE TABLE Person(
pID UNIQUEIDENTIFIER PRIMARY KEY,
Person VARCHAR(10),
Age INT
)
INSERT INTO Person
SELECT
NEWID(), Person, Age
FROM(
SELECT DISTINCT Person, Age FROM Trip
)t
然后,向 Trip
table PersonId
添加一个新的 FK 列,它引用 Person
table 中的 pId
:
ALTER TABLE Trip
ADD PersonId UNIQUEIDENTIFIER
FOREIGN KEY(PersonId) REFERENCES Person(pId)
然后,UPDATE
使用 Person
和 Age
上的 JOIN
的值来自 Person
table 的新添加的 FK 列:
UPDATE t
SET PersonId = p.pID
FROM Trip t
INNER JOIN Person p
ON p.Person = t.Person
AND p.Age = t.Age
最后,您可以从 Trip
table:
中删除 Person
和 Age
ALTER TABLE Trip DROP COLUMN Person
ALTER TABLE Trip DROP COLUMN Age
结果
人
pID Person Age
------------------------------------ ---------- -----------
35815766-1634-45FF-A3F6-8194B43F3F65 Alice 21
8EB3A7CC-CED1-4DBC-98B0-99D325BC7F67 Bob 35
D0EDCEA8-3825-4693-9352-BF7A04AEFCB2 Carol 29
旅行
ID Trip_to Date PersonId
------------------------------------ -------------------- ---------- ------------------------------------
77357A57-FAAE-43DE-923E-219038B8641E Los Angeles 2015-04-01 35815766-1634-45FF-A3F6-8194B43F3F65
C1B64E81-D30A-46A9-A868-1D92C4B64B8C New York 2015-03-15 8EB3A7CC-CED1-4DBC-98B0-99D325BC7F67
21F3614A-8E76-4A64-8A0B-815D5343FC26 Chicago 2015-03-20 8EB3A7CC-CED1-4DBC-98B0-99D325BC7F67
E1DB1926-4268-4BFA-B5E0-DA603DA8E1B7 San Francisco 2015-03-29 8EB3A7CC-CED1-4DBC-98B0-99D325BC7F67
F50E45E6-E689-444B-96C1-F936CA6F3D2A Miami 2015-03-30 D0EDCEA8-3825-4693-9352-BF7A04AEFCB2
C2FA7073-79D7-42E8-B2C8-6EEDBC374002 Boston 2015-04-05 D0EDCEA8-3825-4693-9352-BF7A04AEFCB2
旁注:您不应该存储此人的 Age
。相反,存储生日并即时计算年龄。
我想垂直拆分现有的(已经填满数据)。
假设我的起始 table (trip
) 看起来像这样:
ID Person Age Trip_to Date
... Alice 21 Los Angeles 2015-04-01
... Bob 35 New York 2015-03-15
... Bob 35 Chicago 2015-03-20
... Bob 35 San Francisco 2015-03-29
... Carol 29 Miami 2015-03-30
... Carol 29 Boston 2015-04-05
我想将这个 table 分成两个 table,因为它应该是,每个 person
和 trip
。
将每个唯一的人复制到 table person
时,我想要自动创建的 uniqueidentifier
列 table person.pId
(主键) 复制到原始 table 中新创建的 uniqueidentifier
列 trip.personid
并将其转换为外键。 (然后我会从原来的 table 中删除 trip.person
和 trip.age
列,并按照我想要的方式组织数据。)
当我将人员行插入新的 table 时,我想我可以为此使用触发器,如下所示:
CREATE TRIGGER tr_person
on person
after INSERT
as
begin
UPDATE Trip
SET personId=(SELECT i.pId from inserted i)
WHERE person=(SELECT i.person from inserted i) and age=(SELECT i.age from inserted i)
END
但是,我明白了:
Subquery returned more than 1 value.
This is not permitted when the subquery follows =, !=, <, <= , >, >=
or when the subquery is used as an expression.
显然,触发器仅在执行了所有(可能是多个!)插入后才执行,到那时,我的 SET
语句不再允许查询插入。
我也考虑过在 INSERT
语句中使用 OUTPUT
子句,但这也行不通
Insert into person (Driver, Age)
OUTPUT inserted.pId INTO trip.personId WHERE trip.person=inserted.person AND trip.Age=inserted.Age
(Select DISTINCT Person, Age FROM Trip)
所以我现在想知道,这一切都错了吗?还有另一种方法可以自动创建两个新拆分的 table 之间的键和关系吗?
编辑想要的结果: Table行程:
ID Trip_to Date PersonId
... Los Angeles 2015-04-01 xxxx1
... New York 2015-03-15 xxxx2
... Chicago 2015-03-20 xxxx2
... San Francisco 2015-03-29 xxxx2
... Miami 2015-03-30 xxxx3
... Boston 2015-04-05 xxxx3
Table人
pId Person Age
xxxx1 Alice 21
xxxx2 Bob 35
xxxx3 Carol 29
(ID字段当然应该都是uniqueidentifiers)
这是一个想法:
首先,您插入所有不同的 Person
从 Trip
table 到 Person
table:
CREATE TABLE Person(
pID UNIQUEIDENTIFIER PRIMARY KEY,
Person VARCHAR(10),
Age INT
)
INSERT INTO Person
SELECT
NEWID(), Person, Age
FROM(
SELECT DISTINCT Person, Age FROM Trip
)t
然后,向 Trip
table PersonId
添加一个新的 FK 列,它引用 Person
table 中的 pId
:
ALTER TABLE Trip
ADD PersonId UNIQUEIDENTIFIER
FOREIGN KEY(PersonId) REFERENCES Person(pId)
然后,UPDATE
使用 Person
和 Age
上的 JOIN
的值来自 Person
table 的新添加的 FK 列:
UPDATE t
SET PersonId = p.pID
FROM Trip t
INNER JOIN Person p
ON p.Person = t.Person
AND p.Age = t.Age
最后,您可以从 Trip
table:
Person
和 Age
ALTER TABLE Trip DROP COLUMN Person
ALTER TABLE Trip DROP COLUMN Age
结果
人
pID Person Age
------------------------------------ ---------- -----------
35815766-1634-45FF-A3F6-8194B43F3F65 Alice 21
8EB3A7CC-CED1-4DBC-98B0-99D325BC7F67 Bob 35
D0EDCEA8-3825-4693-9352-BF7A04AEFCB2 Carol 29
旅行
ID Trip_to Date PersonId
------------------------------------ -------------------- ---------- ------------------------------------
77357A57-FAAE-43DE-923E-219038B8641E Los Angeles 2015-04-01 35815766-1634-45FF-A3F6-8194B43F3F65
C1B64E81-D30A-46A9-A868-1D92C4B64B8C New York 2015-03-15 8EB3A7CC-CED1-4DBC-98B0-99D325BC7F67
21F3614A-8E76-4A64-8A0B-815D5343FC26 Chicago 2015-03-20 8EB3A7CC-CED1-4DBC-98B0-99D325BC7F67
E1DB1926-4268-4BFA-B5E0-DA603DA8E1B7 San Francisco 2015-03-29 8EB3A7CC-CED1-4DBC-98B0-99D325BC7F67
F50E45E6-E689-444B-96C1-F936CA6F3D2A Miami 2015-03-30 D0EDCEA8-3825-4693-9352-BF7A04AEFCB2
C2FA7073-79D7-42E8-B2C8-6EEDBC374002 Boston 2015-04-05 D0EDCEA8-3825-4693-9352-BF7A04AEFCB2
旁注:您不应该存储此人的 Age
。相反,存储生日并即时计算年龄。