作为我目前工作的公司的一部分,我需要创建一些数据库升级脚本来替换以前的承包商的一些工作。
运行以下块之前的代码,创建新的ID列,然后这个脚本将填充值,然后删除一些列。
IF EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID(N'[Central].[Core.Report].[ReportLessonComp]')
AND name = 'Name')
and
EXISTS (
SELECT *
FROM sys.columns
WHERE object_id = OBJECT_ID(N'[Central].[Core.Report].[ReportLessonComp]')
AND name = 'Code')
BEGIN
UPDATE
[Central].[Core.Report].[ReportLessonComp]
SET
CompetencyId = rc.Id
FROM
[Central].[Core.Report].[ReportLessonComp] rlc
INNER JOIN
[Core.Lookup].ReportCompetency rc
ON
rc.Code = rlc.Code and rc.Name = rlc.Name
ALTER TABLE [Central].[Core.Report].[ReportLessonComp] DROP COLUMN CODE
ALTER TABLE [Central].[Core.Report].[ReportLessonComp] DROP COLUMN [Name]
ALTER TABLE [Central].[Core.Report].[ReportLessonComp] DROP COLUMN [Description]
END
GO
当运行if存在\ not存在检查,然后选择getdate()时,这会很好地工作,并给出我期望的结果。
但是,当我运行上面的代码块时,会出现错误。
Msg 207,第16级,状态1,第23线 无效的列名‘代码’。 Msg 207,第16级,状态1,第23线 无效列名“名称”。
该脚本是更大的升级脚本的一部分,用于公司选择的系统calle RoundHouse https://github.com/chucknorris/roundhouse中。
在进行上述检查之前,如果存在,
IF (SELECT COUNT(1) FROM sys.columns
WHERE OBJECT_ID = OBJECT_ID('[Central].[Core.Report].[ReportLessonComp]')
AND Name in ('Name','Code')) = 2
这也给出了同样的问题。我有五个表需要更新,如果我不能在下一次公关中解决这个问题,这将阻止团队工作。
我能做些什么来阻止这种情况导致升级脚本失败?
编辑--我之所以在varchar字段上链接,也是因为之前的开发人员没有在表之间创建关系,只是将字符串插入表中,而不是通过ID进行关联,从而可能导致未链接\不一致的数据。
在此之前的表编辑将创建新的id列,此脚本将获取不再需要的值和删除列。
发布于 2019-05-07 12:45:00
SQL Server将在执行之前解析整个语句,因此,“存在”检查不会保护您不受正在解析的更新的影响。如果已经删除了该列,则该语句将无效,您将得到一个解析错误。update语句必须以dynamic,sp_execute的形式执行,这样更新的varchar就不会被直接解析。
对于Server 2016及以上,drop列也可以受到更多的保护:
ALTER TABLE [Central].[Core.Report].[ReportLessonComp] DROP COLUMN IF EXISTS CODE
https://stackoverflow.com/questions/56022785
复制相似问题