web-dev-qa-db-fra.com

Quelle est la meilleure façon d'inclure des travaux de l'Agent SQL Server dans le contrôle de code source?

J'ai constaté que si je créais un script pour un travail de l'Agent SQL Server comme "créer vers", le script commençait par use msdb- donc je suppose que les travaux sont stockés dans la base de données msdb?

Quelle est la meilleure façon d'ajouter des travaux SQL Server à un projet de base de données Visual Studio? J'ai ajouté la base de données msdb à la solution de base de données, mais cela ne semble pas avoir de référence aux travaux.

Je souhaite que les emplois soient déployés/mis à jour avec une base de données ... il semble que ce ne soit pas possible?

7
Zach Smith

Je suis vraiment content que vous ayez posé cette question. J'avais ce même besoin de travaux SQL Server dans un projet de base de données Visual Studio et de déploiements de travaux avec une base de données.

Je voulais que le fichier de solution contienne tout ce qui est nécessaire pour le processus de base de données SQL que j'avais implémenté, en un seul endroit, pour Créer cette solution ET Déployer ceci solution à un serveur donné (en quelques clics). Les composants de cette solution sont:

  • Schéma de base de données
  • Package SSIS
  • Configurations SQL Server (création de base de données maître "Credential"; création msdb "Proxy"; création SQL Agent "Job").

Je voulais tout garder ensemble pour deux raisons:

  • Déploiement simplifié (SOURCE: Instance de développement local/CIBLE: Instance de développement de serveur)
  • Documentation de la solution

Je me suis donc mis à travailler pour comprendre cela. Voici ce que j'ai créé et comment j'ai trouvé cette configuration. Cela fonctionne très bien pour les fins prévues.


Aperçu:

  1. Créez les fichiers de script avec le code TSQL . J'ai utilisé la méthode CHECK FOR EXISTENCE pour éviter les erreurs où je pourrais éventuellement créer quelque chose qui existe déjà dans l'environnement.

Référence: Comment vérifier si une information d'identification existe dans une instance SQL Server?

Exemple:

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. Créez un fichier de script qui exécute les fichiers de script . Plus de détails ci-dessous.

  2. Publiez le projet de base de données , et [~ # ~] boom [~ # ~] vous venez de faire quelque chose impressionnant.


Configuration SSDT:

  1. Pluralsight: "Développement de projet DB en VS" par Robert Cain | Module: Comparaisons de données et de schémas, scripts de pré et post-déploiement

J'ai d'abord examiné cette vidéo Pluralsight utile. J'ai pu suivre, et ce que j'ai fait, c'est ...

UNE) New Folder. Créez un nouveau dossier dans le projet appelé [ScriptsPostDeployment]

B) New Script. Créez un nouveau script dans le dossier appelé [Create_SqlAgentJobs.sql].

  1. ERREUR MSG: "Vous ne pouvez avoir qu'un seul script de post-déploiement dans un projet de base de données Visual Studio"

Vous obtiendrez ce message d'erreur si vous essayez de créer plusieurs fichiers de script avec [Build Action = "Post Deploy"].

Au total, mon projet avait besoin non seulement de ce script, mais il avait également besoin d'autres scripts-- Create_SqlAgentJobs.sql, Credential_GEORGES-bl0040ep.sql, ProxyAccount_GEORGES-bl0040ep.sql. L'erreur a été discutée et résolue dans ce fil sur StackOverFlow: projet SQL Server exécutant plusieurs déploiements de script .

Au total, le nouveau dossier contient 4 scripts - 1 pour exécuter les scripts; 3 scripts qui doivent être exécutés.

ssdt-dbproj_DB-ScriptsPostDeployment.png

enter image description here


Publication SSDT:

J'ai exécuté le fichier de publication et choisi l'option "Générer le script". J'ai vu le script et ... POST DEPLOYMENT a été automatiquement inséré pour ajouter le JOB AGENT SQL !! Succès! Voici le script et les messages d'exécution du script après avoir exécuté la requête sur l'instance SQL dans 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
6
SherlockSpreadsheets

Je pense que la meilleure option est d'inclure l'instruction create job dans un script de post-déploiement. Comme la solution dans ce fil:

Comment déployer un Job Agent SQL Server dans un projet VS SQL?

4
analyzethat