在2012及更高版本中,我想知道存储过程是否有可能在数据库联机时自动执行?我已经找到了这文章,它展示了如何在服务器实例启动时运行存储过程,但我似乎找不到类似于数据库本身即将上线的东西。
当数据库联机时,我需要运行一个存储过程,例如,如果数据库以新名称还原,或者在备份数据库的单独服务器/实例上进行还原。我想,从技术上讲,我可以运行一个作业,定期检查任何新的数据库,但是数据库可能会被还原到一个没有安装这个作业的服务器上,所以这是个死胡同。
另一个例子是服务器重新启动时,或者数据库因任何原因脱机,然后重新联机。基本上,每当数据库联机时,我都想通过一个被触发的存储过程来了解它。
如有任何其他建议,将不胜感激。
发布于 2019-03-13 14:19:16
因此,我研究了所有可能的方法,我查看了Server Triggers:您可以:
CREATE TRIGGER [TrackDBStarted]
ON ALL SERVER
FOR CREATE_DATABASE, ALTER_DATABASE这将使您在创建数据库时,而不是在恢复/附加数据库时,这样做是行不通的。
您可以使用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://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查询
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发布于 2019-03-11 11:59:41
正如我理解您的需求一样,当Server实例联机时,您正在寻找过程的执行。为此,您可以阅读下面的文章。
https://stackoverflow.com/questions/55100669
复制相似问题