Sea*_*ish 3 sql-server ssms sql-server-2016
我正在尝试提出一个数据库脚本,用于将应用程序数据库的早期版本迁移到更高版本。差异相当大,完成迁移将涉及创建新表、重命名表、添加函数、添加具有依赖于这些函数的计算列的视图等。脚本完成后,我将其交给其他人在目标环境上运行。
我希望能够在单个事务中运行整个迁移,这样如果出现问题,回滚就很容易了。
我遇到的问题是,当脚本尝试时CREATE FUNCTION,它会抱怨:
SQL80001:语法不正确:“CREATE FUNCTION”必须是批处理中的唯一语句。
我做了一些研究,发现 SSMS 允许使用GO关键字来分隔批次,但是每次我尝试将整个脚本包装在 a 中BEGIN TRANSACTION,然后包含 aGO以将 create 函数调用分离到自己的批次中时,我得到一个错误:
“GO”附近的语法不正确。
我不知道为什么,因为像这样的答案似乎适用于那里的 GO 语句。
我还假设(可能是错误的)我提供脚本的人将使用 SSMS。
我还发现了几篇提到 using 的文章,SET XACT_ABORT ON;我一开始就在交易之外尝试过。
所以我的脚本看起来像这样:
SET XACT_ABORT ON
GO
BEGIN TRY
BEGIN TRANSACTION
-- Create some tables
GO -- Error
CREATE FUNCTION [...]
GO -- Error
-- Create some views that rely on the above function
COMMIT TRANSACTION
END TRY -- With the GOs in there, this line also gives an error: Incorrect syntax near 'TRY'. Expecting CONVERSATION.
BEGIN CATCH
-- Error handling, including transaction rollback
END CATCH
Run Code Online (Sandbox Code Playgroud)
关于如何在单个脚本中使用多个批次但一个事务迁移 SQL 数据库的任何建议?
问题实际上只是关于错误处理,因为当您在 SSMS 查询窗口(以太正常或 SQLCMD 模式)中运行脚本时,SSMS 无法跨批次处理错误。因此,您的事务可能会中止,而 SSMS 将运行下一批。
如果您使用 SQLCMD 运行脚本,您可以在第一批中启动一个事务,并使用 -b 开关。任何错误都会中止脚本并回滚您的事务。
例如
use tempdb
go
begin transaction
-- be sure to run with sqlcmd -b
-- eg c:> sqlcmd -b -i c:\deploy\thisscript.sql
go
--. . . any number of batches here
go
commit transaction
go
Run Code Online (Sandbox Code Playgroud)
当然,您必须确保您的脚本不会提交或回滚事务、捕获错误或包含任何无法在事务中运行的语句(例如向数据库添加文件)。
类似地,您可以在 .NET 或 PowerShell 中自己分批批处理,启动事务,然后单独运行每个批处理,仅当所有批处理都没有错误运行时才提交。
处理整个场景的另一个好方法(如果您可以在中断期间进行升级)是使用数据库快照。万一发生故障,从数据库快照还原允许快速回滚所有升级操作,而无需事务。
| 归档时间: |
|
| 查看次数: |
1471 次 |
| 最近记录: |