2017-11-09 14 views
1

いくつかのテーブルといくつかのDMLクエリを実行する展開後スクリプトを持つDACPAC(sqlproj)ソリューションがあります。 DMLクエリが失敗した場合(重大度= 20のエラーが発生しています)、dacpacによって行われたDDLの変更と展開後のファイルの変更を含め、すべての変更をロールバックしたいと思います。これは、既存のターゲットデータベースをアップグレードする場合に特に便利です。sqlcmdを使用してトランザクションでDACによって生成された配布スクリプトを実行する

DACPACが公開されているときに、アトミックDBのアップグレードを実行しようとしています.DACPACソリューションで言及されているすべてのDDL変更は、導入後スクリプトのすべてが成功した場合にのみ公開する必要があります。

DACPAC DDLの変更は、デプロイメント後のスクリプトを呼び出す前にコミットされているため、DacServices.GenerateDeployScriptを使用して単一のスクリプトファイルとしてすべてのDAC変更を生成すると考えました。それはまっすぐに見えません。

誰もがこのような試みをしたことがありますか?

私は多くの挑戦に直面しています... データベースはトランザクション内にすべきではありません。 ロールバックはまったく起こりません。

[編集10Nov]:私はより良い自分の問題を説明することができるように、私はあなたがのためにロールバックを含める方法を知っていることを理解質問から(たぶん)、

/* 
Deployment script for 9Nov 

This code was generated by a tool. 
Changes to this file may cause incorrect behavior and will be lost if 
the code is regenerated. 
*/ 

GO 
SET ANSI_NULLS, ANSI_PADDING, ANSI_WARNINGS, ARITHABORT, CONCAT_NULL_YIELDS_NULL, QUOTED_IDENTIFIER ON; 

SET NUMERIC_ROUNDABORT OFF; 


GO 
:setvar INSTALL_DIR "D:\EDW_9Nov\" 
:setvar DatabaseName "9Nov" 
:setvar DefaultFilePrefix "9Nov" 
:setvar DefaultDataPath "C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\" 
:setvar DefaultLogPath "C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\" 

GO 
:on error exit 
GO 
/* 
Detect SQLCMD mode and disable script execution if SQLCMD mode is not supported. 
To re-enable the script after enabling SQLCMD mode, execute the following: 
SET NOEXEC OFF; 
*/ 
:setvar __IsSqlCmdEnabled "True" 
GO 
IF N'$(__IsSqlCmdEnabled)' NOT LIKE N'True' 
    BEGIN 
     PRINT N'SQLCMD mode must be enabled to successfully execute this script.'; 
     SET NOEXEC ON; 
    END 


GO 
USE [master]; 


GO 

IF (DB_ID(N'$(DatabaseName)') IS NOT NULL) 
BEGIN 
    ALTER DATABASE [$(DatabaseName)] 
    SET SINGLE_USER WITH ROLLBACK IMMEDIATE; 
    DROP DATABASE [$(DatabaseName)]; 
END 

GO 
PRINT N'Creating $(DatabaseName)...' 
GO 
CREATE DATABASE [$(DatabaseName)] 
    ON 
    PRIMARY(NAME = [$(DatabaseName)], FILENAME = N'$(DefaultDataPath)$(DefaultFilePrefix)_Primary.mdf') 
    LOG ON (NAME = [$(DatabaseName)_log], FILENAME = N'$(DefaultLogPath)$(DefaultFilePrefix)_Primary.ldf') COLLATE SQL_Latin1_General_CP1_CI_AS 
GO 
IF EXISTS (SELECT 1 
      FROM [master].[dbo].[sysdatabases] 
      WHERE [name] = N'$(DatabaseName)') 
    BEGIN 
     ALTER DATABASE [$(DatabaseName)] 
      SET ANSI_NULLS ON, 
       ANSI_PADDING ON, 
       ANSI_WARNINGS ON, 
       ARITHABORT ON, 
       CONCAT_NULL_YIELDS_NULL ON, 
       NUMERIC_ROUNDABORT OFF, 
       QUOTED_IDENTIFIER ON, 
       ANSI_NULL_DEFAULT ON, 
       CURSOR_DEFAULT LOCAL, 
       RECOVERY SIMPLE, 
       CURSOR_CLOSE_ON_COMMIT OFF, 
       AUTO_CREATE_STATISTICS ON, 
       AUTO_SHRINK OFF, 
       AUTO_UPDATE_STATISTICS ON, 
       RECURSIVE_TRIGGERS OFF 
      WITH ROLLBACK IMMEDIATE; 
     ALTER DATABASE [$(DatabaseName)] 
      SET AUTO_CLOSE OFF 
      WITH ROLLBACK IMMEDIATE; 
    END 


GO 
IF EXISTS (SELECT 1 
      FROM [master].[dbo].[sysdatabases] 
      WHERE [name] = N'$(DatabaseName)') 
    BEGIN 
     ALTER DATABASE [$(DatabaseName)] 
      SET ALLOW_SNAPSHOT_ISOLATION OFF; 
    END 


