首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当数据库联机时运行存储过程

当数据库联机时运行存储过程
EN

Stack Overflow用户
提问于 2019-03-11 11:18:10
回答 2查看 470关注 0票数 1

在2012及更高版本中,我想知道存储过程是否有可能在数据库联机时自动执行?我已经找到了文章,它展示了如何在服务器实例启动时运行存储过程,但我似乎找不到类似于数据库本身即将上线的东西。

当数据库联机时,我需要运行一个存储过程,例如,如果数据库以新名称还原,或者在备份数据库的单独服务器/实例上进行还原。我想,从技术上讲,我可以运行一个作业,定期检查任何新的数据库,但是数据库可能会被还原到一个没有安装这个作业的服务器上,所以这是个死胡同。

另一个例子是服务器重新启动时,或者数据库因任何原因脱机,然后重新联机。基本上,每当数据库联机时,我都想通过一个被触发的存储过程来了解它。

如有任何其他建议,将不胜感激。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-13 14:19:16

因此,我研究了所有可能的方法,我查看了Server Triggers:您可以:

代码语言:javascript
运行
复制
CREATE TRIGGER [TrackDBStarted] 
ON ALL SERVER
FOR CREATE_DATABASE, ALTER_DATABASE

这将使您在创建数据库时,而不是在恢复/附加数据库时,这样做是行不通的。

您可以使用Extended Events,因为它有一个database_started事件

代码语言:javascript
运行
复制
CREATE EVENT SESSION [TrackDBStarted] 
ON SERVER
ADD EVENT sqlserver.database_started
( ACTION ( sqlserver.database_name ) )

但不幸的是,您不能Target T-SQL,所以这是行不通的。

其中一种保证的方法是创建一个Startup Procedure,允许您创建一个全局Temp Table,在服务器正常运行期间不会超出范围。通过该Stored Procedure,您可以确保创建了一个Agent Job,它将每隔x时间增量检查数据库列表,并对新的Onlined数据库执行操作。这是一段很长的代码,但它会创建/查询/删除所执行的操作,希望任何人都能从中收集想法。我试着在必要的地方发表评论,但是如果你不理解其中的一些内容,我建议你先读一读。

如果有人有更好的方法做这件事,我很乐意学习。

创建

代码语言:javascript
运行
复制
USE MASTER;
GO

IF ( OBJECT_ID( N'dbo.STARTUPPROC' ) IS NOT Null )
    DROP PROCEDURE [dbo].[STARTUPPROC];
IF ( OBJECT_ID( N'dbo.CHECKDBS' ) IS NOT Null )
    DROP PROCEDURE [dbo].[CHECKDBS];
GO

