我有以下两个表/列:
TableA
id | data
TableB
fkeyA1 | fkeyA2 | fkeyA3 | name
TableB中的前三列是所有指向TableA的外键。我想将TableB转换为以下两个表:
TableC
id | name
TableD
fkeyC | fkeyA
使TableB中的一行成为TableC中的一行加上TableD中的三行。我该如何为此编写SQL查询?
在TableB
中,(fkeyA1, fkeyA2, fkeyA3)
上有一个唯一索引,但name
列不一定具有唯一值。
答案 0 :(得分:1)
我首先要插入到tableC中,Id
为IDENTITY
列
INSERT INTO TableC(name)
SELECT b.name
FROM TableB AS b
然后我会写一个插入内容:
SELECT c.Id, b.fkeyA1
FROM TableC AS c
INNER JOIN tableB AS b ON c.name = b.name
UNION
SELECT c.Id, b.fkeyA2
FROM TableC AS c
INNER JOIN tableB AS b ON c.name = b.name
UNION
SELECT c.Id, b.fkeyA3
FROM TableC AS c
INNER JOIN tableB AS b ON c.name = b.name
INSERT进入TableD的另一种方法是:
SELECT c.Id, a.Id
FROM TableB AS b
INNER JOIN TableC AS c ON b.name = c.name
LEFT JOIN TableA AS a ON b.fkeyA1 = a.Id
OR b.fkeyA2 = a.Id
OR b.fkeyA3 = a.Id
如果tableB包含名称“Adam”两次,则B中的两个记录将由TableC中的相同Id引用,TableD将具有该Id的6个记录
例如
TableA TableB TableC TableD
1, 'Data1' 1, 2, 3, 'Adam' 1, 'Adam' 1, 1
2, 'Data2' 4, 5, 6, 'Someone' 2, 'Someone' 1, 2
3, 'Data3' 7, 8, 9, 'Adam' 1, 3
4, 'Data4' 1, 7
5, 'Data5' 1, 8
6, 'Data6' 1, 9
7, 'Data7' 2, 4
8, 'Data8' 2, 5
9, 'Data9' 2, 6
答案 1 :(得分:1)
您可以使用游标语句:
declare @idC table(id int)
declare @fkeyC int, @fkeyA1 int, @fkeyA2 int, @fkeyA3 int, @name varchar(8)
declare CursorB cursor fast_forward for select fkeyA1, fkeyA2, fkeyA3, name from TableB
open CursorB
fetch next from CursorB into @fkeyA1, @fkeyA2, @fkeyA3, @name
while @@fetch_status = 0
begin
insert into TableC(name) output inserted.id into @idC values (@name)
set @fkeyC = (select top 1 id from @idC)
insert into TableD(fkeyC, fkeyA) values (@fkeyC, @fkeyA1), (@fkeyC, @fkeyA2), (@fkeyC, @fkeyA3)
delete from @idC
fetch next from CursorB into @fkeyA1, @fkeyA2, @fkeyA3, @name
end
close CursorB
deallocate CursorB
这可能不是性能最好的,但会允许名称列的非唯一值。