web-dev-qa-db-ja.com

ソース管理にSQL Serverエージェントジョブを含める最善の方法は何ですか?

SQL Serverエージェントジョブを「作成先」としてスクリプト化すると、スクリプトがuse msdb-で始まることがわかりました。そのため、ジョブはmsdbデータベースに格納されていると思いますか?

SQL ServerジョブをVisual Studioデータベースプロジェクトに追加する最良の方法は何ですか? msdbデータベースをデータベースソリューションに追加しましたが、ジョブへの参照がないようです。

ジョブをデータベースとともに展開/更新したいのですが、これは不可能のようです。

7
Zach Smith

この質問をしていただいて本当にうれしいです。 Visual StudioデータベースプロジェクトでのSQL Serverジョブと、データベースと一緒にジョブを展開する必要性も同じでした。

ソリューションファイルに、実装したSQLデータベースプロセスに必要なすべてを1か所に含めて、このソリューションを作成してAND Deployしたかった任意のサーバーに対するこのソリューション(数クリックで)。このソリューションのコンポーネントは次のとおりです。

  • データベーススキーマ
  • SSISパッケージ
  • SQL Serverの構成(マスターdb“ Credential”の作成、msdb“ Proxy”の作成、SQLエージェント“ Job”の作成)。

次の2つの理由から、すべてをまとめておきたいと思いました。

  • 簡素化されたデプロイメント(ソース:ローカル開発インスタンス/ターゲット:サーバー開発インスタンス)
  • ソリューションのドキュメント

それで私はこれを理解することに取り組むことにしました。これが私が作成したものであり、このセットアップをどのように調達したかです。それは意図された目的のためにうまく働きます。


概要:

  1. TSQLコードを使用してスクリプトファイルを作成します。 CHECK FOR EXISTENCEメソッドを使用して、環境にすでに存在するものを作成する可能性のあるエラーを回避しました。

参照: 資格情報がSQL Serverインスタンスに存在するかどうかを確認する方法

例:

IF EXISTS (SELECT job_id FROM msdb.dbo.sysjobs WHERE name = N'MyJobNameInSqlAgent')
    BEGIN
        print 'Yep, found it!!!'

        --Really you need to add the script to create it...
    END
  1. スクリプトファイルを実行するスクリプトファイルを作成します。詳細は以下をご覧ください。

  2. データベースプロジェクトを公開します、および[〜#〜] boom [〜#〜]ただ素晴らしいことをしました。


SSDTセットアップ:

  1. Pluralsight:Robert DBによる "VSでのDBプロジェクト開発" |モジュール:データとスキーマの比較、展開前後のスクリプト

まず、この役立つPluralsightビデオを確認しました。私はそれに沿って進むことができました、そして私がしたことは...

A)New Folder[ScriptsPostDeployment]というプロジェクトに新しいフォルダーを作成します

B)New Script[Create_SqlAgentJobs.sql]というフォルダーに新しいスクリプトを作成します。

  1. エラーMSG:「Visual Studioデータベースプロジェクトに配置できる配置後スクリプトは1つだけです」

[Build Action = "Post Deploy"]で複数のスクリプトファイルを作成しようとすると、このエラーメッセージが表示されます。

全体として、私のプロジェクトにはこの1つのスクリプトだけでなく、Create_SqlAgentJobs.sqlCredential_GEORGES-bl0040ep.sqlProxyAccount_GEORGES-bl0040ep.sqlなどのスクリプトも必要です。エラーは、StackOverFlowのこのスレッドで説明および解決されました: SQL Serverプロジェクトが複数のスクリプトポストデプロイを実行しています

合計で、新しいフォルダには4つのスクリプトがあります。1つはスクリプトを実行するためのものです。実行する必要がある3つのスクリプト。

ssdt-dbproj_DB-ScriptsPostDeployment.png

enter image description here


SSDT公開:

パブリッシュファイルを実行し、「スクリプトを生成する」オプションを選択しました。スクリプトを表示して... POSTデプロイメントコードが自動的に挿入され、SQLエージェントジョブが追加されました!!成功!以下は、SQLインスタンスでクエリを実行した後のスクリプトとスクリプト実行メッセージですSSMS ...

enter image description here

