我需要获取两个父>子表集合中的数据/合并到第三个父>子表中。合并两个父>子表集合
的表是这样的:
在三套表的唯一区别是,表C具有TableType
列,以帮助辨别TableA的记录和表B记录之间的差。
我的第一个想法是使用游标。这里的代码来创建表结构,插入一些记录,然后将数据合并在一起。它工作得很好,SOOOOO ....
--Create the tables
CREATE TABLE TableA
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableAChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_A FOREIGN KEY (Parent) REFERENCES TableA(ID)
);
CREATE TABLE TableB
(
ID int not null identity primary key,
Name VARCHAR(30)
);
CREATE TABLE TableBChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_B FOREIGN KEY (Parent) REFERENCES TableB(ID)
);
CREATE TABLE TableC
(
ID int not null identity primary key,
TableType VARCHAR(1),
Name VARCHAR(30)
);
CREATE TABLE TableCChild
(
ID int not null identity primary key,
Parent int not null,
Name VARCHAR(30),
CONSTRAINT FK_C FOREIGN KEY (Parent) REFERENCES TableC(ID)
);
-- Insert some test records..
INSERT INTO TableA (Name) Values ('A1')
INSERT INTO TableAChild (Name, Parent) VALUES ('A1Child', SCOPE_IDENTITY())
INSERT INTO TableB (Name) Values ('B1')
INSERT INTO TableBChild (Name, Parent) VALUES ('B1Child', SCOPE_IDENTITY())
-- Needed throughout..
DECLARE @ID INT
-- Merge TableA and TableAChild into TableC and TableCChild
DECLARE TableACursor CURSOR
-- Get the primary key from TableA
FOR SELECT ID FROM TableA
OPEN TableACursor
FETCH NEXT FROM TableACursor INTO @ID
WHILE @@FETCH_STATUS = 0
BEGIN
-- INSERT INTO SELECT the parent record into TableC, being sure to specify a TableType
INSERT INTO TableC (Name, TableType) SELECT Name, 'A' FROM TableA WHERE ID = @ID
-- INSERT INTO SELECT the child record into TableCChild using the parent ID of the last row inserted (SCOPE_IDENTITY())
-- and the current record from the cursor (@ID).
INSERT INTO TableCChild(Name, Parent) SELECT Name, SCOPE_IDENTITY() FROM TableAChild WHERE Parent = @ID
FETCH NEXT FROM TableACursor INTO @ID
END;
CLOSE TableACursor
DEALLOCATE TableACursor
-- Repeat for TableB
DECLARE TableBCursor CURSOR
FOR SELECT ID FROM TableB
OPEN TableBCursor
FETCH NEXT FROM TableBCursor INTO @ID
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO TableC (Name, TableType) SELECT Name, 'B' FROM TableB WHERE ID = @ID
INSERT INTO TableCChild(Name, Parent) SELECT Name, SCOPE_IDENTITY() FROM TableBChild WHERE Parent = @ID
FETCH NEXT FROM TableBCursor INTO @ID
END;
CLOSE TableBCursor
DEALLOCATE TableBCursor
现在,我的问题(S):
- 我一直被告知,光标是坏的。但我找不到另一种方式。我想知道是否有某种方式可以用CTE来做到这一点?
- 如果光标适合这种情况,我是怎么做的?有没有更好的方式去做我所做的事情?它看起来不太干,但我不是SQL专家。
最后,如果你想重新运行上面的查询,这里有一个小脚本来删除创建的表。
DROP TABLE TableAChild
DROP TABLE TableBChild
DROP TABLE TableCChild
DROP TABLE TableA
DROP TABLE TableB
DROP TABLE TableC
正确的结果应该是这样的:
如果'tablea'和'tableb'中的名称字段在每个表中都是唯一的,那么您可以在不使用游标的情况下重写它,并使用'join'。但是,如果它们不是唯一的,那么光标是我看到从父级获得'id'字段的唯一选项。 – sgeddes
@sgeddes您是在引用名称列中的*值*吗?如果是这样,它们不是唯一的。 –
为什么不只是将另一列添加到TableC for LegacyID。这会给你一个使用连接的价值。没有必要做这种RBAR。 –