我試圖改變我們的SQL環境中用於遠程創建備份作業的存儲過程。下面是程序動態查詢語法錯誤
/****** Object: StoredProcedure [dbo].[CreateBackupJobGroupBFull] Script Date: 8/06/2016 3:18:25 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[CreateBackupJobGroupAFull]
(@servername nvarchar(100))
AS
declare @commandstr nvarchar(max)
DECLARE @SQL nvarchar(4000)
DECLARE @TableExists bit
DECLARE @recp nvarchar(100)
DECLARE @error_msg varchar(300)
declare @groupAfull nvarchar(150)
declare @schedulestr nvarchar(150)
DECLARE @pripathstr VARCHAR(1256)
DECLARE @secpathstr VARCHAR(1256)
declare @defaultscheduleStart varchar(30)
declare @gstr varchar(5)
declare @g varchar(1)
set @groupAfull = 'DBABackupJobGroupA_Full'
set @recp = '**************'
set @defaultscheduleStart = '230000'
set @gstr = '_GA_F'
set @g = 'A'
SET @SQL = 'SELECT @TableExists = CASE WHEN TableExists = 0 THEN 0 ELSE 1 END
FROM OPENQUERY(' + QUOTENAME(@servername)
+ ', ''SELECT TableExists = COUNT(*)
from msdb.dbo.sysjobs
WHERE name = '''' + @groupAfull + '''''');';
begin try
EXECUTE sp_executesql @SQL, N'@TableExists BIT OUTPUT', @TableExists OUT;
END TRY
BEGIN CATCH
print 'error message is:'
print error_message()
set @error_msg='Error occurred when executing CreatBackupJob against server ' + @ServerName + '. Failed to check control table locally. The error message is: ' + error_message()
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'Internal mail',
@recipients = @recp,
@body = @error_msg ,
@subject = 'Error occurred on reporting server' ;
END CATCH
IF (@TableExists = 0)
BEGIN
--add new job for the instance
set @sql = 'if not exists (select * from [' + @ServerName + '].msdb.dbo.sysjobs where name = ''' + @groupAfull + ''')
BEGIN
EXEC [' + @ServerName + '].msdb.dbo.sp_add_job
@job_name = ''' + @groupAfull + ''',
@enabled = 1,
@description = N''DBA backup job. DO NOT REMOVE. V1.5 (2015-06-16)'',
@owner_login_name = N''sa''
EXEC [' + @ServerName + '].msdb.dbo.sp_add_jobserver
@job_name = ''' + @groupAfull + ''',
@server_name = ''(local)''
end
'
begin try
EXEC sp_executeSQL @sql
END TRY
BEGIN CATCH
print 'error message is:'
print error_message()
set @error_msg='Error occurred when executing CreatBackupJob against server ' + @ServerName + '. Failed to create new job'+ @groupAfull +'. The error message is: ' + error_message()
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'Internal mail',
@recipients = @recp,
@body = @error_msg ,
@subject = 'Error occurred on reporting server' ;
END CATCH
SET @pripathstr = (SELECT Top 1 [PrimDestinationfull] FROM [SQLADMIN].[dbo].[BackupDestination])
SET @secpathstr = (SELECT Top 1 [SecDestinationfull] FROM [SQLADMIN].[dbo].[BackupDestination])
--add job step 1 'test'
set @commandstr = '
DECLARE @dbname VARCHAR(150) -- database name
DECLARE @pripath VARCHAR(1256) -- path for backup files
DECLARE @secpath VARCHAR(1256) -- path for backup files
DECLARE @path VARCHAR(1256) -- path for backup files
DECLARE @fileName VARCHAR(1256) -- filename for backup
DECLARE @fileDate VARCHAR(40) -- used for file name
DECLARE @DBGROUP varchar(1)
DECLARE @filecount int
DECLARE @lastbackuptime datetime
SET @DBGROUP = ''''' + @g + '''''
IF not EXISTS (SELECT [name] FROM msdb.sys.tables WHERE [name] = ''''DBBackupControlTbl'''' )
begin
raiserror(''''Control table not found!'''', 20, -1) with log
return
end
else
if (select count(*) from msdb.dbo.DBBackupControlTbl where BackupGroup = @DBGROUP) > 0
-- specify database backup directory
SET @pripath = ''''' + @pripathstr + '''''
SET @secpath = ''''' + @secpathstr + '''''
if object_id(''''tempdb.dbo.#fileExist'''') is not null
drop table #fileExist
create table #fileExist (
fileExists int,
fileIsDir int,
parentDirExists int
)
insert into #fileExist
exec xp_fileexist @pripath
if object_id(''''tempdb.dbo.#fileExist2'''') is not null
drop table #fileExist2
create table #fileExist2 (
fileExists int,
fileIsDir int,
parentDirExists int
)
insert into #fileExist2
exec xp_fileexist @secpath
if (select count(*) from #fileExist where fileIsDir = 1) > 0
begin
set @path = @pripath
end
ELSE
begin
if (select count(*) from #fileExist2 where fileIsDir = 1) > 0
begin
set @path = @secpath
end
ELSE
begin
raiserror(''''None of the backup directory can be accessed at the moment!'''', 20, -1) with log
return
end
end
set @filecount = 999
while @filecount >= 15
begin
IF OBJECT_ID(''''tempdb..#DirectoryTree'''') IS NOT NULL
DROP TABLE #DirectoryTree;
CREATE TABLE #DirectoryTree (
id int IDENTITY(1,1)
,subdirectory nvarchar(512)
,depth int
,isfile bit);
INSERT #DirectoryTree (subdirectory,depth,isfile)
EXEC master.sys.xp_dirtree @path,1,1;
select @filecount = COUNT(*) FROM #DirectoryTree
WHERE isfile = 1 AND RIGHT(subdirectory,4) = ''''.sts''''
if @filecount >= 15
begin
print ''''Wait for status file to be cleared.''''
waitfor delay ''''00:00:10''''
end
else
begin
print ''''Backing up now.''''
DECLARE @statusfile AS VARCHAR(150)
DECLARE @cmd AS VARCHAR(150)
-- specify filename format
SELECT @fileDate = replace(replace(CONVERT(VARCHAR(40),GETDATE(),120), '''':'''', ''''-''''), '''' '''', ''''T'''')
set @statusfile = @path + replace(@@SERVERNAME, ''''\'''', ''''-'''') + ''''_'''' + @fileDate + '''''+ @gstr + ''''' + ''''.STS''''
set @cmd = ''''echo '''' + @filedate + '''' > '''' + @statusfile
EXECUTE Master.dbo.xp_CmdShell @Cmd
DECLARE db_cursor CURSOR FOR
select databasename from msdb.dbo.DBBackupControlTbl where BackupGroup = @DBGROUP
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @dbname
WHILE @@FETCH_STATUS = 0
BEGIN
SET @fileName = @path + replace(@@SERVERNAME, ''''\'''', ''''-'''') + ''''_'''' + @dbname + ''''_'''' + @fileDate + '''''+ @gstr + ''''' + ''''.BAK''''
BACKUP DATABASE @dbname TO DISK = @fileName
FETCH NEXT FROM db_cursor INTO @dbname
END
CLOSE db_cursor
DEALLOCATE db_cursor
set @cmd = ''''del '''' + @statusfile
EXECUTE Master.dbo.xp_CmdShell @Cmd
end
continue
end
'
print @commandstr
set @sql = 'if not exists (select * from [' + @ServerName + '].msdb.dbo.sysjobsteps where step_name = ''' + @groupAfull + ''')
BEGIN
EXEC [' + @ServerName + '].msdb.dbo.sp_add_jobstep
@job_name = ''' + @groupAfull + ''',
@step_name = ''' + @groupAfull + ''',
@subsystem = N''TSQL'',
@command = N''' + @commandstr + ''',
@retry_attempts = 3,
@retry_interval = 1,
@on_success_action = 1 ,
@on_fail_action= 2;
end
'
begin try
EXEC sp_executeSQL @sql
END TRY
BEGIN CATCH
print 'error message is:'
print error_message()
set @error_msg='Error occurred when executing CreatBackupJob against server ' + @ServerName + '. Failed to create new job step '+ @groupAfull +'. The error message is: ' + error_message()
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'Internal mail',
@recipients = @recp,
@body = @error_msg ,
@subject = 'Error occurred on reporting server' ;
END CATCH
--add the schedule
set @schedulestr = @groupAfull + '_Schedule'
set @sql = 'if not exists (select * from [' + @ServerName + '].msdb.dbo.sysschedules where name = ''' + @schedulestr + ''')
BEGIN
EXEC [' + @ServerName + '].msdb.dbo.sp_add_schedule
@schedule_name = ''' + @schedulestr + ''',
@enabled=1,
@freq_type=4,
@freq_interval=1,
@freq_subday_type=1,
@freq_subday_interval=0,
@freq_relative_interval=0,
@freq_recurrence_factor=1,
@active_start_date=20140819,
@active_end_date=99991231,
@active_start_time= '+ @defaultscheduleStart +',
@active_end_time=235959
end
'
--print @sql
begin try
EXEC sp_executeSQL @sql
END TRY
BEGIN CATCH
print 'error message is:'
print error_message()
set @error_msg='Error occurred when executing CreatBackupJob against server ' + @ServerName + '. Failed to create new job schedule '+ @groupAfull +'. The error message is: ' + error_message()
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'Internal mail',
@recipients = @recp,
@body = @error_msg ,
@subject = 'Error occurred on reporting server' ;
END CATCH
--attach the schedule
set @sql = 'EXEC [' + @ServerName + '].msdb.dbo.sp_attach_schedule
@job_name = ''' + @groupAfull + ''',
@schedule_name = ''' + @schedulestr + '''
'
begin try
EXEC sp_executeSQL @sql
END TRY
BEGIN CATCH
print 'error message is:'
print error_message()
set @error_msg='Error occurred when executing CreatBackupJob against server ' + @ServerName + '. Failed to attach the schedule to the job '+ @groupAfull +'. The error message is: ' + error_message()
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'Internal mail',
@recipients = @recp,
@body = @error_msg ,
@subject = 'Error occurred on reporting server' ;
END CATCH
end
GO
與3個重創建,因此,如果備份失敗就退休,然後再次無關備份所有的數據庫,在那裏失敗創建工作。我正在嘗試更改該過程,以便在作業失敗時爲運行失敗的數據庫運行備份。我寫了下面的代碼來替換備份數據庫的位置。
*@lastbackuptime is declared
BEGIN
SET @lastbackuptime = (select max(backup_finish_date) from msdb.dbo.backupset where [email protected] and type=''''D'''')
if (Select datediff(hour,@lastbackuptime,getdate()))> 18
Begin
SET @fileName = @path + replace(@@SERVERNAME, ''''\'''', ''''-'''') + ''''_'''' + @dbname + ''''_'''' + @fileDate + '''''+ @gstr + ''''' + ''''.BAK''''
BACKUP DATABASE @dbname TO DISK = @fileName
End
else
Begin
Print ''''Backup exists for database ''''
End
FETCH NEXT FROM db_cursor INTO @dbname
END
當我從作業步驟進行此更改時,查詢解析正常並且作業正常運行。但是,當我把這個過程中,並嘗試遠程創建作業失敗,語法錯誤。因爲它是動態的SQL它不提供任何線索在哪裏是語法錯誤。
將是巨大的,如果有人能發現它。
的問候中,「動態SQL不工作」 希德
調試時動態SQL它來執行它之前打印結果字符串的關鍵。長字符串可以通過PRINT命令截斷,因此您需要使用解決方法:http://stackoverflow.com/questions/7850477/how-to-print-varcharmax-using-print-statement。一旦你得到完整的字符串打印檢查它的語法錯誤並運行它。修復動態SQL生成器代碼中的錯誤並沖洗並重復。 – Alex