SET QUOTED_IDENTIFIER ON GO SET ANSI_NULLS ON GO if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[adminLoadScripts]') and OBJECTPROPERTY(id, N'IsProcedure') = 1) drop procedure [dbo].[adminLoadScripts] GO create procedure dbo.adminLoadScripts @pServerName varchar(60), @pDatabaseName varchar(30), @pCollection varchar(30) as /**************************************************************************** Loads all scripts found from the local working folder defined by @scriptgroup of the specified server and database into that database on the local system. Notes: Both the local server and the specified server must be member servers in the project that owns the database and bothe servers must already be added to the local dbChangeControl metadata hierarchy. Will ot work for scripts located directly in the database's named folder (i.e. Admin\admin.sql) *****************************************************************************/ declare @cmd nvarchar(1200), @returnstatus int, @procedureName varchar(100), @serverName varchar(50), @instanceName varchar(50), @workingFolder varchar(255), @vssHierarchy varchar(255), @vssShare varchar(255), @vssUserName varchar(30), @fileName varchar(255), @rowcount int set nocount on set @procedureName = db_name() + '.' + user_name(objectproperty(@@procid,'OwnerId')) + '.' + object_name(@@procid) set @serverName = reverse(substring(reverse(@pServername), charindex('\',reverse(@pServername)) + 1, datalength(reverse(@pServername)))) set @instanceName = substring(@pServername, charindex('\',@pServername) + 1, datalength(@pServername)) -- get file system path select @workingFolder = s.workingFolderRoot + p.projectName + '\' + e.environmentName + '\' + s.serverName + '\' + s.instanceName + '\' + @pDatabaseName + '\' + @pCollection + '\', @vssUserName = n.vssUserName from Admin.dbo.SqlDatabase d inner join Admin.dbo.ProjectNode n on d.id = n.sqlDatabase_id inner join Admin.dbo.SqlServer s on s.id = n.sqlServer_id inner join Admin.dbo.Environment e on e.id = n.environment_id inner join Admin.dbo.Project p on p.id = n.project_id inner join Admin.dbo.ProjectNode l -- local on ( n.project_id = l.project_id and n.sqlDatabase_id = l.sqlDatabase_id) where d.databaseName = @pDatabaseName and s.serverName = @serverName and s.instanceName = @instanceName and n.IsActive = 1 --and l.sqlServer_id = Admin.dbo.thisSQLServer_id() cannot use function in SQL Server 7 and l.sqlServer_id = (select id from Admin.dbo.SqlServer where serverName = reverse(substring(reverse(@@servername), charindex('\',reverse(@@servername)) + 1, datalength(reverse(@@servername)))) and instanceName = substring(@@servername, charindex('\',@@servername) + 1, datalength(@@servername))) and l.IsActive = 1 -- valid project node must exist if @@rowcount = 0 begin raiserror(59002,16,1,@procedureName,@pDatabaseName) goto ErrorHandler end -- wrong user asking if substring(system_user,charindex('\', system_user) + 1, datalength(system_user)) <> @vssUserName begin set @vssUserName = substring(system_user,charindex('\', system_user) + 1, datalength(system_user)) raiserror (59005,16,1, @procedurename, @vssUserName, @vssShare) goto ErrorHandler end -- file system working folder for the database must exist set @cmd = 'dir ' + @workingFolder exec @returnstatus = master.dbo.xp_cmdshell @CMD, no_output if @returnstatus <> 0 begin raiserror (59007,16,1,@procedureName, @WorkingFolder,@@servername) goto ErrorHandler end -- vss project must exist - must be created by vss admin -- NOTE! if you put a password on vss, this will hang (tries to prompt for password) set @cmd = @vssShare + 'win32\ss Cp ' + @vssHierarchy + ' -I-N -Y' + @vssUserName exec @returnstatus = master.dbo.xp_cmdshell @cmd, no_output if @returnstatus <> 0 begin raiserror(59008,16,1,@procedureName, @vssHierarchy, @vssShare) goto ErrorHandler end -- see if any files are checked out in this project set @Cmd = @vssShare + 'win32\ss Status ' + @vssHierarchy + '\ -I-N -R -Y' + @vssUSerName exec @returnstatus = master..xp_cmdshell @Cmd, NO_OUTPUT if @returnstatus <> 0 begin if @returnstatus = 1 raiserror(59010,16,1,@procedureName, @vssHierarchy) else -- something else must have happened goto ErrorHandler end -- get list of all files in the working folder create table #fileList (fileName varchar(255)) set @Cmd = 'dir ' + @WorkingFolder + ' /A /B' insert #fileList exec @returnstatus = master.dbo.xp_cmdshell @Cmd if @returnstatus <> 0 goto ErrorHandler -- a little clean up of the list delete #fileList where fileName not like '%.sql' or fileName is null update #fileList set FileName = reverse(substring(reverse(fileName), 1, datalength(filename) - charindex('\',reverse(fileName)))) -- run all scripts and log the results to a file declare cur cursor for select FileName from #fileList open cur fetch next from cur into @fileName while @@fetch_status = 0 begin print 'echo processing script ' + @fileName +'...' set @Cmd = 'osql -E -S ' + @@servername + ' -d' + @pDatabaseName + ' -i"' + @workingFolder + @fileName + '" -b -n' exec @returnstatus = master.dbo.xp_cmdshell @Cmd, no_output if @returnstatus <> 0 begin -- try again and dump errors to screen exec @returnstatus = master.dbo.xp_cmdshell @Cmd--, no_output if @returnstatus = 1 --audit insert Admin.dbo.ActivityLog (activity) select @procedureName + ' ' + @pDatabaseName + 'attempt to run script ' + @fileName + ' failed with returnstatus ' + cast(@returnstatus as varchar(10)) + ' at: ' + @cmd end fetch next from cur into @FileName end drop table #FileList close cur deallocate cur return ErrorHandler: if (@Cmd is not null) begin -- audit insert Admin.dbo.ActivityLog (activity) select @procedureName + ' ' + @pDatabaseName + ' failed with returnstatus ' + cast(@returnstatus as varchar(10)) + ' at: ' + @cmd raiserror(59001,16,1,@procedureName) end else raiserror(59000,16,1,@procedureName) if (cursor_status('local','cur') >= 0) deallocate cur return -1 GO SET QUOTED_IDENTIFIER OFF GO SET ANSI_NULLS ON GO