/*
Deployment script for DBA

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 DatabaseName "DBA"
:setvar DefaultFilePrefix "DBA"
: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

IF (DB_ID(N'$(DatabaseName)') IS NOT NULL)
BEGIN
    DECLARE @rc      int,                       -- return code
            @fn      nvarchar(4000),            -- file name for back up
            @dir     nvarchar(4000)             -- backup directory

    EXEC @rc = [master].[dbo].[xp_instance_regread] N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'BackupDirectory', @dir output, 'no_output'
    if (@rc = 0) SELECT @dir = @dir + N'\'

    IF (@dir IS NULL)
    BEGIN 
        EXEC @rc = [master].[dbo].[xp_instance_regread] N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'DefaultData', @dir output, 'no_output'
        if (@rc = 0) SELECT @dir = @dir + N'\'
    END

    IF (@dir IS NULL)
    BEGIN
        EXEC @rc = [master].[dbo].[xp_instance_regread] N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\Setup', N'SQLDataRoot', @dir output, 'no_output'
        if (@rc = 0) SELECT @dir = @dir + N'\Backup\'
    END

    IF (@dir IS NULL)
    BEGIN
        SELECT @dir = N'$(DefaultDataPath)'
    END

    SELECT  @fn = @dir + N'$(DatabaseName)' + N'-' + 
            CONVERT(nchar(8), GETDATE(), 112) + N'-' + 
            RIGHT(N'0' + RTRIM(CONVERT(nchar(2), DATEPART(hh, GETDATE()))), 2) + 
            RIGHT(N'0' + RTRIM(CONVERT(nchar(2), DATEPART(mi, getdate()))), 2) + 
            RIGHT(N'0' + RTRIM(CONVERT(nchar(2), DATEPART(ss, getdate()))), 2) + 
            N'.bak' 
            BACKUP DATABASE [$(DatabaseName)] TO DISK = @fn
END
GO
USE [$(DatabaseName)];


GO
PRINT N'SKIPPING THIS STEP (Manual)!!!  Dropping [olap].[UsageStatsLog_GCOP039_bak20190218]...';


GO
--DROP TABLE [olap].[UsageStatsLog_GCOP039_bak20190218];


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 
--https://dba.stackexchange.com/questions/202000/what-is-the-best-way-to-include-sql-server-agent-jobs-in-source-control
--
*/

--DESCRIPTION:
--SQL Agent Job created.
--Credential and Proxy Account required setups are preceded in this script 
USE master 
GO

/*
REFERENCE 
--https://dataqueen.unlimitedviz.com/2015/05/creating-a-proxy-user-to-run-an-ssis-package-in-sql-server-agent/ 
--https://stackoverflow.com/questions/10946718/how-to-check-if-a-credential-exists-in-a-sql-server-instance
*/

IF EXISTS (select * from sys.credentials where name = 'Credential_BL0040EP')
    BEGIN
        PRINT 'The credential [Credential_BL0040EP] already exists...'

    END

IF NOT EXISTS (select * from sys.credentials where name = 'Credential_BL0040EP')
    BEGIN
        -- Create a proxy credential for xp_cmdshell.
        EXEC sp_xp_cmdshell_proxy_account 'GEORGES\bl0040ep', 'EnterThePasswordHere';   --SELECT  * FROM [master].[sys].[credentials]

        -- Grant execute permission on xp_cmdshell to the SQL Server login account. 
        GRANT exec ON sys.xp_cmdshell TO [GEORGES\bl0040ep] 

        -- Create a credential containing the GEORGES account PowerGEORGES\PowerUser and its password
        CREATE CREDENTIAL Credential_BL0040EP WITH IDENTITY = N'GEORGES\bl0040ep', SECRET = N'EnterThePasswordHere'

        PRINT 'The credential [Credential_BL0040EP] was created!'
    END



USE [msdb]

/*
REFERENCE 
--https://dataqueen.unlimitedviz.com/2015/05/creating-a-proxy-user-to-run-an-ssis-package-in-sql-server-agent/ 
--http://sqldbatask.blogspot.com/2013/10/credentials-and-proxy-creation-script.html?_sm_au_=iVVM80kNTL4rs4Dq
*/

IF EXISTS (SELECT 1 FROM msdb.dbo.sysproxies WHERE name = 'Proxy_BL0040EP')
    BEGIN
        PRINT 'The proxy [Proxy_BL0040EP] already exists...'
    END

