在Microsoft SQL Server 2012及更高版本中,我想知道当数据库联机时,存储过程是否可以自动执行?我发现this文章展示了如何在服务器实例启动时运行存储过程,但我似乎找不到类似于数据库本身上线的东西。
我需要在数据库联机时运行存储过程,例如,如果数据库是以新名称还原,或者是在备份它的单独服务器/实例上。我想我可以在技术上运行一个定期检查任何新数据库的工作,但数据库可能会恢复到没有安装此工作的服务器上,这有点死路一条。
另一个例子是服务器重新启动,或者数据库因任何原因脱机然后重新联机。从本质上讲,任何时候数据库上线我想通过被解雇的存储过程来了解它。
任何其他建议将不胜感激。
所以我经历了一切可能的方式,我看着Server Triggers
:你可以这样做:
CREATE TRIGGER [TrackDBStarted]
ON ALL SERVER
FOR CREATE_DATABASE, ALTER_DATABASE
这将在创建数据库时为您提供,但在RESTORED / ATTACHED时则不会为您提供,这样就无法工作。
您可以使用Extended Events
,因为它是database_started
的事件:
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
数据库执行操作。这是一段冗长的代码,但它创建/查询/删除所执行的操作,这样任何人都可以从中收集想法。我试图在必要时发表评论,但如果你不理解某些项目,我建议先阅读一下。
如果有人有更好的方法,我会很乐意学习。
创建
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://docs.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://docs.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
QUERY
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
拆除
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
据我了解您的要求,您正在寻找SQL Server实例联机时执行的过程。为此你可以通过下面的文章。