SQL Server restore proc with database name parameter - sql

Looking for a stored procedure to restore from a .bak file, but would like to be able to enter the db name as a parameter, i.e. Exec sp_restore #dbname
The paths to the .bak will be identical for all the dbs i.e. all dbs are dev copies of the same production backup.
Each .mdf and .ldf will have the same name as the db itself i.e.
dbname = #dbname, mdf = D:\data\#dbname.mdf, ldf =D:\data\#dbname.ldf
The paths to .mdf and .ldf will be the identical for each db, i.e. D:\data\#dbname.mdf

Using Sql Server Management Studio, you can start performing a restore operation. Before completing the task, you should be able to see a "Script" button. This will create a script with all the parameters you have manually entered, including mdf and ldf location. You can then save this script and execute it at will. You can also modify the resulting script to make the database name an input variable. You can do anything really. It's SQL!
A sample script that restores a database and changes mdf and ldf file locations would look like this:
RESTORE DATABASE [example] FROM DISK = N'E:\Backup\example.BAK' WITH FILE = 1, MOVE N'ExampleData' TO N'E:\dbfiles\example.mdf', MOVE N'example_log' TO N'E:\dbfiles\example.ldf', NOUNLOAD, STATS = 10
GO
You can read more about the RESTORE statement
You can then insert the script in a stored procedure as such:
CREATE PROCEDURE RestoreDb
-- Add the parameters for the stored procedure here
#dbName nvarchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
RESTORE DATABASE #dbName FROM DISK = N'C:\Data\MSSQL\Backup\lolwut.bak' WITH FILE = 1, NOUNLOAD, STATS = 10
END
GO

