【问题标题】:Correlation names using insert and outer join使用插入和外连接的关联名称
【发布时间】:2012-07-31 18:31:37
【问题描述】:

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

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

我最终得到了一条错误消息:

消息 208,第 16 级,状态 1,第 1 行 无效的对象名称“测试”。

有谁知道我做错了什么?

【问题讨论】:

    标签: database left-join correlation sql-insert


    【解决方案1】:

    在第一行你应该使用真实的表名

    insert into testDB.dbo.table1

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

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

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

    你可以说,而不是 select *...(假设 source 和 test 具有完全相同的列)

    select source.*
    

    或者您可以调用特定列,如...

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

    我不知道你的栏目名称。

    【讨论】:

    • 我试过了。它不起作用 Msg 213, Level 16, State 1, Line 1 Insert Error: 列名或提供的值的数量与表定义不匹配。
    • 好的,我的例子对我有用,但我会拿你的代码来试一试。
    • 发现另一个问题,修改答案。这样做可以吗?
    【解决方案2】:
    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 
    

    让我们谈谈这有什么问题。首先 select * 将包含源中的所有列并在其中进行测试,这显然比您计划插入的表中的列更多。出于多种原因,在插入语句中使用 select * 是不可接受的。

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

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

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

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

    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])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多