I'm trying to restore a SQL Server database with Delphi. The code that I have is placed in a thread and works - meaning I manage to make the restore. The problem is that I get an error from Delphi saying that "Object is open" and the program stops, even though the restore happens successfully. Why am I getting this problem and how can I fix it? Here's the code:
This is the restore thread:
type
TThreadRestoreBackUp = class( TThread )
protected
procedure Execute(); override;
public
DataSource : TMSDataSource;
Connection : TMSConnection;
Query : TMSQuery;
var
DBName, RestorePath, dbRPath, dbRLogPath : string;
differentDB : Boolean;
end;
This is how I call the thread:
procedure TfrmCreateBackUp.btnRestoreClick(Sender: TObject);
var
RestoreBackUp : BackUpThread.TThreadRestoreBackUp;
begin
RestoreBackUp := BackUpThread.TThreadRestoreBackUp.Create(True);
RestoreBackUp.FreeOnTerminate := True;
try
RestoreBackUp.DataSource := frmMain.MSDSChanges;
RestoreBackUp.Connection := frmMain.MSConnLyubenAirport;
RestoreBackUp.Query := frmMain.MSQChanges;
RestoreBackUp.DBName := edtDBName.Text;
RestoreBackUp.DifferentDB := tcxCheckBoxNewDB.Checked;
RestoreBackUp.RestorePath := cxbeChoosePath.Text;
RestoreBackUp.Start;
except on EConvertError do
RestoreBackUp.Free;
end;
end;
And this is the Execute function of the thread, aka the code that gets run, when I call the thread:
procedure TThreadRestoreBackUp.Execute();
begin
dbRPath := 'E:\ClientDBS\';
dbRLogPath := 'E:\ClientDBS\';
Query.Connection := Connection;
DataSource.DataSet := Query;
if DifferentDB then
begin
dbRPath := dbRPath + DBName + '.mdf';
dbRLogPath := dbRLogPath + DBName + '.ldf';
Query.SQL.Text := 'USE master If DB_ID(' + QuotedStr(DBName) + ') IS NOT NULL BEGIN' +
' ALTER DATABASE [' + DBName + '] SET OFFLINE WITH ROLLBACK IMMEDIATE RESTORE DATABASE [' +
DBName + '] FROM DISK = ' +
QuotedStr(RestorePath) +
' WITH REPLACE, RECOVERY ALTER DATABASE [' + DBName +
'] SET ONLINE END ELSE BEGIN RESTORE DATABASE [' + DBName + ']' +
' FROM DISK = ' + QuotedStr(RestorePath)
+ ' WITH RECOVERY, MOVE ' + QuotedStr('Test') + ' TO ' +
QuotedStr(dbRPath) + ', MOVE ' + QuotedStr('Test_log') +
' TO ' + QuotedStr(dbRLogPath) + 'END';
Query.Execute;
end
else
begin
DBName := Connection.Database;
Query.SQL.Text := 'USE master ALTER DATABASE [' + DBName +
'] SET OFFLINE WITH ROLLBACK IMMEDIATE' +
' RESTORE DATABASE [' + DBName +
'] FROM DISK = ' + QuotedStr(RestorePath) +
' WITH REPLACE, RECOVERY ALTER DATABASE [' + DBName +
'] SET ONLINE';
Query.Execute;
end;
DataSource.Free;
Connection.Free;
Query.Free;
end;
Here's an explanation on how it works: I have a form in which I can choose a path from a tcxButtonEdit, which opens TOpenDialog when the button is pressed. When the path is chosen I have option to press a checkbox, which indicates whether the user wants to restore in the database used, or in a different one. Then the user can enter the name of the different database or the new database if they want to save in another database and not the original. When the button Restore is pressed the thread is called and executed. The code inside the thread sets up the things needed for the restore, like paths for the files, connection, tmsQuery and DataSource. Then if it's the checkbox is checked then the if statement receives true, and makes the restore in the different database, if not then it does it in the same.
Related
I asked this on GitHub here, but I think we can turn into a more generic question to get some helpful ideas faster.
First, I ran the script here, which shows that I am a member of the db-owner group.
This is on the install script for an older tool called AutoEdit. Despite the issue below, I'm able to turn on AutoAudit for specific tables and it's working okay.
The supplied script stores a few stored proc under a schema with my username, then tries to transfer them to the "audit" schema later. The AutoEdit concepts and stored procs are all actually working, but now I need to clean it up and put in another environment.
Error is:
Cannot find the object 'pAutoAudit', because it does not exist or you do not have permission.
It created the stored proc as
"Corp\myuserid.pAutoAudit"
I added two print statements to help debug:
-- This is the line of code (the EXEC below) that is causing the issue:
print Concat('#AuditSchema=', #AuditSchema)
SET #Sql = 'ALTER SCHEMA ' + quotename(#AuditSchema) + ' TRANSFER dbo.pAutoAudit'
print Concat('#Sql=', #Sql)
EXEC (#Sql)
Above shows:
#AuditSchema=Audit
#Sql=ALTER SCHEMA [Audit] TRANSFER dbo.pAutoAudit
The schema Audit exists, and it has one stored proc in it: pAutoAuditArchive.
I have added a related question here: SQL Server setting that changes schema from dbo
To fix this specific problem, I saw the correct syntax from the Lauren answer here, like this:
ALTER SCHEMA NewSchema TRANSFER [OldSchema].[TableName]
The following script temporarily fixes the issue. I have to study more how to fix the original script if indeed it has an error:
use myDbname
Declare #AuditSchema varchar(32)
Declare #OldSchema varchar(32)
Declare #SQL varchar(max)
Set #AuditSchema = 'Audit'
Set #OldSchema = 'Corp\myuser'
-- ALTER SCHEMA NewSchema TRANSFER [OldSchema].[TableName]
SET #SQL = 'ALTER SCHEMA ' + quotename(#AuditSchema) + ' TRANSFER ' + quotename(#OldSchema) + '.pAutoAudit'
print Concat('#SQL=', #SQL)
EXEC (#SQL)
SET #SQL = 'ALTER SCHEMA ' + quotename(#AuditSchema) + ' TRANSFER ' + quotename(#OldSchema) + '.pAutoAuditAll'
EXEC (#SQL)
SET #SQL = 'ALTER SCHEMA ' + quotename(#AuditSchema) + ' TRANSFER ' + quotename(#OldSchema) + '.pAutoAuditDrop'
EXEC (#SQL)
SET #SQL = 'ALTER SCHEMA ' + quotename(#AuditSchema) + ' TRANSFER ' + quotename(#OldSchema) + '.pAutoAuditDropAll'
EXEC (#SQL)
SET #SQL = 'ALTER SCHEMA ' + quotename(#AuditSchema) + ' TRANSFER ' + quotename(#OldSchema) + '.pAutoAuditRebuild'
EXEC (#SQL)
SET #SQL = 'ALTER SCHEMA ' + quotename(#AuditSchema) + ' TRANSFER ' + quotename(#OldSchema) + '.pAutoAuditRebuildAll'
EXEC (#SQL)
SET #SQL = 'ALTER SCHEMA ' + quotename(#AuditSchema) + ' TRANSFER ' + quotename(#OldSchema) + '.pAutoAuditSetTriggerState'
EXEC (#SQL)
SET #SQL = 'ALTER SCHEMA ' + quotename(#AuditSchema) + ' TRANSFER ' + quotename(#OldSchema) + '.pAutoAuditSetTriggerStateAll'
EXEC (#SQL)
However, to fix the "AutoEdit" script referenced in the question, the problem can be corected by adding this code to AutoEdit or running it before AutoEdit. Apparently, it assumes you are in the "dbo" default_schema. You might have to set the value back to the original value if needed after the script.
DECLARE #SQL2 VARCHAR(max)
SET #SQL2 = 'ALTER USER ' + quotename(current_user) + ' WITH DEFAULT_SCHEMA = dbo'
print Concat('#SQL2=', #SQL2)
exec (#SQL2)
The better fix for when I moved it to another environment, was to change all the "Create Proc xxxx" to "Create Proc dbo.xxxx".
Using SQL Server 2012.
Using the system views stored for each database I wanted to keep a summary of index behavior for all indexes across the instance. The code below collects some stats and drops them in a table for later use. The snag is, I had to use a cursor to loop through the databases in the instance. Can anyone suggest a nicer way of doing this without having to use the cursor?
USE Master
GO
-- If the procedure already exists then update it.
IF OBJECT_ID('sp_index_stats') IS NOT NULL
DROP PROCEDURE sp_index_stats
GO
CREATE PROCEDURE sp_index_stats AS
DECLARE #dbname NVARCHAR(128)
DECLARE #finalSQL NVARCHAR(1024)
-- Results of the query are put into a table in Demo_DB.
-- So empty it now for the new results.
TRUNCATE TABLE Demo_DB.dbo.index_stats
-- Use a cursor to get a list of all the tables in the instance.
DECLARE database_cursor CURSOR LOCAL FOR
SELECT name
FROM Master.dbo.sysdatabases
WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb')
OPEN database_cursor
FETCH NEXT FROM database_cursor INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
-- Each database will contain the same structue, so I need
-- to create a standard query just changing the database name.
SET #finalSQL = 'INSERT INTO Demo_DB.dbo.index_stats '
-- Sort out the select statement.
SET #finalSQL = #finalSQL + 'SELECT sdb.name, st.name, si.name, si.type_desc, '
SET #finalSQL = #finalSQL + 'si.is_primary_key, si.fill_factor, '
SET #finalSQL = #finalSQL + 'sd.user_scans, sd.last_user_scan, '
SET #finalSQL = #finalSQL + 'sd.user_updates, sd.last_user_update '
-- The 'from' and 'joins' need to be adjusted slightly for each databse.
SET #finalSQL = #finalSQL + 'FROM ' + #dbname + '.sys.tables st '
SET #finalSQL = #finalSQL + 'JOIN ' + #dbname + '.sys.indexes si ON (si.object_id = st.object_id) '
SET #finalSQL = #finalSQL + 'JOIN ' + #dbname + '.sys.dm_db_index_usage_stats sd ON (si.object_id = sd.object_id) '
SET #finalSQL = #finalSQL + 'JOIN ' + #dbname + '.sys.databases sdb ON (sdb.database_id = sd.database_id) ;'
-- Ok, let's run that...
EXEC (#finalSQL)
-- Get the next database in the instance..,
FETCH NEXT FROM database_cursor INTO #dbname
END
CLOSE database_cursor
DEALLOCATE database_cursor
GO
Regards,
JC.
What about concatenation?
Something like this (not reproduced the whole stored procedure, but hopefully you get the gist)
DECLARE #SQL VARCHAR(MAX)
SET #SQL = ''
SELECT #SQL = #SQL +
'INSERT INTO Demo_DB.dbo.index_stats ' +
'SELECT sdb.name, st.name, si.name, si.type_desc, ' +
'si.is_primary_key, si.fill_factor, ' +
'sd.user_scans, sd.last_user_scan, ' +
'sd.user_updates, sd.last_user_update ' +
'FROM ' + name + '.sys.tables st ' +
'JOIN ' + name + '.sys.indexes si ON (si.object_id = st.object_id) ' +
'JOIN ' + name + '.sys.dm_db_index_usage_stats sd ON (si.object_id = sd.object_id) ' +
'JOIN ' + name + '.sys.databases sdb ON (sdb.database_id = sd.database_id) ;'
FROM Master.dbo.sysdatabases
WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb')
SELECT #SQL
(Obviously not EXECing anything at this point).
I have a piece of dynamic sql query. I'd like to keep the result in a temp table. But the query returns +100 fields so I'd prefer not to type the Create table script manually.
Is it possible in Sql Server Management Studio to script out the results returned by the procedure into a create table script.
So let's say that in a new query panel I execute my script. Below I get the returned results. Option I'm looking for is something like e.g. right clicking the results and selecting "Script into a table". Or something similar to what you get when you select "Edit top 200 rows" on a table and then in the returned results when you right click -> Pane -> SQL you can edit the SQL that generated the results.
Is anything like that possible in SSMS for results of a procedure? If external tools are required are there any that are free? I'm using SQL Server 2012 and SSMS 2012. Some tools that where available for previous versions are licensed for 2012.
Below some mocked version of the core code in the procedure:
exec dbo.spDynamic
#ID ,
#ID2 ,
#Parameters ,
#prefixLogic,
#selectprefix,
#selectsuffix,
#Table_1,
#Function_1,
#SelectExtra_1,
#Where_1,
#Function_2,
#SelectExtra_2,
#Where_2,
#On,
#finalWhere
#tempSchema
#tempTable
#tempWhere
And here's the essential part of the spDynamic:
Declare #sql nvarchar(max)
set #sql =
+ #parameterLogic
+ ' ' + #prefixlogic
+ #selectprefix
+ ' SELECT ' + #DeltaLogic
+ ' FROM ( Select * ' + Case When #ID < 0 Then Replace(#SelectExtra_1, '<ID>', CAST(#ID AS nvarchar))
When #ID = 0 Then Replace(#SelectExtra_2, '<ID>', CAST(#ID AS nvarchar))
Else Replace(#Table_1, '<ID>', CAST(#ID AS nvarchar)) End
+ ' From ' + Case When #ID < 0 Then #Function_1 + ' ' + #Where_1
When #ID = 0 Then #Function_2 + ' ' + #Where_2
Else #tempSchema + #tempTable
+ ' ' + Replace(#tempWhere, '<ID>', CAST(#ID AS nvarchar)) End
+ ' ) A '
+ ' FULL OUTER JOIN '
+ ' ( Select * ' + Case When #ID2 < 0 Then Replace(#SelectExtra_1, '<ID>', CAST(#ID2 AS nvarchar))
When #ID2 = 0 Then Replace(#SelectExtra_2, '<ID>', CAST(#ID2 AS nvarchar))
Else Replace(#Table_1, '<ID>', CAST(#ID2 AS nvarchar)) End
+ ' From ' + Case When #ID2 < 0 Then #Function_1 + ' ' + #Where_1
When #ID2 = 0 Then #Function_2 + ' ' + #Where_2
Else #tempSchema + #tempTable
+ ' ' + Replace(#tempWhere, '<ID>', CAST(#ID2 AS nvarchar)) End
+ ' ) B ' + #on
+ #finalWhere
+ #selectsuffix
exec sp_sqlexec #sql
One solution could be to execute the stored procedure inside an OPENROWSET function as described here.
This allows you to create the table on-the-fly, for example by writing:
SELECT * INTO MyTempTable
FROM OPENROWSET('SQLNCLI', 'Server=localhost;Trusted_Connection=yes',
'EXEC myStoredProc')
If you don't want actual data into MyTempTable, you could add WHERE 1 = 0 at the end. Afterwards, you can then script out MyTempTable just like any other table.
If you use SSMSBoost tool bar then it has a "script grid data" option:
This will create a table called NewTable
SELECT *
INTO NewTable
FROM AnotherTable
Can you could alter your dynamic SQL to do this?
Whith the assistance of a very good fellow from this forum (Mr. DJHnz) i solve my first issue regarding the creation of a stream database
Now i'm facing another issue
I'm giving you the code:
USE [master]
GO
/****** Object: StoredProcedure [dbo].[sp_AddStreamDB] Script Date: 12/21/2009 09:55:47 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_AddStreamDB](
-- Add the parameters for the stored procedure here
#DPath varchar(MAX),
#DBName varchar(50),
#Qchar varchar(1) = "'"
) AS
BEGIN_TRY:
SET QUOTED_IDENTIFIER ON;
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE
#ErrMsg nvarchar(4000),
#DBName1 varchar(50),
#DBName2 varchar(50),
#DBNamefs varchar(50),
#DBNamelog varchar(50),
#FileGroupN varchar(100),
#DATName varchar(MAX),
#LOGName varchar(MAX),
#FSName varchar(MAX),
#CreateSdb nvarchar(MAX),
#Statement nvarchar(MAX)
SET #DBName1 = (#DBName + '1')
SET #DBName2 = (#DBName + '2')
SET #DBNamefs = (#DBName + 'fs')
SET #DBNamelog = (#DBName + 'log')
SET #FileGroupN = (#DBname + 'StreamGroup')
SET #DATName = (#Qchar + #DPath + #DBName +'_dat.mdf' + #Qchar)
SET #LOGName = (#Qchar + #DPath + #DBName +'_log.ldf' + #Qchar)
SET #FSName = (#Qchar + #DPath + #DBName + '_fs' + #Qchar)
SET #CreateSdb =('CREATE DATABASE ' + #DBName + ' ON PRIMARY (NAME = ' + #DBName1 + ', FILENAME = ' + #DATName + '), FILEGROUP ' + #FileGroupN + ' CONTAINS FILESTREAM (NAME = ' + #DBNamefs + ', FILENAME = ' + #FSName + ') LOG ON (NAME = ' + #DBNamelog + ', FILENAME = ' + #LOGName + ')')
SET #Statement = ' '
BEGIN_CATCH:
SELECT ERROR_MESSAGE() as ErrorMessage;
SELECT #ErrMsg = ERROR_MESSAGE()
EXEC master.sys.sp_executesql #CreateSdb, #Statement
RAISERROR (#ErrMsg,1,1)
RETURN 0
END_CATCH:
END_TRY:
So far to point everything works fine until the remote server tries to create the neccessary files for the stream DB
then he gives the following error:
Unable to open the physical file "C:\sqlDATA\RemoteDB_fs". Operating system error -2147024891: "0x80070005(Access is denied.)".
The name of the drive C:\ lies on the remote machine (a machine near to me in the same network with Windows server 2003; later i will run the program for my ISP machine)
the subfolder sqlDATA\ is already there i have created manually as it should be.
In my local machine the all package works fine and the DATA BASE created fine but the issue starts when i use remote server.
NOW I NEED THE HELP:
Why i receive this ERROR?
The SQL Server service account does not have rights on C:\SQLData
As #gbn explained and also:
C:\sqlDATA directory must exist.
The \RemoteDB_fs sub-directory for file-stream must not exist.
When I want to make a copy of a database, I always create a new empty database, and then restore a backup of the existing database into it. However, I'm wondering if this is really the least error-prone, least complicated, and most efficient way to do this?
It is possible to skip the step of creating the empty database. You can create the new database as part of the restore process.
This is actually the easiest and best way I know of to clone a database. You can eliminate errors by scripting the backup and restore process rather than running it through the SQL Server Management Studio
There are two other options you could explore:
Detach the database, copy the .mdf file and re-attach.
Use SQL Server Integration Services (SSIS) to copy all the objects over
I suggest sticking with backup and restore and automating if necessary.
Here's a dynamic sql script I've used in the past. It can be further modified but it will give you the basics. I prefer scripting it to avoid the mistakes you can make using the Management Studio:
Declare #OldDB varchar(100)
Declare #NewDB varchar(100)
Declare #vchBackupPath varchar(255)
Declare #query varchar(8000)
/*Test code to implement
Select #OldDB = 'Pubs'
Select #NewDB = 'Pubs2'
Select #vchBackupPath = '\\dbserver\C$\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Backup\pubs.bak'
*/
SET NOCOUNT ON;
Select #query = 'Create Database ' + #NewDB
exec(#query)
Select #query = '
Declare #vBAKPath varchar(256)
declare #oldMDFName varchar(100)
declare #oldLDFName varchar(100)
declare #newMDFPath varchar(100)
declare #newLDFPath varchar(100)
declare #restQuery varchar(800)
select #vBAKPath = ''' + #vchBackupPath + '''
select #oldLDFName = name from ' + #OldDB +'.dbo.sysfiles where filename like ''%.ldf%''
select #oldMDFName = name from ' + #OldDB +'.dbo.sysfiles where filename like ''%.mdf%''
select #newMDFPath = physical_name from ' + #NewDB +'.sys.database_files where type_desc = ''ROWS''
select #newLDFPath = physical_name from ' + #NewDB +'.sys.database_files where type_desc = ''LOG''
select #restQuery = ''RESTORE DATABASE ' + #NewDB +
' FROM DISK = N'' + '''''''' + #vBAKpath + '''''''' +
'' WITH MOVE N'' + '''''''' + #oldMDFName + '''''''' +
'' TO N'' + '''''''' + #newMDFPath + '''''''' +
'', MOVE N'' + '''''''' + #oldLDFName + '''''''' +
'' TO N'' + '''''''' + #newLDFPath + '''''''' +
'', NOUNLOAD, REPLACE, STATS = 10''
exec(#restQuery)
--print #restQuery'
exec(#query)
Backup and Restore is the most straight-forward way I know. You have to be careful between servers as security credentials don't come with the restored database.
The Publish to Provider functionality has worked great for me. See Scott Gu's Blog Entry.
If you need something really robust look at redgate software's tools here...if you are doing much SQL at all, these are worth the $$.
::================ BackUpAllMyDatabases.cmd ============= START
::BackUpAllMyDatabases.cmd
:: COMMAND LINE BATCH SCRIPT FOR TAKING BACKUP OF ALL DATABASES
::RUN THE SQL SCRIPT VIA THE COMMAND LINE WITH LOGGING
sqlcmd -S localhost -e -i "BackUpAllMyDatabases.sql" -o Result_Of_BackUpAllMyDatabases.log
::VIEW THE RESULTS
Result_Of_BackUpAllMyDatabases.log
::pause
::================ BackUpAllMyDatabases.cmd ============= END
--=================================================BackUpAllMyDatabases.sql start
DECLARE #DBName varchar(255)
DECLARE #DATABASES_Fetch int
DECLARE DATABASES_CURSOR CURSOR FOR
select
DATABASE_NAME = db_name(s_mf.database_id)
from
sys.master_files s_mf
where
-- ONLINE
s_mf.state = 0
-- Only look at databases to which we have access
and has_dbaccess(db_name(s_mf.database_id)) = 1
-- Not master, tempdb or model
--and db_name(s_mf.database_id) not in ('Master','tempdb','model')
group by s_mf.database_id
order by 1
OPEN DATABASES_CURSOR
FETCH NEXT FROM DATABASES_CURSOR INTO #DBName
WHILE ##FETCH_STATUS = 0
BEGIN
declare #DBFileName varchar(256)
set #DBFileName = #DbName + '_' + replace(convert(varchar, getdate(), 112), '-', '.') + '.bak'
--REMEMBER TO PUT HERE THE TRAILING \ FOR THE DIRECTORY !!!
exec ('BACKUP DATABASE [' + #DBName + '] TO DISK = N''D:\DATA\BACKUPS\' +
#DBFileName + ''' WITH NOFORMAT, INIT, NAME = N''' +
#DBName + '-Full Database Backup'', SKIP, NOREWIND, NOUNLOAD, STATS = 100')
FETCH NEXT FROM DATABASES_CURSOR INTO #DBName
END
CLOSE DATABASES_CURSOR
DEALLOCATE DATABASES_CURSOR
--BackUpAllMyDatabases==========================end
--======================RestoreDbFromFile.sql start
-- Restore database from file
-----------------------------------------------------------------
use master
go
declare #backupFileName varchar(100), #restoreDirectory varchar(100),
#databaseDataFilename varchar(100), #databaseLogFilename varchar(100),
#databaseDataFile varchar(100), #databaseLogFile varchar(100),
#databaseName varchar(100), #execSql nvarchar(1000)
-- Set the name of the database to restore
set #databaseName = 'ReplaceDataBaseNameHere'
-- Set the path to the directory containing the database backup
set #restoreDirectory = 'ReplaceRestoreDirectoryHere' -- such as 'c:\temp\'
-- Create the backup file name based on the restore directory, the database name and today's date
#backupFileName = #restoreDirectory + #databaseName + '-' + replace(convert(varchar, getdate(), 110), '-', '.') + '.bak'
-- set #backupFileName = 'D:\DATA\BACKUPS\server.poc_test_fbu_20081016.bak'
-- Get the data file and its path
select #databaseDataFile = rtrim([Name]),
#databaseDataFilename = rtrim([Filename])
from master.dbo.sysaltfiles as files
inner join
master.dbo.sysfilegroups as groups
on
files.groupID = groups.groupID
where DBID = (
select dbid
from master.dbo.sysdatabases
where [Name] = #databaseName
)
-- Get the log file and its path
select #databaseLogFile = rtrim([Name]),
#databaseLogFilename = rtrim([Filename])
from master.dbo.sysaltfiles as files
where DBID = (
select dbid
from master.dbo.sysdatabases
where [Name] = #databaseName
)
and
groupID = 0
print 'Killing active connections to the "' + #databaseName + '" database'
-- Create the sql to kill the active database connections
set #execSql = ''
select #execSql = #execSql + 'kill ' + convert(char(10), spid) + ' '
from master.dbo.sysprocesses
where db_name(dbid) = #databaseName
and
DBID <> 0
and
spid <> ##spid
exec (#execSql)
print 'Restoring "' + #databaseName + '" database from "' + #backupFileName + '" with '
print ' data file "' + #databaseDataFile + '" located at "' + #databaseDataFilename + '"'
print ' log file "' + #databaseLogFile + '" located at "' + #databaseLogFilename + '"'
set #execSql = '
restore database [' + #databaseName + ']
from disk = ''' + #backupFileName + '''
with
file = 1,
move ''' + #databaseDataFile + ''' to ' + '''' + #databaseDataFilename + ''',
move ''' + #databaseLogFile + ''' to ' + '''' + #databaseLogFilename + ''',
norewind,
nounload,
replace'
exec sp_executesql #execSql
exec('use ' + #databaseName)
go
-- If needed, restore the database user associated with the database
/*
exec sp_revokedbaccess 'myDBUser'
go
exec sp_grantdbaccess 'myDBUser', 'myDBUser'
go
exec sp_addrolemember 'db_owner', 'myDBUser'
go
use master
go
*/
--======================RestoreDbFromFile.sql