/* Create the stored procedure that will check for any new databases. */
CREATE PROCEDURE [dbo].[CHECKDBS]
AS
    SET NOCOUNT ON;

    DECLARE @Database   sysname;

    DECLARE c_databases CURSOR LOCAL FOR    SELECT name FROM sys.databases 
                                            WHERE name NOT IN ( N'master', N'model', N'msdb', N'tempdb' )
                                            AND name NOT IN ( SELECT [Database] FROM ##DBList )
                                            AND state = 0;  -- Online

    OPEN c_databases;
    FETCH NEXT FROM c_databases INTO @Database;

    WHILE ( @@FETCH_STATUS = 0 )
    BEGIN
        IF ( HAS_PERMS_BY_NAME( @Database, 'DATABASE', 'ANY' ) = 1 )  
        BEGIN

            /**************************************
            *** Do database related tasks here. ***
            ***************************************/

            INSERT INTO ##DBList ( [Database] )
            VALUES ( @Database );
        END

        FETCH NEXT FROM c_databases INTO @Database;
    END

    CLOSE c_databases;
    DEALLOCATE c_databases;
GO

/* 
Create the stored procedure that will:
1. Create the temporary table so it doesn't go out of scope. 
2. Create the job that will periodically call the CHECKDBS stored procedure.
*/
CREATE PROCEDURE [dbo].[STARTUPPROC]
AS
    SET NOCOUNT ON;

    -- Create the temporary table if it doesn't already exist.
    IF ( OBJECT_ID( N'tempdb..##DBList' ) IS Null )
    BEGIN
        CREATE TABLE ##DBList
        (
            [Database]  sysname NOT NULL,                       -- Name of the database.
            PRIMARY KEY CLUSTERED 
            (
                [Database] ASC
            )
        );
    END

    DECLARE @JobName    sysname         = N'DBCheck';       -- Name of the job.
    DECLARE @ServerName nvarchar(30)    = @@SERVERNAME;     -- SQL Server on which this job will be configured.
    DECLARE @JobDate    nvarchar(8)     = CONVERT( nvarchar(8), SYSDATETIME(), 112 );   -- Job start date.
    DECLARE @Command    nvarchar(max)   = N'EXEC [dbo].[CHECKDBS]';                     -- The T-SQL command to run in the step.

    -- Check if the job exists and create it if it doesn't.
    IF NOT EXISTS ( SELECT Null FROM msdb.dbo.sysjobs WHERE name = @JobName )
    BEGIN
        -- Add the job.
        EXEC msdb.dbo.sp_add_job 
            @job_name = @JobName;

        -- Add the job step.
        -- See https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-add-jobstep-transact-sql?view=sql-server-2017
        EXEC msdb.dbo.sp_add_jobstep
            @job_name = @JobName,
            @step_name = N'Job Step',
            @subsystem = N'TSQL',
            @command = @Command;

        -- Schedule the job.
        -- See https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-add-jobschedule-transact-sql?view=sql-server-2017
        EXEC msdb.dbo.sp_add_jobschedule @job_name = @JobName,
            @name = N'Minute',                  -- Name of the job schedule.
            @enabled = 1,                       -- Will be enabled.
            @freq_type = 4,                     -- Daily.
            @freq_interval = 1,                 -- Every x days.
            @freq_subday_type = 4,              -- Minutes.
            @freq_subday_interval = 1,          -- Sub day interval.
            @freq_relative_interval = 0,        -- Only used when @freq_type = 32 so set to 0.
            @freq_recurrence_factor = 0,        -- Not used for @freq_type = 4 so set to 0.
            @active_start_date = @JobDate,      -- Date on which job execution should commence, must be greater than or equal to 19900101.
            @active_end_date = 99991231,        -- No end date.
            @active_start_time = 0,             -- Start job at 00:00:00.
            @active_end_time = 235959;          -- End job at 23:59:59.

        -- Add the job to the SQL Server.
        EXEC msdb.dbo.sp_add_jobserver
            @job_name = @JobName,
            @server_name = @ServerName;
    END
GO

/* Mark the stored proc for startup. */
IF ( OBJECT_ID( N'dbo.STARTUPPROC' ) IS NOT Null )
    AND NOT EXISTS ( SELECT Null FROM MASTER.INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = N'STARTUPPROC' AND OBJECTPROPERTY( OBJECT_ID( ROUTINE_NAME ), 'ExecIsStartup' ) = 1 )
    EXEC SP_PROCOPTION N'STARTUPPROC', 'STARTUP', 'ON';
GO

查询

代码语言:javascript
运行
复制
USE MASTER;
GO
SELECT * FROM SYS.CONFIGURATIONS WHERE NAME = N'scan for startup procs';
SELECT * FROM MASTER.INFORMATION_SCHEMA.ROUTINES WHERE SPECIFIC_NAME = N'STARTUPPROC' AND OBJECTPROPERTY( OBJECT_ID( ROUTINE_NAME ), 'ExecIsStartup' ) = 1;
SELECT * FROM msdb.dbo.sysjobs WHERE name = N'DBCheck';
SELECT * FROM sys.procedures WHERE name IN ( N'STARTUPPROC', N'CHECKDBS' );
SELECT * from tempdb.sys.objects WHERE name = N'##DBList';
GO

去除

代码语言:javascript
运行
复制
USE MASTER;
GO

-- Delete the job.
IF EXISTS ( SELECT Null FROM msdb.dbo.sysjobs WHERE name = N'DBCheck' )
    EXEC msdb.dbo.sp_delete_job @job_name = N'DBCheck';
GO

-- Remove the stored procedure and turn off the auto-startup.
IF EXISTS ( SELECT Null FROM MASTER.INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_NAME = N'STARTUPPROC' AND OBJECTPROPERTY( OBJECT_ID( ROUTINE_NAME ), 'ExecIsStartup' ) = 1 )
    EXEC SP_PROCOPTION N'STARTUPPROC', 'STARTUP', 'OFF';
GO

-- Drop the stored procedures.
IF ( OBJECT_ID( N'dbo.STARTUPPROC' ) IS NOT Null )
    DROP PROCEDURE [dbo].[STARTUPPROC];
IF ( OBJECT_ID( N'dbo.CHECKDBS' ) IS NOT Null )
    DROP PROCEDURE [dbo].[CHECKDBS];
GO

-- Drop the temporary table.
IF ( OBJECT_ID( N'tempdb..##DBList' ) IS NOT Null )
    DROP TABLE ##DBList;
GO
票数 2
EN

Stack Overflow用户

发布于 2019-03-11 11:59:41

正如我理解您的需求一样,当Server实例联机时,您正在寻找过程的执行。为此,您可以阅读下面的文章。

https://www.mssqltips.com/sqlservertip/1574/automatically-running-stored-procedures-at-sql-server-startup/

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55100669

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档