使用插入和外部连接的关联名称

时间:2012-07-31 18:31:38

标签: database left-join correlation sql-insert

我正在尝试运行代码,使用来自不同数据库的不同表中的行从一个表插入行 我有这个:

INSERT [testDB].[dbo].[table1]
SELECT * FROM 
[sourceDB].[dbo].[table1]
LEFT OUTER JOIN [testDB].[dbo].[table1] 
ON [sourceDB].[dbo].[table1].[PKcolumn] = [testDB].[dbo].[table1].[PKcolumn]
WHERE [testDB].[dbo].[table1].[PKcolumn] IS NULL

但是我被告知要添加相关名称,所以我做了这个:

INSERT test
SELECT * FROM 
[sourceDB].[dbo].[table1] as source
LEFT OUTER JOIN 
[testDB].[dbo].[table1] as test
ON 
source.[PKcolumn] = test.[PKcolumn]
WHERE test.[PKcolumn] IS NULL

我最终将此视为错误消息:

Msg 208,Level 16,State 1,Line 1 无效的对象名称't​​est'。

有谁知道我做错了什么?

2 个答案:

答案 0 :(得分:1)

在第一行中,您应该使用实际表名称,如

insert into testDB.dbo.table1

SQLServer不接受该位置的别名或相关名称,我通过测试确认了这一点。

但是您可以在查询中稍后使用别名,这样做非常有用,可以避免关于列来自哪个表格的模糊性。

此查询中的另一个潜在问题是使用select *。这会尝试将sourcedb.dbo.table1和testdb.dbo.table1中的组合列集插入testdb.dbo.table1。那不行。

而不是选择*你可以说...(假设源和测试具有完全相同的列)

select source.*

或者您可以在...中调出特定的列

select source.colA, source.col3, etc....

我不知道你的专栏名称。

答案 1 :(得分:0)

INSERT test 
SELECT *
FROM  [sourceDB].[dbo].[table1] as source 
LEFT OUTER JOIN  [testDB].[dbo].[table1] as test 
   ON  source.[PKcolumn] = test.[PKcolumn] 
WHERE test.[PKcolumn] IS NULL 

让我们谈谈这有什么问题。首先选择*将包含源和测试中的所有列,这显然比您计划插入的表中的列多。由于多种原因,在insert语句中使用select *是绝对不可接受的。

首先,如果有人更改了列的顺序或表的结构,则插入会中断。其次,当你有这样的连接时,它的列数就是错误的。第三,即使它们在不同的顺序中具有相同的列,您也可以将数据放入worng列。如果它们是相似的数据类型并且数据适合或可以进行隐含转换,则数据库不会阻止您执行此操作。

接下来,您不能使用select中的别名作为插入中的目标,您必须引用实际的表名。

最后,在每个插入中不使用列列表是一种非常糟糕的做法。这有助于维护,并确保您可以检查列中的列是否与插入中的列匹配。此外,如果您有自动生成的字段,则必须使用列列表,否则它将尝试插入自动生成的字段,从而出错。

所以你的陈述应该是这样的:

INSERT [testDB].[dbo].[table1] (field1, field2, field3)
SELECT source.field1, source.field2, source.field3
FROM  [sourceDB].[dbo].[table1] as source 
LEFT OUTER JOIN  [testDB].[dbo].[table1] as test 
   ON  source.[PKcolumn] = test.[PKcolumn] 
WHERE test.[PKcolumn] IS NULL 

或者(可能更有效率,您必须在特定情况下进行测试):

INSERT [testDB].[dbo].[table1] (field1, field2, field3)
SELECT source.field1, source.field2, source.field3
FROM  [sourceDB].[dbo].[table1] as source 
WHERE NOT EXISTS (SELECT * FROM testDB].[dbo].[table1] test 
                  WHERE  source.[PKcolumn]=test.[PKcolumn])