GO 
IF EXISTS (SELECT 1 
      FROM [master].[dbo].[sysdatabases] 
      WHERE [name] = N'$(DatabaseName)') 
    BEGIN 
     ALTER DATABASE [$(DatabaseName)] 
      SET READ_COMMITTED_SNAPSHOT OFF 
      WITH ROLLBACK IMMEDIATE; 
    END 


GO 
IF EXISTS (SELECT 1 
      FROM [master].[dbo].[sysdatabases] 
      WHERE [name] = N'$(DatabaseName)') 
    BEGIN 
     ALTER DATABASE [$(DatabaseName)] 
      SET AUTO_UPDATE_STATISTICS_ASYNC OFF, 
       PAGE_VERIFY NONE, 
       DATE_CORRELATION_OPTIMIZATION OFF, 
       DISABLE_BROKER, 
       PARAMETERIZATION SIMPLE, 
       SUPPLEMENTAL_LOGGING OFF 
      WITH ROLLBACK IMMEDIATE; 
    END 


GO 
IF IS_SRVROLEMEMBER(N'sysadmin') = 1 
    BEGIN 
     IF EXISTS (SELECT 1 
        FROM [master].[dbo].[sysdatabases] 
        WHERE [name] = N'$(DatabaseName)') 
      BEGIN 
       EXECUTE sp_executesql N'ALTER DATABASE [$(DatabaseName)] 
    SET TRUSTWORTHY OFF, 
     DB_CHAINING OFF 
    WITH ROLLBACK IMMEDIATE'; 
      END 
    END 
ELSE 
    BEGIN 
     PRINT N'The database settings cannot be modified. You must be a SysAdmin to apply these settings.'; 
    END 


GO 
IF IS_SRVROLEMEMBER(N'sysadmin') = 1 
    BEGIN 
     IF EXISTS (SELECT 1 
        FROM [master].[dbo].[sysdatabases] 
        WHERE [name] = N'$(DatabaseName)') 
      BEGIN 
       EXECUTE sp_executesql N'ALTER DATABASE [$(DatabaseName)] 
    SET HONOR_BROKER_PRIORITY OFF 
    WITH ROLLBACK IMMEDIATE'; 
      END 
    END 
ELSE 
    BEGIN 
     PRINT N'The database settings cannot be modified. You must be a SysAdmin to apply these settings.'; 
    END 


GO 
ALTER DATABASE [$(DatabaseName)] 
    SET TARGET_RECOVERY_TIME = 0 SECONDS 
    WITH ROLLBACK IMMEDIATE; 


GO 
IF EXISTS (SELECT 1 
      FROM [master].[dbo].[sysdatabases] 
      WHERE [name] = N'$(DatabaseName)') 
    BEGIN 
     ALTER DATABASE [$(DatabaseName)] 
      SET FILESTREAM(NON_TRANSACTED_ACCESS = OFF), 
       CONTAINMENT = NONE 
      WITH ROLLBACK IMMEDIATE; 
    END 


GO 
IF EXISTS (SELECT 1 
      FROM [master].[dbo].[sysdatabases] 
      WHERE [name] = N'$(DatabaseName)') 
    BEGIN 
     ALTER DATABASE [$(DatabaseName)] 
      SET AUTO_CREATE_STATISTICS ON(INCREMENTAL = OFF), 
       MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT = OFF, 
       DELAYED_DURABILITY = DISABLED 
      WITH ROLLBACK IMMEDIATE; 
    END 


GO 
USE [$(DatabaseName)]; 


GO 
IF fulltextserviceproperty(N'IsFulltextInstalled') = 1 
    EXECUTE sp_fulltext_database 'enable'; 


GO 
PRINT N'Creating [EDW_INTERNAL]...'; 


GO 
CREATE SCHEMA [EDW_INTERNAL] 
    AUTHORIZATION [dbo]; 


GO 
PRINT N'Creating [EDW_INTERNAL].[DB_VERSIONS]...'; 


GO 
CREATE TABLE [EDW_INTERNAL].[DB_VERSIONS] (
    [ID]      BIGINT  IDENTITY (1, 1) NOT NULL, 
    [MODULE]     VARCHAR (30) NOT NULL, 
    [FROM_VERSION]   VARCHAR (20) NOT NULL, 
    [TO_VERSION]    VARCHAR (20) NOT NULL, 
    [UPGRADE_DML_APPLIED_YN] VARCHAR (1) NOT NULL, 
    CONSTRAINT [PK_DB_VERSIONS] PRIMARY KEY CLUSTERED ([MODULE] ASC, [FROM_VERSION] ASC, [TO_VERSION] ASC) 
); 


GO 
PRINT N'Creating [EDW_INTERNAL].[DML_UPGR_SCRIPT_MASTER]...'; 


