我喜欢在我的编码中冗长,所以我的典型插入语句如下所示:
INSERT INTO MyTable
(
Column1
,Column2
,Column3
,Column4
,Column5
,Column6
)
SELECT
Column1 = 'some value'
,Column2 = 'some value'
,Column4 = 'some value'
,Column3 = 'some value'
,Column5 = 'some value'
,Column6 = 'some value'
....
如果你没有注意到这句话的问题,那么你就和我一样被愚弄了无数次。
而这类缺陷真正阴险的部分是,它可能会在导致任何问题之前工作很长时间,当它失败时,即使有错误,它也不会指示真正的错误。
例如,如果第 3 列和第 4 列分别是数字和字符串类型,那么只有某些值会导致第 4 列出现运行时错误(而第 3 列不会出现运行时错误)类型转换失败(例如,'0' 转换为数字就好了但 'asdf' 不会)。
(在我的例子中,它被隐藏在受保护代码部分之外的 Service Broker 激活过程中(这是一个日志语句),所以我什至没有看到那个错误,而是得到了伪装成禁用我的队列的毒消息的孤立事务错误。)
有什么方法可以验证这种不需要人工校对的说法吗?
PS 我知道你可以给任何你喜欢的别名,但是在一个完全可选的上下文中,比如一个语句,使用某种自动化工具(即 IntelliSense)来指出可能的意外代码INSERT
将是非常有用的。
更新:我已经向微软开放了这个反馈项目,因为这个明显缺乏的功能。
我认为没有任何好的方法可以使它自动化。特别是因为根据我的经验,大多数使用的人
INSERT ... SELECT
都没有SELECT
专门为编写INSERT
,而是从其他地方复制它。如果他们已经为 编写了SELECT
,INSERT
他们不太可能去添加列别名的麻烦(无论源是另一个具有不同列名的表,还是只是一系列常量),如果他们确实添加了列别名,则不能保证他们以列名 1:1 映射的方式命名它们。如果我们真的在谈论INSERT ... SELECT (a bunch of constants)
,那更有可能是INSERT ... VALUES()
。您可以向 Microsoft 提交功能请求,但我认为您必须非常彻底地布置用例,才能获得社区希望看到的许多其他改进的牵引力。
如果我的头发特别糟糕,我会这样写我的代码:
而且更容易看出我犯了一个错误。
我已经多次遇到这个问题,以至于我的
INSERT ... SELECT
陈述如下所示:我更喜欢 CTE 而不是子查询。
通过使用
copy+paste
,此方法有助于确保您以相同的顺序列出所有列。既然源表和目标表中的数据没有以我所知道的任何永久方式链接,唯一的验证方法是检查数据类型的正确性,那么我相信 SQL 没有任何其他方法可以判断您的查询是否正确真的真的 REAAAAALLLY 你想要达到的目标。也许将来会有一些人工智能 :)
对于临时表,您可以尝试使用 SELECT INTO 而不是 INSERT..SELECT - 这样列顺序在创建后可能会有所不同,但是从这样的临时表中进行选择时您将获得正确的列。