如何在T-SQL TRY ... CATCH块中使用SQL Server Transaction

时间:2014-01-13 08:49:51

标签: sql-server tsql distributed-transactions database-mail

我有以下示例T-SQL代码,BEGIN TRY

BEGIN TRY    
BEGIN TRANSACTION 

    RESTORE FILELISTONLY
    FROM DISK = 'D:\Backup\MyDatabase.bak'
    GO

    ALTER DATABASE MyDatabase
    SET SINGLE_USER WITH
    ROLLBACK IMMEDIATE

    ALTER DATABASE MyDatabase 
    SET RECOVERY Simple

    ----Restore Database
    RESTORE DATABASE MyDatabase
    FROM DISK = 'D:\Backup\MyDatabase.bak'
    WITH MOVE 'MyDatabase' TO 'C:\DataFolder\MyDatabase.mdf',
    MOVE 'MyDatabase_log' TO 'C:\DataFolder\MyDatabase_log.ldf'

    ALTER DATABASE MyDatabase SET MULTI_USER

    GO

    USE [MyDatabase]
    IF NOT  EXISTS (SELECT * FROM sys.database_principals WHERE name = N'user1')
    CREATE USER [user1] FOR LOGIN [user1] WITH DEFAULT_SCHEMA=[user1]
    GO

    EXEC sp_addrolemember 'db_owner',N'user1'
    GO
    COMMIT
    --Send email on successfull execution of script
    USE  [msdb];
    EXEC sp_send_dbmail @profile_name='My Mail Profile',
    @recipients='myemail@mydomain.org',
    @subject='Test subject',
    @query = '',
    @body='Tested successfully.'
    END TRY
    BEGIN CATCH
    --If there is any error in the script, roll back the transaction and also send an error report email notification
    ROLLBACK
    USE  [msdb];
    EXEC sp_send_dbmail @profile_name='My Mail Profile',
    @recipients='myemail@mydomain.org',
    @subject='Test error',
    @body= ERROR_MESSAGE()
    END CATCH

该代码抛出以下错误,

  1. Msg 102,Level 15,State 1,Line 4 'D:\ Backup \ MyDatabase.bak'附近的语法不正确。

  2. Msg 102,Level 15,State 1,Line 10 'BEGIN'附近的语法不正确。

  3. Msg 102,Level 15,State 1,Line 17 ')'附近的语法不正确。

  4. 但是如果我将代码移出BEGIN TRY和BEGIN TRANSACTION块,它会成功执行而不会出现任何错误。

    我想要实现的只是执行该T-SQL脚本,如果失败,我通知我向某个电子邮件帐户发送通知,其中包含导致电子邮件正文中的代码失败的错误消息。

    关于如何更好地实现这一目标的任何建议都是非常受欢迎的。

2 个答案:

答案 0 :(得分:3)

TRY / CATCH块只能在单个请求(批处理)的范围内使用。您试图跨越几个批次的TRY块。 GO是默认的批处理分隔符,fyi。

您还希望支持某些不支持交易的操作的交易和回滚,例如RESTORE

  

在显式或隐式事务中不允许RESTORE。

您可以更好地在更高级别,应用程序甚至脚本中处理此类问题。请注意,sqlcmd支持-b选项在第一次出错时中断,您可以使用退出代码(%ERRORLEVEL%)。

答案 1 :(得分:1)

第一个问题是第5行中的“go”语句... sql server试图执行到目前为止的行,但这不起作用,因为你有一个没有相应的结束尝试的开始尝试...