GO 
CREATE TABLE [EDW_INTERNAL].[DML_UPGR_SCRIPT_MASTER] (
    [MODULE]    VARCHAR (30) NOT NULL, 
    [FROM_VERSION]   VARCHAR (20) NOT NULL, 
    [TO_VERSION]   VARCHAR (20) NOT NULL, 
    [APPLY_ORDER]   INT   NOT NULL, 
    [UPGR_SCRIPT_FILEPATH] VARCHAR (1024) NOT NULL, 
    CONSTRAINT [PK_DML_UPGR_SCRIPT_MASTER] PRIMARY KEY CLUSTERED ([APPLY_ORDER] ASC, [TO_VERSION] ASC, [FROM_VERSION] ASC, [MODULE] ASC) 
); 


GO 
PRINT N'Creating unnamed constraint on [EDW_INTERNAL].[DB_VERSIONS]...'; 


GO 
ALTER TABLE [EDW_INTERNAL].[DB_VERSIONS] 
    ADD DEFAULT 'N' FOR [UPGRADE_DML_APPLIED_YN]; 


GO 
PRINT N'Creating [EDW_INTERNAL].[UPGRADE_DML]...'; 


GO 

CREATE PROCEDURE EDW_INTERNAL.UPGRADE_DML 
    @Module VARCHAR(30) 
AS 
BEGIN 

    DECLARE @Failure bit = 1; 


    IF @Failure = 1 
    BEGIN 
     RAISERROR 
     (N'One or more database upgrade query statements have failed. Please check the DML Upgrade Log table for details.', 
     20, -- Severity. 
     1 -- State 
     ) WITH LOG; 
    END 

END 
GO 
/* 
Post-Deployment Script Template       
-------------------------------------------------------------------------------------- 
This file contains SQL statements that will be appended to the build script.  
Use SQLCMD syntax to include a file in the post-deployment script.   
Example:  :r .\myfile.sql        
Use SQLCMD syntax to reference a variable in the post-deployment script.  
Example:  :setvar TableName MyTable        
       SELECT * FROM [$(TableName)]     
-------------------------------------------------------------------------------------- 
*/ 

-- Reference to load the Version Upgrade tables with rows 
--:r VersionUpgradeRowsPopulate.sql 

-- execute 
EXEC [EDW_INTERNAL].[UPGRADE_DML] @MODULE = 'Test_Common' 
GO 

GO 
DECLARE @VarDecimalSupported AS BIT; 

SELECT @VarDecimalSupported = 0; 

IF ((ServerProperty(N'EngineEdition') = 3) 
    AND (((@@microsoftversion/power(2, 24) = 9) 
      AND (@@microsoftversion & 0xffff >= 3024)) 
     OR ((@@microsoftversion/power(2, 24) = 10) 
      AND (@@microsoftversion & 0xffff >= 1600)))) 
    SELECT @VarDecimalSupported = 1; 

IF (@VarDecimalSupported > 0) 
    BEGIN 
     EXECUTE sp_db_vardecimal_storage_format N'$(DatabaseName)', 'ON'; 
    END 


GO 
PRINT N'Update complete.'; 


GO 

答えて

0

をここdacpacによって生成された展開スクリプトを貼り付けますメインスクリプトは、プレ/ポストスクリプトをロールバックできるように、そのようなことをする必要があります(ただの簡単なテストだったので、理想的な解決策ではないかもしれません)。スクリプトを2回発行し、それをテーブルとして失敗することになっている二度目がすでに存在している:

プリスクリプト:

IF (SELECT OBJECT_ID('tempdb..#tmpErrors2')) IS NOT NULL DROP TABLE #tmpErrors 
GO 
CREATE TABLE #tmpErrors2 (Error int) 
GO 
SET XACT_ABORT ON 
GO 
SET TRANSACTION ISOLATION LEVEL READ COMMITTED 
GO 
BEGIN TRANSACTION 
GO 



--Your prescript part goes here 



GO 
IF @@ERROR <> 0 
    AND @@TRANCOUNT > 0 
    BEGIN 
     ROLLBACK; 
    END 

IF @@TRANCOUNT = 0 
    BEGIN 
     INSERT INTO #tmpErrors2 (Error) 
     VALUES     (1); 
     BEGIN TRANSACTION; 
    END 

ポストスクリプト:

CREATE TABLE tttt4 (a int); 
GO 
IF @@ERROR <> 0 
    AND @@TRANCOUNT > 0 
    BEGIN 
     ROLLBACK; 
    END 

IF @@TRANCOUNT = 0 
    BEGIN 
     INSERT INTO #tmpErrors2 (Error) 
     VALUES     (1); 
     BEGIN TRANSACTION; 
    END 


GO 

IF EXISTS (SELECT * FROM #tmpErrors2) ROLLBACK TRANSACTION 
GO 
IF @@TRANCOUNT>0 BEGIN 
PRINT N'Post/Pre script finished' 
COMMIT TRANSACTION 
END 
ELSE PRINT N'Pre/Post scripts failed' 
GO 
DROP TABLE #tmpErrors2 
GO 
+0

は今より明確に私の質問ですか?質問の中でいくつかの詳細を編集しました – Ash

関連する問題