Sql server 为什么“插入表”失败,但“插入表(值)”有效

Sql server 为什么“插入表”失败,但“插入表(值)”有效,sql-server,insert,Sql Server,Insert,我在一个数据库中有一个大表,希望将一些列复制到另一个数据库中的另一个表中,这两个数据库位于同一台服务器SQL server 2012上。我已经使用源表中的数据类型和定义创建了目标表,然后尝试: INSERT INTO [MYDB].[dbo].[MYTABLE] SELECT ColumnA, ColumnB, ColumnC, ColumnD FROM [MYotherDB].[dbo].[MYotherTABLE] 这将导致一个错误: 将表达式转

我在一个数据库中有一个大表,希望将一些列复制到另一个数据库中的另一个表中,这两个数据库位于同一台服务器SQL server 2012上。我已经使用源表中的数据类型和定义创建了目标表,然后尝试:

INSERT INTO [MYDB].[dbo].[MYTABLE]
SELECT ColumnA, 
       ColumnB,
       ColumnC,
       ColumnD
FROM [MYotherDB].[dbo].[MYotherTABLE]
这将导致一个错误:

将表达式转换为数据类型nvarchar时出现算术溢出错误

然而,下面的工作。为什么?

INSERT INTO [MYDB].[dbo].[MYTABLE] (ColumnA, ColumnB, ColumnC, ColumnD)
SELECT ColumnA, 
       ColumnB,
       ColumnC,
       ColumnD,
FROM [MYotherDB].[dbo].[MYotherTABLE]

因为[MYDB].[dbo].[MYTABLE]和[MYotherDB].[dbo].[MYotherTABLE]的定义不同

执行INSERT时,SELECT中列的别名/名称对目标表没有意义。以这两个表为例:

CREATE TABLE dbo.T1 (C1 int,
                     C2 int);
CREATE TABLE dbo.T2 (C1 int,
                     C2 int);
让我们把一些数据放在T1中:

现在,如果我们运行以下两条语句:

INSERT INTO dbo.T2
SELECT C2, C1
FROM T1;

INSERT INTO dbo.T2 (C2,C1)
SELECT C2, C1
FROM T1;
你认为这两种说法相同吗?如果是这样,你就错了:

SELECT *
FROM T2;
请注意,第一个语句中的值在其中切换。这是因为第一句话相当于:

INSERT INTO dbo.T2 (C1,C2)
SELECT C2, C1
FROM T1;
如果我们要在表的定义中切换列,我怀疑您的环境中会出现这种情况,这同样适用于:

CREATE TABLE dbo.T3 (C2 int,
                     C1 int);

INSERT INTO dbo.T3
SELECT C1, C2
FROM T1;

SELECT *
FROM dbo.T3

我们不知道您的表的定义,但原因是相同的。解决方案:在使用INSERT时始终显式定义列。

盲插入是常见的反模式-显式定义列列表-因为您正在插入错误的列,或者表中列的顺序与select子句中的顺序不一致。始终明确列出插入到的目标列。。。SELECT.Antipattern警报-太棒了。我在记笔记。谢谢你,卢卡斯。那么,为什么下面的工作很好呢?插入[MYDB].[dbo].[MYTABLE]从[MYotherDB].[dbo].[MYotherTABLE]中选择前1000列A、B、C、D,谢谢,拉穆。我明白你所说的-切换列可能会导致错误,因为要将第一个参数填充到第一列中。但我没有把它们换过来。我也接受卢卡斯和蒂姆的最佳实践建议。。。让我恼火的是上面提到的错误类型,这听起来更像是一个数据类型问题,在这种情况下,插入表值应该成功对我来说没有意义。
CREATE TABLE dbo.T3 (C2 int,
                     C1 int);

INSERT INTO dbo.T3
SELECT C1, C2
FROM T1;

SELECT *
FROM dbo.T3