Sql server 如果列存在,则有条件地插入到表中
我正在尝试编写一个幂等元db迁移脚本,其中包括需要洗牌一些数据的脚本。在脚本的后面,我从中选择的一列被删除(迁移的目的是将数据从该列移动到一个新位置),因此我有如下内容(由EF Core生成): 然而,这并不像我希望的那样是幂等的;第二次运行脚本时,由于Sql server 如果列存在,则有条件地插入到表中,sql-server,tsql,idempotent,Sql Server,Tsql,Idempotent,我正在尝试编写一个幂等元db迁移脚本,其中包括需要洗牌一些数据的脚本。在脚本的后面,我从中选择的一列被删除(迁移的目的是将数据从该列移动到一个新位置),因此我有如下内容(由EF Core生成): 然而,这并不像我希望的那样是幂等的;第二次运行脚本时,由于INSERT语句中出现错误,脚本失败,因为OldB列不再存在于bar上 但是,如果删除了OldB,则上面的guard子句将始终为false,因为在删除OldB的过程中,我们还将该行插入迁移历史记录中(是的,我已经检查过,现在也是这样;该行存在)。
INSERT
语句中出现错误,脚本失败,因为OldB
列不再存在于bar
上
但是,如果删除了OldB
,则上面的guard子句将始终为false,因为在删除OldB
的过程中,我们还将该行插入迁移历史记录中(是的,我已经检查过,现在也是这样;该行存在)。因此,INSERT
在没有它关心的所有列的情况下永远不会运行
如何编写像上面那样的幂等元
INSERT
,它在实际运行之前不会验证所有列的存在性?您可以检查是否所有列都存在:
IF NOT EXISTS (SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'AName')
BEGIN
IF (SELECT COUNT(*)
FROM sys.columns
WHERE [object_id] = OBJECT_ID('Bars')
AND name IN ('OldA', 'OldB')) = 2
BEGIN
EXEC('INSERT INTO Foos (A, B)
SELECT OldA, OldB FROM Bars');
END
END
-- a little later in the script:
IF NOT EXISTS (SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'AnotherName')
BEGIN
EXEC('ALTER TABLE [Bars] DROP COLUMN [OldB]');
END
您可以检查是否存在所有列:
IF NOT EXISTS (SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'AName')
BEGIN
IF (SELECT COUNT(*)
FROM sys.columns
WHERE [object_id] = OBJECT_ID('Bars')
AND name IN ('OldA', 'OldB')) = 2
BEGIN
EXEC('INSERT INTO Foos (A, B)
SELECT OldA, OldB FROM Bars');
END
END
-- a little later in the script:
IF NOT EXISTS (SELECT * FROM [__EFMigrationsHistory]
WHERE [MigrationId] = N'AnotherName')
BEGIN
EXEC('ALTER TABLE [Bars] DROP COLUMN [OldB]');
END
我打算建议使用动态SQL。我打算建议使用动态SQL。这仍然会产生相同的错误;似乎我在
INSERT
周围有一个保护子句来确保它永远不会被执行并不重要,它仍然被认为是无效的。例如,如果0=1,用包装插入
,仍然会产生错误。@TomasLycken请检查我的编辑。用动态SQL包装它将解决名称解析问题,检查将在运行时完成;似乎我在INSERT
周围有一个保护子句来确保它永远不会被执行并不重要,它仍然被认为是无效的。例如,如果0=1,用包装插入
,仍然会产生错误。@TomasLycken请检查我的编辑。用动态SQL包装它将解决名称解析问题,检查将在运行时完成。