Procedure for restore DB from bak-file #DeviceName. It works with DBs, wich have two logical files.
How to use:
EXEC RestoreDb #dbName='qqq', #DeviceName = 'D:\temp\1\R.bak'
Sorry for my English, I improve it.
CREATE PROCEDURE RestoreDb
#dbName NVARCHAR(50),
#DeviceName NVARCHAR(400)
AS
SET NOCOUNT ON
DECLARE #Cmd NVARCHAR(1000),
#DataLogicalName NVARCHAR(200),
#LogLogicalName NVARCHAR(200),
#DatabasePath NVARCHAR(200),
#DataPath NVARCHAR(300),
#LogPath NVARCHAR(300)
CREATE TABLE #Files
(
LogicalName nvarchar(128),
PhysicalName nvarchar(260),
[Type] char(1),
FileGroupName nvarchar(128),
Size numeric(20,0),
MaxSize numeric(20,0),
FileID bigint,
CreateLSN numeric(25,0),
DropLSN numeric(25,0),
UniqueID uniqueidentifier,
ReadOnlyLSN numeric(25,0) ,
ReadWriteLSN numeric(25,0),
BackupSizeInBytes bigint,
SourceBlockSize int,
FileGroupID int,
LogGroupGUID uniqueidentifier,
DifferentialBaseLSN numeric(25,0),
DifferentialBaseGUID uniqueidentifier,
IsReadOnly bit,
IsPresent bit,
TDEThumbprint varbinary(32)
)
SELECT #DatabasePath = 'D:\data\'
SELECT #DataPath = #DatabasePath + #dbName + '.mdf',
#LogPath = #DatabasePath + #dbName + '.ldf'
SELECT #Cmd = 'RESTORE FILELISTONLY
FROM DISK = ''' + #DeviceName + ''''
INSERT #Files
EXEC (#Cmd)
IF NOT EXISTS(SELECT 1 FROM #Files) GOTO ERRORFILES
IF (SELECT COUNT(*) FROM #Files) > 2 GOTO ERRORFILESCOUNT
SELECT #DataLogicalName = LogicalName
FROM #Files
WHERE [Type] = 'D'
SELECT #LogLogicalName = LogicalName
FROM #Files
WHERE [Type] = 'L'
RESTORE DATABASE #DbName
FROM DISK = #DeviceName
WITH
MOVE #DataLogicalName TO #DataPath,
MOVE #LogLogicalName TO #LogPath
GOTO EXITSTAT
ERRORFILES:
BEGIN
RAISERROR( 'The list of files contained in the backup set is empty', 16, 1 )
GOTO EXITSTAT
END
ERRORFILESCOUNT:
BEGIN
RAISERROR( 'The count of files contained in the backup set is more than two', 16, 1 )
GOTO EXITSTAT
END
EXITSTAT:

Related

Scripted Restore Using xp_DirTree For Transient Logical BAK File Name SQL Server

Hi I am trying to restore a DB from one server to another where the logical name of the .bak file changes daily with a new timestamp, I have so far found success in determining this name using the following SQL script provided by Jeff Moden here: http://www.sqlservercentral.com/Forums/Topic1200360-391-1.aspx
--===== Create a holding table for the file names
CREATE TABLE #File
(
FileName SYSNAME,
Depth TINYINT,
IsFile TINYINT
)
;
--===== Capture the names in the desired directory
-- (Change "C:\Temp" to the directory of your choice)
INSERT INTO #File
(FileName, Depth, IsFile)
EXEC xp_DirTree '\\filepath\',1,1
;
--===== Find the latest file using the "constant" characters
-- in the file name and the ISO style date.
SELECT TOP 1
FileName
FROM #File
WHERE IsFile = 1
AND FileName LIKE '%.bak' ESCAPE '_'
ORDER BY FileName DESC
;
DROP TABLE #File
My question is now how do I use this as the basis of a scripted restore operation? any help would be very much appreciated!
I have found success by extending the above to cache the directory path and ordered bak files chronologically to determine which to use, then combined the restore operation, with move for logs.
--==CHECK IF DB EXISTS IF IT DOES DROP IT
USE [master]
IF EXISTS(SELECT * FROM sys.databases where name='insert db name')
DROP DATABASE [insert db name]
--==START THE RESTORE PROCESS
DECLARE #FileName varchar(255), #PathToBackup varchar(255), #RestoreFilePath varchar(1000)
DECLARE #Files TABLE (subdirectory varchar(255), depth int, [file] int)
SET NOCOUNT ON
--==SET THE FILEPATH
SET #PathToBackup = '\\insert path to back up'
--insert into memory table using dirtree at a single file level
INSERT INTO #Files
EXEC master.dbo.xp_DirTree #PathToBackup,1,1
SELECT TOP 1
#FileName = [subdirectory]
FROM
#Files
WHERE
-- get where it is a file
[file] = 1
AND
--==FIND THE LOGICAL NAME OF THE BAK FILE FROM THE CHRONILOGICALLY ORDERED LIST
subdirectory LIKE '%.bak'
ORDER BY
-- order descending so newest file will be first by naming convention
subdirectory DESC
IF LEFT(REVERSE(#PathToBackup), 1) != '\'
BEGIN
SET #PathToBackup = #PathToBackup + '\'
END
SET #RestoreFilePath = #PathToBackup + #FileName
--Grab the file path to restore from
SELECT #RestoreFilePath
--BEGIN THE RESTORE TO THE DESIGNATED SERVER
RESTORE DATABASE [insert name of database to restore]
FROM DISK = #RestoreFilePath
WITH
FILE = 1,
--Create transactional log files on target
MOVE 'mdf_file_name' TO 'file_path\file.mdf',
MOVE 'log_file_name' TO 'file_path\file.ldf', REPLACE;
Here is a script that I have partly written and partly collected.
Features include:
Imports exactly one backup file that has any file name with .bak
ending. If there are more files, then imports only one without any
errors.
If no files exist, gives an error.
Kicks users out from the database.
Deletes the backup file
DECLARE #DBName nvarchar(255), #FileName nvarchar(255), #PathToBackup nvarchar(255), #RestoreFilePath nvarchar(1000)
DECLARE #Files TABLE (subdirectory nvarchar(255), depth int, [file] int)
SET XACT_ABORT, NOCOUNT ON
SET #PathToBackup = N'I:\Folder'
-- insert into our memory table using dirtree and a single file level
INSERT INTO #Files
EXEC master.dbo.xp_DirTree #PathToBackup,1,1
SELECT
#FileName = [subdirectory]
FROM
#Files
WHERE
-- get where it is a file
[file] = 1
AND
subdirectory LIKE N'%.bak'
ORDER BY
-- order descending so newest file will be first by naming convention
subdirectory DESC
IF LEFT(REVERSE(#PathToBackup), 1) != N'\'
BEGIN
SET #PathToBackup = #PathToBackup + N'\'
END
SET #RestoreFilePath = #PathToBackup + #FileName
SET #DBName = LEFT(#FileName, LEN(#FileName)-4)
-- SELECT 'Replace AdventureWorks2016CTP3 in this script with #DBName'
SELECT #RestoreFilePath
BEGIN TRY
-- You can try to check if this command works "already":
-- ALTER DATABASE [#DBName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE [AdventureWorks2016CTP3] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
-- You can try to check if this command works "already":
-- RESTORE DATABASE [#DBName]
RESTORE DATABASE [AdventureWorks2016CTP3]
FROM DISK = #RestoreFilePath
WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 10
END TRY
BEGIN CATCH
-- You can try to check if this command works "already":
-- ALTER DATABASE [#DBName] SET MULTI_USER;
ALTER DATABASE [AdventureWorks2016CTP3] SET MULTI_USER;
; THROW
END CATCH
-- You can try to check if this command works "already":
-- ALTER DATABASE [#DBName] SET MULTI_USER;
ALTER DATABASE [AdventureWorks2016CTP3] SET MULTI_USER;
-- This script is especially for the case where you replication from one location to another using backup and restore.
-- Typically you don't need transaction log backups as all changes will be wiped out on next transfer.
-- You can try to check if this command works "already":
-- ALTER DATABASE [#DBName] SET RECOVERY SIMPLE;
ALTER DATABASE [AdventureWorks2016CTP3] SET RECOVERY SIMPLE;
-- Delete file(s)
-- NOTE: This works only if you give deletion permissions as defined in https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/xp-cmdshell-server-configuration-option?view=sql-server-2017
-- EXAMPLE: exec xp_cmdshell 'del "I:\Directory\AdventureWorks2016CTP3___.bak"'
-- exec xp_cmdshell 'del "' + '#PathToBackup + ''\'' + #FileName + ''"''
DECLARE #cmd NVARCHAR(MAX) = 'xp_cmdshell ''del "' + #PathToBackup + #FileName + '"''';
-- SELECT #cmd
EXEC (#cmd)

SQL GO disrupts chain of local variables

I use script for DB backup as below:
---- INITIALIZATION
-- UNIFIED DATE
DECLARE #DAT DATETIME
SELECT #DAT = GETDATE()
-- DEFAULT BACKUPS LOCATION
DECLARE #PATH VARCHAR(20)
SELECT #PATH = 'Q:\DBbackup\Default\'
---- DATABASE BACKUPS
-- DB1
DECLARE #DBNAME VARCHAR(64)
SELECT #DBNAME = 'DB1'
DECLARE #BACKUPNAME VARCHAR(64)
DECLARE #DESCRIPTION VARCHAR (255)
SELECT #BACKUPNAME = (#PATH + #DBNAME +'_'+ CONVERT(VARCHAR(19),#DAT,121) + '.bak')
SELECT #DESCRIPTION = #DBNAME + ' Full ad hoc backup ' + CONVERT(VARCHAR(20),#DAT)
SELECT #BACKUPNAME
BACKUP DATABASE #DBNAME TO DISK = #BACKUPNAME WITH FORMAT, INIT, NAME = #DESCRIPTION, SKIP, NOREWIND, NOUNLOAD, STATS = 10, COMPRESSION
GO
-- DB2
DECLARE #DBNAME VARCHAR(64)
SELECT #DBNAME = 'DB2'
DECLARE #BACKUPNAME VARCHAR(64)
DECLARE #DESCRIPTION VARCHAR (255)
SELECT #BACKUPNAME = (#PATH + #DBNAME + '_' + CONVERT(VARCHAR(19),#DAT,121) + '.bak')
SELECT #DESCRIPTION = #DBNAME + ' Full ad hoc backup ' + CONVERT(VARCHAR(20),#DAT)
BACKUP DATABASE #DBNAME TO DISK = #BACKUPNAME WITH FORMAT, INIT, NAME = #DESCRIPTION, SKIP, NOREWIND, NOUNLOAD, STATS = 10, COMPRESSION
GO
However, for backup DB2 the variables #PATH and #DAT are not found as they apply only to first backup. It seems the GO command cancels the effect of local variables for DB2 backup. Is there any workaround for this situation? I want to use the variables in INIT only once, not duplicate them for each database backup.
SQL Server does not know what GO means. That's an SSMS feature. It causes multiple batches to be sent. Either remove GO (and restructure the variables so that they are declared only once) or store that data in a persistent location such as a temp table.
Unfortunately, no great options. T-SQL is a stone-age language.

SQL Script to clone database leaving original untouched

we currently have a base installation of our CMS, in this CMS it contains a complete working dataset for users, products, content etc. We are looking to increase our installation time because right now we currently have to go into SQL Server 2012, create a new DB and then restore the DB from an existing base installation db.
This can take up to 10 - 15 minutes each installation we do.
We also make sure our base database has all the requirements for sites we build.
Our issue is, we would like to do the following.
have a script create a fresh new empty database
make a clone of this database into a new .bak file
Take this .bak file then reproduce this into a fresh new database with its own MDF and LDF files respectively.
the databases are on the same server so we dont need to migrate this across to any other machine or instance.
Our code is below
CREATE database my_test
BACKUP DATABASE test_db TO DISK = 'C:\my_test\my_test.bak' WITH INIT;
EXEC internal_lab_test.dbo.sp_helpfile;
RESTORE FILELISTONLY
FROM DISK = 'C:\my_test\my_test.bak'
RESTORE DATABASE my_test
FROM DISK = 'C:\my_test\my_test.bak'
WITH MOVE 'my_test' TO 'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\test_db.mdf',
MOVE 'my_test_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\test_db_log.ldf'
we want to make sure that everything is fresh and clean, but also still contain all the data, however everytime we run this code, we get the following error messages
we also want to make sure the original database mdf and ldf files are left in tact and arent used in the new database
Msg 3154, Level 16, State 4, Line 10
The backup set holds a backup of a database other than the existing 'my_test' database.
Msg 3013, Level 16, State 1, Line 10
RESTORE DATABASE is terminating abnormally.
I know this is old, but it was the 2nd entry in google so for completeness.
It is because the database already exists. so either drop the database or add with Replace.
Also the my_test and my_test_log names need to be the logical names from the restore filelistonly command.
RESTORE DATABASE my_test
FROM DISK = 'C:\my_test\my_test.bak'
WITH Replace,
MOVE 'my_test' TO 'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\test_db.mdf',
MOVE 'my_test_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\test_db_log.ldf'
Compleate script wroted by me that is enough flexible for common development task (clone db from 'template', apply incremental scripts, then drop cloned db).
Note: you should make your DB 'read_only, single_user' before procedure adv.cloneDatabase will be executed, and return original states after, also you need rights to execute xp_cmdshell.
CREATE PROCEDURE adv.alterateFileNames(
#mdfFileName nvarchar(256),
#ldfFileName nvarchar(256),
#newMdfFileName nvarchar(256) OUTPUT,
#newLdfFileName nvarchar(256) OUTPUT
)
AS
BEGIN
DECLARE #path_data nvarchar(256)
DECLARE #ext_data nvarchar(4)
DECLARE #path_log nvarchar(256)
DECLARE #ext_log nvarchar(4)
-- respect file extensions
if (RIGHT(#mdfFileName , 4)='.mdf')
BEGIN
SET #path_data = SUBSTRING(#mdfFileName,0,LEN(#mdfFileName)-3)
SET #ext_data = '.mdf'
END
ELSE
BEGIN
SET #path_data = #mdfFileName
SET #ext_data = ''
END
if (RIGHT(#ldfFileName , 4)='.ldf')
BEGIN
SET #path_log = SUBSTRING(#ldfFileName,0,LEN(#ldfFileName)-3)
SET #ext_log = '.ldf'
END
ELSE
BEGIN
SET #path_log = #ldfFileName
SET #ext_log = ''
END
-- respect suffix counters like dbname_2 (that means add value to them)
DECLARE #iData int
DECLARE #data_suffix_index int = len(#path_data) - charindex('_', reverse(#path_data))
IF (#data_suffix_index < len(#path_data)-1 AND #data_suffix_index > 0 )
BEGIN
DECLARE #data_suffix nvarchar(128) = substring(#path_data, #data_suffix_index+2, len(#path_data)-#data_suffix_index-1 )
IF #data_suffix NOT LIKE '%[^0-9]%'
BEGIN
SET #path_data = SUBSTRING(#path_data,0,#data_suffix_index+1)
SET #iData = CAST(#data_suffix as int);
END
END
IF (#iData is null)
BEGIN
SET #path_data = #path_data
SET #iData = 0
END
DECLARE #iLog int
DECLARE #log_suffix_index int = len(#path_log) - charindex('_', reverse(#path_log))
IF (#log_suffix_index < len(#path_log)-1 AND #log_suffix_index > 0 )
BEGIN
DECLARE #log_suffix nvarchar(128) = substring(#path_log, #log_suffix_index+2, len(#path_log) - #log_suffix_index-1 )
IF #log_suffix NOT LIKE '%[^0-9]%'
BEGIN
SET #path_log = SUBSTRING(#path_log,0,#log_suffix_index+1)
SET #iLog = CAST(#log_suffix as int);
END
END
IF (#iLog is null)
BEGIN
SET #path_log = #path_log
SET #iLog = 0
END
WHILE 1=1
BEGIN
IF EXISTS(SELECT * FROM sys.master_files WHERE physical_name=#path_data+'_'+CAST(#iData AS varchar(6))+#ext_data)
SET #iData=#iData+1
ELSE
BEGIN
SET #path_data= #path_data+'_'+CAST(#iData AS varchar(6))+#ext_data
BREAK
END
END
WHILE 1=1
BEGIN
IF EXISTS(SELECT * FROM sys.master_files WHERE physical_name=#path_log+'_'+CAST(#iLog AS varchar(6))+#ext_log)
SET #iLog=#iLog+1
ELSE
BEGIN
SET #path_log= #path_log+'_'+CAST(#iLog AS varchar(6))+#ext_log
BREAK
END
END
SET #newMdfFileName = #path_data
SET #newLdfFileName = #path_log
END
GO
CREATE PROCEDURE adv.cloneDatabase
(
#databaseName sysname,
#newDatabaseName sysname
)
AS
BEGIN
SET NOCOUNT ON
IF NOT EXISTS ( SELECT * FROM sys.databases WHERE name = #databaseName)
THROW 50000, 'Database doesn''t exist', 1;
IF NOT EXISTS ( SELECT * FROM sys.databases WHERE name = #databaseName AND owner_sid<>0x01)
THROW 50000, 'Clonning of system database is not supported', 1;
IF NOT EXISTS ( SELECT * FROM sys.databases WHERE name = #databaseName AND is_read_only=1)
THROW 50000, 'Clonning of not readonly database is not supported', 1;
IF NOT EXISTS ( SELECT * FROM sys.databases WHERE name = #databaseName AND user_access=1 /*single user*/)
THROW 50000, 'Clonning of nor single_user database is not supported', 1;
-- collect file info
DECLARE #Files TABLE
(
[type] int, /*0,1,2,3,4*/
type_desc nvarchar(60), /*ROWS,LOG,FILESTREAM,FULLTEXT*/
name sysname,
physical_name nvarchar(260)
)
INSERT INTO #Files ([type], type_desc, name, physical_name)
SELECT [type], type_desc, f.name, physical_name
FROM sys.master_files f INNER JOIN sys.databases d ON f.database_id=d.database_id
WHERE d.name=#databaseName
-- test files
DECLARE #filesCount int
SELECT #filesCount = count(*) from #Files
IF (#filesCount<>2)
THROW 50000, 'The procedure doesn''t support complex file structures', 1;
DECLARE #mdfFileName nvarchar(260), #ldfFileName nvarchar(260)
SELECT #mdfFileName = physical_name FROM #Files WHERE type_desc='ROWS'
SELECT #ldfFileName = physical_name FROM #Files WHERE type_desc='LOG'
DECLARE #newMdfFileName nvarchar(260), #newLdfFileName nvarchar(260)
exec adv.alterateFileNames #mdfFileName, #ldfFileName, #newMdfFileName=#newMdfFileName OUTPUT, #newLdfFileName=#newLdfFileName OUTPUT
DECLARE #cmd1 nvarchar(4000)= 'copy /Y "#mdfFileName" "#newMdfFileName"'
DECLARE #cmd2 nvarchar(4000)= 'copy "#ldfFileName" "#newLdfFileName"'
SET #cmd1=replace(#cmd1,'#mdfFileName',#mdfFileName)
SET #cmd1=replace(#cmd1,'#newMdfFileName',#newMdfFileName)
SET #cmd2=replace(#cmd2,'#ldfFileName',#ldfFileName)
SET #cmd2=replace(#cmd2,'#newLdfFileName',#newLdfFileName)
DECLARE #OUTPUT TABLE (line text)
DECLARE #result INT
BEGIN TRY
INSERT INTO #OUTPUT (line) VALUES ('> '+#cmd1)
INSERT INTO #OUTPUT
exec #result =xp_cmdshell #cmd1
INSERT INTO #OUTPUT (line) VALUES ('> '+#cmd2)
IF (#result <> 0)
THROW 50000, 'Error copying mdf file',1
INSERT INTO #OUTPUT
exec #result =xp_cmdshell #cmd2
IF (#result <> 0)
THROW 50000, 'Error copying ldf file',1
END TRY
BEGIN CATCH
SELECT * FROM #OUTPUT WHERE line is not null;
THROW
END CATCH
DECLARE #createDatabaseSql nvarchar(max)
SET #createDatabaseSql = '
CREATE DATABASE '+#newDatabaseName+'
ON (FILENAME = '''+#newMdfFileName+'''),
(FILENAME = '''+#newLdfFileName+''')
FOR ATTACH;'
exec sp_executesql #stmt = #createDatabaseSql
END
GO

full backups occasionally skipping certain databases

We have a job set up to run a script every night to do a full backup on all of our databases. Recently, we noticed that sometimes the last two databases are skipped, but not all of the time. We have a tracking table that we are inserting the state of each database in when we do the backups. On the nights that the last two databases are skipped, the state for those databases doesn't get recorded in the tracking table either. We can't figure out why those databases are being skipped. This is the backup script we are using:
DECLARE #dbname VARCHAR(100),
#dbid INT,
#rcmodel VARCHAR(50),
#state VARCHAR(60),
#date VARCHAR(50),
#time VARCHAR(50),
#sql VARCHAR(3000),
#dir VARCHAR(1000),
#path VARCHAR(100),
#type VARCHAR(10)
SET #path = 'E:\Backups\'
SET #type = 'Full'
SET #date = REPLACE(CONVERT(date,GETDATE(),101),'-','_')
SET #time = REPLACE(CONVERT(TIME(0), GETDATE()),':','_')
SET #path = #path + CONVERT(VARCHAR(30),##SERVERNAME) + '\' + #type + '\'
DECLARE BackupCur CURSOR FOR
SELECT NAME, database_id, recovery_model_desc, state_desc
FROM sys.databases
WHERE NAME <> 'tempdb'
OPEN BackupCur
FETCH NEXT FROM BackupCur INTO #dbname, #dbid, #rcmodel, #state
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO backuptrackingtable (db, statedesc, datecreated)
values (#dbname, #state, GETDATE())
IF #type = 'Full' AND #state = 'ONLINE'
BEGIN
SET #dir = 'EXECUTE master.dbo.xp_create_subdir N'''+#path+#dbname+''''
SET #sql = 'BACKUP DATABASE '+#dbname+' TO DISK = N'''+#path+#dbname+'\'+#dbname+'_'+#date+'.bak'' WITH NOFORMAT, INIT, SKIP, REWIND, NOUNLOAD, COMPRESSION'
PRINT 'Backing up ' + #dbname
EXEC (#dir)
EXEC (#sql)
END
IF #type = 'Log' AND #dbid > 4 AND #rcmodel = 'FULL' AND #state = 'ONLINE'
BEGIN
SET #dir = 'EXECUTE master.dbo.xp_create_subdir N'''+#path+#dbname+''''
SET #sql = 'BACKUP LOG '+#dbname+' TO DISK = N'''+#path+#dbname+'\'+#dbname+'_'+#date+'__'+#time+'.bak'' WITH NOFORMAT, INIT, SKIP, REWIND, NOUNLOAD, COMPRESSION'
PRINT 'Backing up ' + #dbname
EXEC (#dir)
EXEC (#sql)
END
FETCH NEXT FROM BackupCur INTO #dbname, #dbid, #rcmodel, #state
END
CLOSE BackupCur
DEALLOCATE BackupCur
Can think of three possible explanations.
They aren't being returned from the query against sys.databases because they don't exist or the user running the query doesn't have permissions on them.
An unhandled error means that the script aborts before processing them.
##FETCH_STATUS returns -2 at some point because a database has been dropped since the keyset cursor opened.
You would need to put more logging in to investigate further. But you might want to consider using a maintenance plan (dependant on edition) or Ola Hallengren's DB maintenance scripts rather than re-inventing the wheel anyway.

how to pass all database (fast) since sql server 2008 express to sql server 2008 R2 (NO express)

well i had sql 2008 express, and now i have installed, sql server, now i want to delete sql express, but in that instance i have all my database i have worked (plus of 20), so they are very important for me, how can i pass it to sql server 2008 r2, i know i can do database of all but i dont want to work a lot of, there is a way short, for to pass al database? coping a folder? something? thanks!
I Attached all database, and i added, all (but one for one) i added all in the same windows and in 5 minutos i had all database in sql (no express)
Create an SSIS package with 4 steps.
First, a Execute SQL task that backups all DBs to a specific location:
exec sp_msforeachdb '
IF DB_ID(''?'') > 4
Begin
BACKUP DATABASE [?] TO DISK = N''\\Backups\?.BAK'' WITH NOFORMAT, INIT,
NAME = N''?-Full Database Backup'', SKIP, NOREWIND, NOUNLOAD
declare #backupSetId as int
select #backupSetId = position from msdb..backupset where database_name=N''?''
and backup_set_id=(select max(backup_set_id) from msdb..backupset
where database_name=N''?'' )
if #backupSetId is null begin
raiserror(N''Verify failed. Backup information for database ''''?'''' not found.'', 16, 1)
end
RESTORE VERIFYONLY FROM DISK = N''\\Backups\?.BAK'' WITH
FILE = #backupSetId, NOUNLOAD, NOREWIND
End
'
Second, Create a SP to restore DBs using a variable for location and DB name:
CreatePROCEDURE [dbo].[uSPMas_RestoreDB] #DBname NVARCHAR(200),
#BackupLocation NVARCHAR(2000)
AS
BEGIN
SET nocount ON;
create table #fileListTable
(
LogicalName nvarchar(128),
PhysicalName nvarchar(260),
[Type] char(1),
FileGroupName nvarchar(128),
Size numeric(20,0),
MaxSize numeric(20,0),
)
insert into #fileListTable EXEC('RESTORE FILELISTONLY FROM DISK = '''+#BackupLocation+#dbname+'.bak''')
Declare #Dname varchar(500)
Set #Dname = (select logicalname from #fileListTable where type = 'D')
Declare #LName varchar(500)
Set #LName = (select logicalname from #fileListTable where type = 'L')
declare #sql nvarchar(4000)
SET #SQL = 'RESTORE DATABASE ['+ #dbname +'] FROM
DISK = N'''+#BackupLocation + #dbname +'.BAK'' WITH FILE = 1,
MOVE N'''+ #Dname +''' TO N''E:\YourLocation\'+ #dbname +'.mdf'',
MOVE N'''+ #LName +''' TO N''D:\Your2ndLocation\'+ #dbname +'_log.ldf'',
NOUNLOAD, REPLACE, STATS = 10'
exec sp_executesql #SQL
drop table #fileListTable
END
Third, Create a ForEach Loop Container and put a Execute Sql Statement with variable:
EXEC uSPMas_RestoreDB ? , ?
Use the for ForEach Loop Container to pass the variables
Fourth, Create a 'Transfer Logins' task to move over all DB logins