IF NOT EXISTS (SELECT 1 FROM msdb.dbo.sysproxies WHERE name = 'Proxy_BL0040EP')
    BEGIN
        -- Create a new proxy called SSISProxy and assign the PowerUser credentail to it
        EXEC msdb.dbo.sp_add_proxy @proxy_name=N'Proxy_BL0040EP',@credential_name=N'Credential_BL0040EP',@enabled=1

        -- Grant SSISProxy access to the "SSIS package execution" subsystem
        EXEC msdb.dbo.sp_grant_proxy_to_subsystem @proxy_name=N'Proxy_BL0040EP', @subsystem_id=11

        -- Grant the login testUser the permissions to use SSISProxy
        EXEC msdb.dbo.sp_grant_login_to_proxy @login_name = N'GEORGES\bl0040ep', @proxy_name=N'Proxy_BL0040EP'

        PRINT 'The proxy [Proxy_BL0040EP] was added!'
    END



USE [msdb]
GO

/*
REFERENCE 
--https://stackoverflow.com/questions/136771/sql-server-agent-job-exists-then-drop
*/


USE [msdb]
GO

IF EXISTS (SELECT job_id FROM msdb.dbo.sysjobs WHERE name = N'DatabaseSSASUsageStats')
    BEGIN
        PRINT 'The job [DatabaseSSASUsageStats] already exists...'
    END

IF NOT EXISTS (SELECT job_id FROM msdb.dbo.sysjobs WHERE name = N'DatabaseSSASUsageStats')
    BEGIN

        /****** Object:  Job [DatabaseSSASUsageStats]    Script Date: 2/21/2019 2:04:38 PM ******/
        BEGIN TRANSACTION
        DECLARE @ReturnCode INT
        SELECT @ReturnCode = 0
        /****** Object:  JobCategory [[Uncategorized (Local)]]    Script Date: 2/21/2019 2:04:38 PM ******/
        IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
        BEGIN
        EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
        IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

        END

        DECLARE @jobId BINARY(16)
        EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N'DatabaseSSASUsageStats', 
                @enabled=1, 
                @notify_level_eventlog=0, 
                @notify_level_email=0, 
                @notify_level_netsend=0, 
                @notify_level_page=0, 
                @delete_level=0, 
                @description=N'No description available.', 
                @category_name=N'[Uncategorized (Local)]', 
                @owner_login_name=N'GEORGES\bl0040ep', @job_id = @jobId OUTPUT
        IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
        /****** Object:  Step [SSASUsageStats]    Script Date: 2/21/2019 2:04:38 PM ******/
        EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'SSASUsageStats', 
                @step_id=1, 
                @cmdexec_success_code=0, 
                @on_success_action=1, 
                @on_success_step_id=0, 
                @on_fail_action=2, 
                @on_fail_step_id=0, 
                @retry_attempts=0, 
                @retry_interval=0, 
                @os_run_priority=0, @subsystem=N'SSIS', 
                @command=N'/ISSERVER "\"\SSISDB\IsolatedPackages\SSASUsageStats\SSASUsageStats.dtsx\"" /SERVER GCO07766 /Par "\"$ServerOption::LOGGING_LEVEL(Int16)\"";3 /Par "\"$ServerOption::SYNCHRONIZED(Boolean)\"";True /CALLERINFO SQLAGENT /REPORTING E', 
                @database_name=N'master', 
                @flags=0, 
                @proxy_name=N'Proxy_BL0040EP'
        IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
        EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
        IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
        EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'DatabaseSSASUsageStats (Hourly_0800-1700)', 
                @enabled=0, 
                @freq_type=4, 
                @freq_interval=1, 
                @freq_subday_type=4, 
                @freq_subday_interval=5, 
                @freq_relative_interval=0, 
                @freq_recurrence_factor=0, 
                @active_start_date=20190125, 
                @active_end_date=20190208, 
                @active_start_time=80000, 
                @active_end_time=170000, 
                @schedule_uid=N'6cd0bef8-9091-4e30-a0c5-5262685aeff0'
        IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
        EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)'
        IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
        COMMIT TRANSACTION
        GOTO EndSave
        QuitWithRollback:
            IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
        EndSave:

    END



GO

GO
PRINT N'Update complete.';


GO

最善のオプションは、配置後スクリプトにcreate jobステートメントを含めることです。このスレッドのソリューションのように:

SQL ServerエージェントジョブをVS SQLプロジェクトにデプロイする方法

4
analyzethat