SQL 通过 dapper 插入的查询以一种方式工作,但不能以另一种方式工作(包括查询)
SQL query to insert via dapper works one way but not the other (queries included)
奇怪的错误来自一个查询而不是另一个,我不确定为什么一个查询有效而另一个无效。
顺便说一下,第二个 Insert
语句处理 FieldA = 单值@var1,FieldB = 值数组和 FieldC = 单值@param3。
还有一点,FieldA + FieldB 是复合唯一约束(但不是外键)
工作版本:
Declare @var1 int
Insert into table1 (field1, field2)
values (@param1, @param2);
select @var1 = SCOPE_IDENTITY()
Insert into table2
Select FieldA = @var1, FieldB = Id, FieldC = @param3
from table3
where FieldD = @param4;
Select @var1;
错误版本(没什么不同,只是 FieldA、B、C 的对齐):
Declare @var1 int
Insert into table1 (field1, field2)
values (@param1, @param2);
select @var1 = SCOPE_IDENTITY()
Insert into table2
Select FieldA = @var1, FieldC = @param3, FieldB = Id
from table3
where FieldD = @param4;
Select @var1;
您似乎(错误地!)假设您在 insert....select
语句的 select
子句中使用的别名决定了值将转到哪些列 - 嗯,那不是它是如何工作的。
就像 insert...values
一样,您应该在 insert
子句中指定列列表(即使它是可选的),就像在 values
子句中一样,顺序select
子句返回的列表示它们将进入的列。
事实上,insert...select
子句中的别名除了有助于提高可读性之外毫无意义——数据库将忽略它们——但如果它们有助于提高可读性,那么保留它们可能不是一个坏选择。
第一个版本只是偶然工作 - 因为 select
子句中列的顺序与 table 本身中列的顺序相匹配 - 或者最糟糕的是,它没有匹配但不匹配的列的数据类型与 select 列表中列的顺序兼容,这意味着您插入了错误的数据而没有得到任何指示。
正确的代码应该是这样的(省略第一个插入语句):
Insert into table2(FieldA, FieldB, FieldC)
Select @var1, Id, @param3 from table3 where FieldD = @param4;
和
Insert into table2(FieldA, FieldC, FieldB)
Select @var1, @param3, Id from table3 where FieldD = @param4;
这样,您的 insert...select
语句不依赖于 table 本身中列的顺序,并且如果您向 table 添加列也不会中断(除非您添加没有默认值的 non-nullable 列)或者如果您更改 table 中列的顺序(我同意这不太可能,但我已经看到它完成了,比您预期的更频繁)。
奇怪的错误来自一个查询而不是另一个,我不确定为什么一个查询有效而另一个无效。
顺便说一下,第二个 Insert
语句处理 FieldA = 单值@var1,FieldB = 值数组和 FieldC = 单值@param3。
还有一点,FieldA + FieldB 是复合唯一约束(但不是外键)
工作版本:
Declare @var1 int
Insert into table1 (field1, field2)
values (@param1, @param2);
select @var1 = SCOPE_IDENTITY()
Insert into table2
Select FieldA = @var1, FieldB = Id, FieldC = @param3
from table3
where FieldD = @param4;
Select @var1;
错误版本(没什么不同,只是 FieldA、B、C 的对齐):
Declare @var1 int
Insert into table1 (field1, field2)
values (@param1, @param2);
select @var1 = SCOPE_IDENTITY()
Insert into table2
Select FieldA = @var1, FieldC = @param3, FieldB = Id
from table3
where FieldD = @param4;
Select @var1;
您似乎(错误地!)假设您在 insert....select
语句的 select
子句中使用的别名决定了值将转到哪些列 - 嗯,那不是它是如何工作的。
就像 insert...values
一样,您应该在 insert
子句中指定列列表(即使它是可选的),就像在 values
子句中一样,顺序select
子句返回的列表示它们将进入的列。
事实上,insert...select
子句中的别名除了有助于提高可读性之外毫无意义——数据库将忽略它们——但如果它们有助于提高可读性,那么保留它们可能不是一个坏选择。
第一个版本只是偶然工作 - 因为 select
子句中列的顺序与 table 本身中列的顺序相匹配 - 或者最糟糕的是,它没有匹配但不匹配的列的数据类型与 select 列表中列的顺序兼容,这意味着您插入了错误的数据而没有得到任何指示。
正确的代码应该是这样的(省略第一个插入语句):
Insert into table2(FieldA, FieldB, FieldC)
Select @var1, Id, @param3 from table3 where FieldD = @param4;
和
Insert into table2(FieldA, FieldC, FieldB)
Select @var1, @param3, Id from table3 where FieldD = @param4;
这样,您的 insert...select
语句不依赖于 table 本身中列的顺序,并且如果您向 table 添加列也不会中断(除非您添加没有默认值的 non-nullable 列)或者如果您更改 table 中列的顺序(我同意这不太可能,但我已经看到它完成了,比您预期的更频繁)。