So, an unsupported workaround, pointed out to me by Erland Sommarskog, SQL MVP & SQL God:
EXEC sp_MS_marksystemobject [your_sp_name]
Put butter in your mixer, add sugar, set on low. Write a stored procedure to keep track of jobs that won't run. Add flour. Use a DMV to find unused indexes. Add eggs. Bake in an MDF with 20% free space.
EXEC sp_MS_marksystemobject [your_sp_name]
SELECT * FROM sys.dm_exec_procedure_stats
EXEC sys.sp_refreshsqlmodule 'dbo.MyProcFnOrView'
foreach ($svr in get-content "C:\MyInstances.txt"){
$svr
invoke-expression "SQLCMD -E -S $svr -i createMyuser.sql"
}
foreach ($svr in (sqlcmd /Lc))
{
$svr
invoke-expression "SQLCMD -E -S $svr -i c:\simplemodel.sql"
}
exec sp_MSforeachtable "DBCC DBREINDEX ('?')"
EXEC sp_MSforeachtable "print '?' DBCC DBREINDEX ('?', ' ', 85)"
EXEC sp_MSforeachtable "update STATISTICS ?"
sp_updatestats
DECLARE @backup_directory VARCHAR(500), @Verified VARCHAR(100), @full_backup_name VARCHAR(600),
@database_name sysname, @restore_directory VARCHAR(500),
@logical_name_log VARCHAR(50), @physical_name_log VARCHAR(50),
@logical_name_data VARCHAR(50), @physical_name_data VARCHAR(50)
,@with_data VARCHAR(200), @with_log VARCHAR(200)
---------------------------------------------------------------------
--put the name of the folder with the backup you want restored here--
---------------------------------------------------------------------
SET @backup_directory = '\\servername\share\databasefolderbackup'
IF RIGHT(@backup_directory, 1) <> '\'
SET @backup_directory = @backup_directory + '\'
IF EXISTS
(
SELECT * FROM dbo.sysobjects
WHERE id = OBJECT_ID(N'tempdb.[dbo].[#listing]')
AND OBJECTPROPERTY(id, N'IsUserTable') = 1
)
DROP TABLE #Listing
create table #Listing
(resultant nvarchar (255))
--Find the backups in the given folder
declare @dirlist varchar(500)
select @dirlist = 'exec master..xp_cmdshell ''dir /b "'+ @backup_directory + '*"'''
insert #Listing exec (@dirlist)
--get the most recent
select @Verified = MAX(resultant) from #listing WHERE resultant LIKE '%.bak'
DROP TABLE #Listing
--get a list of all logical files within the backup so we can restore with the right data
SELECT @full_backup_name = @backup_directory + @Verified
if object_id('tempdb..#database_details') is not null
DROP TABLE #database_details
CREATE TABLE #database_details
(
LogicalName sysname,
PhysicalName varchar(500),
[TYPE] VARCHAR(2),
FileGroupName varchar(50),
[Size] VARCHAR(50),
[MaxSize] VARCHAR(50))
INSERT INTO #database_details
EXEC MASTER..xp_restore_filelistonly @filename = @full_backup_name
--get the names of everything.
SELECT @logical_name_data = LogicalName, @physical_name_data = PhysicalName
FROM #database_details WHERE [TYPE] = 'D'
SELECT @logical_name_log = LogicalName, @physical_name_log = PhysicalName
FROM #database_details WHERE [TYPE] = 'L'
SELECT @database_name = @logical_name_data
--set up the folders where the restore will automatically go.
SELECT @physical_name_data = CASE
WHEN @logical_name_data LIKE '2009%' THEN 'L:\2009\'
WHEN @logical_name_data LIKE '2008%' THEN 'M:\2008\'
ELSE 'not known'
END
+ right(@physical_name_data, CHARINDEX('\', reverse(@physical_name_data))-1)
SELECT @physical_name_log = CASE
WHEN @logical_name_data LIKE '2009%' THEN 'L:\2009_Logs\'
WHEN @logical_name_data LIKE '2008%' THEN 'M:\2008_Logs\'
ELSE 'not known'
END
+ right(@physical_name_log, CHARINDEX('\', reverse(@physical_name_log))-1)
--need to set these separately since you can't call within the SP
SELECT @with_data = 'MOVE "' + @logical_name_data + '" TO "' + @physical_name_data + '"'
SELECT @with_log = 'MOVE "' + @logical_name_log + '" TO "' + @physical_name_log + '"'
--Now do a restore with MOVE.
exec master..xp_restore_database @database=@database_name
, @filename= @full_backup_name
, @with = @with_data
, @with = @with_log
if object_id('tempdb..#database_details') is not null
DROP TABLE #database_details
IF EXISTS
(
SELECT * FROM dbo.sysobjects
WHERE id = OBJECT_ID(N'[dbo].[the_procedure_name]')
AND OBJECTPROPERTY(id, N'IsProcedure') = 1
)
DROP PROCEDURE the_procedure_name
IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_NAME = 'the_routine_name'
and routine_type = 'PROCEDURE' --could also be 'FUNCTION' for a function
)
EXEC ('CREATE PROC dbo.the_procedure_name AS SELECT 1')
GO
ALTER PROCEDURE dbo.the_procedure_name
AS
SELECT *
FROM myTable
CREATE VIEW [dbo].[backup_history]
as
SELECT
server_name,
DATABASE_name,
-- catalog_family_number, --not sure what this does; unclear in BOL
backup_size/1000000 AS backup_size,
CONVERT(CHAR(12),backup_start_date,101) AS backup_date--,
-- in case you want to look at a particular type of backup
-- CASE [type]
-- WHEN 'D' then 'Database'
-- WHEN 'I' then 'Differential database'
-- WHEN 'L' then 'Log'
-- WHEN 'F' then 'File or filegroup'
-- WHEN 'G' then 'Differential file'
-- WHEN 'P' then 'Partial'
-- WHEN 'Q' then 'Differential partial'
-- END AS Backup_Type,
-- [NAME],
-- [description]
FROM msdb.dbo.backupset
WHERE [TYPE] IN ('D','F') --full backups, though tlogs could be interesting
AND server_name = @@SERVERNAME
AND database_name NOT IN ('msdb', 'MASTER', 'model')
AND backup_start_date > GETDATE()-60
--ORDER BY SERVER_name, DATABASE_name, backup_start_date, catalog_family_number