category_class INT NOT NULL, -- 1 = Job, 2 = Alert, 3 = Operator
category_type TINYINT NOT NULL, -- 1 = Local, 2 = Multi-Server [Only relevant if class is 1; otherwise, 3 (None)]
name sysname NOT NULL
)
CREATE UNIQUE CLUSTERED INDEX clust ON syscategories(name, category_class)
END
go
-- Install standard [permanent] categories (reserved ID range is 0 - 99)
SET IDENTITY_INSERT msdb.dbo.syscategories ON
DELETE FROM msdb.dbo.syscategories
WHERE (category_id < 100)
-- Core categories
INSERT INTO msdb.dbo.syscategories (category_id, category_class, category_type, name) VALUES ( 0, 1, 1, N'[Uncategorized (Local)]') -- Local default
INSERT INTO msdb.dbo.syscategories (category_id, category_class, category_type, name) VALUES ( 1, 1, 1, N'Jobs from MSX') -- All jobs downloaded from the MSX are placed in this category
INSERT INTO msdb.dbo.syscategories (category_id, category_class, category_type, name) VALUES ( 3, 1, 1, N'Database Maintenance') -- Default for all jobs created by the Maintenance Plan Wizard
INSERT INTO msdb.dbo.syscategories (category_id, category_class, category_type, name) VALUES ( 4, 1, 1, N'Web Assistant') -- Default for all jobs created by the Web Assistant
INSERT INTO msdb.dbo.syscategories (category_id, category_class, category_type, name) VALUES ( 5, 1, 1, N'Full-Text') -- Default for all jobs created by the Index Server
IF EXISTS (SELECT * FROM master.dbo.sysmessages WHERE (error = @error) AND (msglangid = (SELECT msglangid FROM master.dbo.syslanguages WHERE (langid = @@langid))))
SELECT description FROM master.dbo.sysmessages WHERE (error = @error) AND (msglangid = (SELECT msglangid FROM master.dbo.syslanguages WHERE (langid = @@langid)))
ELSE
SELECT description FROM master.dbo.sysmessages WHERE (error = @error) AND (msglangid = 1033)
@sqlagent_starting_test VARCHAR(7) = 'TEST' -- By default we DO want to test if SQLServerAgent is running (caller should specify 'NO_TEST' if not desired)
AS
BEGIN
DECLARE @retval INT
DECLARE @job_id_as_char VARCHAR(36)
SET NOCOUNT ON
-- Remove any leading/trailing spaces from parameters
IF (@retval <> 0) OR (@local_machine_name IS NULL)
BEGIN
RAISERROR(14225, -1, -1)
RETURN(1)
END
CREATE TABLE #target_servers (server_name sysname COLLATE database_default NOT NULL)
-- Optimization: Simply update the date-posted if the operation has already been posted (but
-- not yet downloaded) and the target server is not currently polling...
IF ((@object_type = 'JOB') AND (ISNULL(@job_id, 0x00) <> CONVERT(UNIQUEIDENTIFIER, 0x00)) AND (@operation_code IN (1, 2, 3, 4, 5))) OR -- Any JOB operation
((@object_type = 'SERVER') AND (@operation_code IN (6, 7))) -- RE-ENLIST or DEFECT operations
BEGIN
-- Populate the list of target servers to post to
IF (@specific_target_server IS NOT NULL)
INSERT INTO #target_servers VALUES (@specific_target_server)
ELSE
BEGIN
IF (@object_type = 'SERVER')
INSERT INTO #target_servers
SELECT server_name
FROM msdb.dbo.systargetservers
IF (@object_type = 'JOB')
INSERT INTO #target_servers
SELECT sts.server_name
FROM msdb.dbo.sysjobs_view sjv,
msdb.dbo.sysjobservers sjs,
msdb.dbo.systargetservers sts
WHERE (sjv.job_id = @job_id)
AND (sjv.job_id = sjs.job_id)
AND (sjs.server_id = sts.server_id)
AND (sjs.server_id <> 0)
END
IF (EXISTS (SELECT *
FROM #target_servers))
BEGIN
DECLARE @target_server sysname
DECLARE @optimized BIT
SELECT @optimized = 1
DECLARE targets_to_post_to CURSOR LOCAL
FOR
SELECT server_name
FROM #target_servers
OPEN targets_to_post_to
FETCH NEXT FROM targets_to_post_to INTO @target_server
-- Optimizing is an all-or-nothing thing, so we do the updates inside a transaction so
-- that we can rollback if necessary
BEGIN TRANSACTION
SAVE TRANSACTION start
WHILE (@@fetch_status = 0)
BEGIN
IF (EXISTS (SELECT *
FROM msdb.dbo.sysdownloadlist
WHERE (target_server = @target_server)
AND (operation_code = @operation_code)
AND (object_id = ISNULL(@job_id, CONVERT(UNIQUEIDENTIFIER, 0x00)))
AND (status = 0))) AND
(NOT EXISTS (SELECT *
FROM master.dbo.sysprocesses
WHERE (loginame = @target_server + N'_msx_probe')))
BEGIN
UPDATE msdb.dbo.sysdownloadlist
SET date_posted = GETDATE()
WHERE (target_server = @target_server)
AND (operation_code = @operation_code)
AND (object_id = ISNULL(@job_id, CONVERT(UNIQUEIDENTIFIER, 0x00)))
AND (status = 0)
END
ELSE
BEGIN
SELECT @optimized = 0
BREAK
END
FETCH NEXT FROM targets_to_post_to INTO @target_server
WHEN (sdl.operation_code >= 1) AND (sdl.operation_code <= 5) AND (sdl.object_id = CONVERT(UNIQUEIDENTIFIER, 0x00)) THEN FORMATMESSAGE(14212) -- '(all jobs)'
WHEN (sdl.operation_code = 3) AND (sdl.object_id <> CONVERT(UNIQUEIDENTIFIER, 0x00)) THEN sdl.deleted_object_name -- Special case handling for a deleted job
WHEN (sdl.operation_code >= 1) AND (sdl.operation_code <= 5) AND (sdl.object_id <> CONVERT(UNIQUEIDENTIFIER, 0x00)) THEN FORMATMESSAGE(14580) -- 'job' (safety belt: should never appear)
WHEN (sdl.operation_code >= 6) AND (sdl.operation_code <= 9) THEN sdl.target_server
ELSE FORMATMESSAGE(14205)
END),
'object_id' = ISNULL(sjv.job_id, CASE sdl.object_id
WHEN CONVERT(UNIQUEIDENTIFIER, 0x00) THEN CONVERT(UNIQUEIDENTIFIER, 0x00)
ELSE sdl.object_id
END),
sdl.target_server,
sdl.error_message,
sdl.date_posted,
sdl.date_downloaded,
sdl.status
FROM msdb.dbo.sysdownloadlist sdl LEFT OUTER JOIN
msdb.dbo.sysjobs_view sjv ON (sdl.object_id = sjv.job_id)
WHERE ((@operation_code IS NULL) OR (operation_code = @operation_code))
AND ((@object_type_id IS NULL) OR (object_type = @object_type_id))
AND ((@job_id IS NULL) OR (object_id = @job_id))
AND ((@target_server IS NULL) OR (target_server = @target_server))
AND ((@has_error IS NULL) OR (DATALENGTH(error_message) >= 1 * @has_error))
AND ((@status IS NULL) OR (status = @status))
AND ((@date_posted IS NULL) OR (date_posted >= @date_posted))
FETCH NEXT FROM all_subsystems INTO @subsystem, @part
END
DEALLOCATE all_subsystems
UPDATE #sp_enum_ss_temp SET description = FORMATMESSAGE(14550)
WHERE (subsystem = N'CmdExec')
UPDATE #sp_enum_ss_temp SET description = FORMATMESSAGE(14551)
WHERE (subsystem = N'Snapshot')
UPDATE #sp_enum_ss_temp SET description = FORMATMESSAGE(14552)
WHERE (subsystem = N'LogReader')
UPDATE #sp_enum_ss_temp SET description = FORMATMESSAGE(14553)
WHERE (subsystem = N'Distribution')
UPDATE #sp_enum_ss_temp SET description = FORMATMESSAGE(14554)
WHERE (subsystem = N'Merge')
UPDATE #sp_enum_ss_temp SET description = FORMATMESSAGE(14555)
WHERE (subsystem = N'ActiveScripting')
UPDATE #sp_enum_ss_temp SET description = FORMATMESSAGE(14581)
WHERE (subsystem = N'QueueReader')
-- 'TSQL' is always available (since it's a built-in subsystem), so we explicity add it
-- to the result set
IF (NOT EXISTS (SELECT *
FROM #sp_enum_ss_temp
WHERE (subsystem = N'TSQL')))
INSERT INTO #sp_enum_ss_temp VALUES (N'TSQL', FORMATMESSAGE(14556), FORMATMESSAGE(14557), FORMATMESSAGE(14557), FORMATMESSAGE(14557), FORMATMESSAGE(14557), FORMATMESSAGE(14557), CASE (PLATFORM() & 0x2) WHEN 0x2 THEN 10 ELSE 20 END) -- Worker thread rule should match DEF_REG_MAX_TSQL_WORKER_THREADS
SELECT @schedule_description = N'Every ' + CONVERT(NVARCHAR, @freq_recurrence_factor) + N' months(s) on day ' + CONVERT(NVARCHAR, @freq_interval) + N' of that month '
END
IF (@freq_type = 0x20) -- Monthly Relative
BEGIN
SELECT @schedule_description = N'Every ' + CONVERT(NVARCHAR, @freq_recurrence_factor) + N' months(s) on the '
IF ((UPPER(@originating_server) = UPPER(CONVERT(NVARCHAR(30), SERVERPROPERTY('ServerName')))) OR (UPPER(@originating_server) = UPPER(@local_machine_name)))
IF ((@current_msx_server IS NOT NULL) AND (@current_msx_server <> N'') AND (@originating_server <> @current_msx_server))
RAISERROR(14224, 0, 1, @current_msx_server)
END
-- Check authority (only SQLServerAgent can delete a non-local job)
IF (((@originating_server IS NOT NULL) AND (@originating_server <> UPPER(CONVERT(NVARCHAR(30), SERVERPROPERTY('ServerName'))))) OR (@bMSX_job = 1)) AND
(PROGRAM_NAME() NOT LIKE N'SQLAgent%')
BEGIN
RAISERROR(14274, -1, -1)
RETURN(1) -- Failure
END
CREATE TABLE #temp_jobs_to_delete (job_id UNIQUEIDENTIFIER NOT NULL, job_is_cached INT NOT NULL)
-- Do the delete (for a specific job)
IF (@job_id IS NOT NULL)
BEGIN
INSERT INTO #temp_jobs_to_delete
SELECT job_id, (SELECT COUNT(*)
FROM msdb.dbo.sysjobservers
WHERE (job_id = @job_id)
AND (server_id = 0))
FROM msdb.dbo.sysjobs_view
WHERE (job_id = @job_id)
-- Check if we have any work to do
IF (NOT EXISTS (SELECT *
FROM #temp_jobs_to_delete))
RETURN(0) -- Success
-- Post the delete to any target servers (need to do this BEFORE deleting the job itself,
-- but AFTER clearing all all pending download instructions). Note that if the job is
-- NOT a multi-server job then sp_post_msx_operation will catch this and will do nothing.
IF (EXISTS (SELECT * from msdb.dbo.sysobjects WHERE name = N'sp_add_log_shipping_primary' AND type = N'P'))
drop procedure sp_add_log_shipping_primary
go
CREATE PROCEDURE sp_add_log_shipping_primary
@primary_server_name sysname,
@primary_database_name sysname,
@maintenance_plan_id UNIQUEIDENTIFIER = NULL,
@backup_threshold INT = 60,
@threshold_alert INT = 14420,
@threshold_alert_enabled BIT = 1,
@planned_outage_start_time INT = 0,
@planned_outage_end_time INT = 0,
@planned_outage_weekday_mask INT = 0,
@primary_id INT = NULL OUTPUT
AS
BEGIN
SET NOCOUNT ON
IF EXISTS (SELECT * FROM msdb.dbo.log_shipping_primaries WHERE primary_server_name = @primary_server_name AND primary_database_name = @primary_database_name)
IF (NOT EXISTS (SELECT * FROM msdb.dbo.log_shipping_primaries WHERE primary_server_name = @primary_server_name AND primary_database_name = @primary_database_name))
IF (NOT EXISTS (SELECT * FROM msdb.dbo.log_shipping_secondaries WHERE secondary_server_name = @secondary_server_name AND secondary_database_name = @secondary_database_name))
IF (NOT EXISTS (SELECT * FROM msdb.dbo.log_shipping_primaries WHERE primary_server_name = @primary_server_name AND primary_database_name = @primary_database_name))
IF (NOT EXISTS (SELECT * FROM msdb.dbo.log_shipping_secondaries WHERE secondary_server_name = @secondary_server_name AND secondary_database_name = @secondary_database_name))
DELETE FROM msdb.dbo.log_shipping_secondaries WHERE secondary_server_name = @secondary_server_name AND secondary_database_name = @secondary_database_name
IF (@@error <> 0)
goto rollback_quit
-- if there are no more secondaries for this primary then delete it
IF (NOT EXISTS (SELECT * FROM msdb.dbo.log_shipping_primaries p, msdb.dbo.log_shipping_secondaries s WHERE p.primary_id = s.primary_id AND primary_server_name = @primary_server_name AND primary_database_name = @primary_database_name))
BEGIN
DELETE FROM msdb.dbo.log_shipping_primaries WHERE primary_server_name = @primary_server_name AND primary_database_name = @primary_database_name