Every week I have to restore 2 different databases. I submit a ticket to Epi support and they give me .BAK files with different dates appended to them.
Running SQL Server 2014 (on remote server), Visual Studio 19 (on local machine), and Integration Service Project.
So far, my SSIS package removes previous .BAK files from SQL Server Backup directory, moves the new ones from my Downloads folder to the SQL Server Backup directory, and deletes one of previously existing backups (I like to delete them because WITH REPLACE does not update the LAST RESTORED DATE and I like to keep those up-to-date).
I would think that I could re-use the filename and the directory from when I move the BAK files with a File System Task in order to generate the RESTORE DATABASE statement, but I am not sure how to pass those fields in SSIS.
Now, I need to EXECUTE SQL TASK to RESTORE DATABASE, but it is hard to execute this in one statement with a dynamic filename.
I have looked at many different articles and tried different things, but none have worked.
The following script is what I want to be able to run, but I get errors even when the filename is hardcoded:
RESTORE DATABASE [Insite.Commerce.horizon.Sandbox] FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\horizon-sandbox-20210412.bak'
The errors that this draws are below:
Msg 5133, Level 16, State 1, Line 2 Directory lookup for the file "d:\sqldata\\Insite.Commerce.horizon.mdf" failed with the operating system error 21(The device is not ready.).
Msg 3156, Level 16, State 3, Line 2 File 'Insite.Commerce.horizon' cannot be restored to 'd:\sqldata\\Insite.Commerce.horizon.mdf'. Use WITH MOVE to identify a valid location for the file.
Msg 5133, Level 16, State 1, Line 2 Directory lookup for the file "l:\sqllogs\\Insite.Commerce.horizon_log.ldf" failed with the operating system error 3(The system cannot find the path specified.).
Msg 3156, Level 16, State 3, Line 2 File 'Insite.Commerce.horizon_log' cannot be restored to 'l:\sqllogs\\Insite.Commerce.horizon_log.ldf'. Use WITH MOVE to identify a valid location for the file.
Msg 3119, Level 16, State 1, Line 2 Problems were identified while planning for the RESTORE statement. Previous messages provide details.
Msg 3013, Level 16, State 1, Line 2 RESTORE DATABASE is terminating abnormally.
I am not sure how to address these errors and/or if they are even relevant because I do not know if I am going about a database restore in SSIS the right way.
Regardless, as of now, I am trying to execute the following SQL statement in SSIS in order to return the SQL statement it generates as a result or variable that can be passed to another SQL statement and then executed. See below:
DECLARE #dirPath nvarchar(500) = 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\'
DECLARE #tblgetfileList TABLE
(FileName nvarchar(500)
,depth int
,isFile int)
INSERT INTO #tblgetfileList
EXEC xp_DirTree #dirPath,1,1
select 'RESTORE DATABASE [Insite.Commerce.horizon.Sandbox] FROM DISK = ''C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\' + FileName + '''' from #tblgetfileList where isFile = 1 and FileName like 'horizon-sandbox-%.bak'
The output of this is: RESTORE DATABASE [Insite.Commerce.horizon.Sandbox] FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\horizon-sandbox-20210412.bak'
I tried storing this output as a variable and then executing it. See following script:
DECLARE #dirPath nvarchar(500) = 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\'
DECLARE #tblgetfileList TABLE
(FileName nvarchar(500)
,depth int
,isFile int)
INSERT INTO #tblgetfileList
EXEC xp_DirTree #dirPath,1,1
declare #sqltext varchar(max)
set #sqltext = '
select ''RESTORE DATABASE [Insite.Commerce.horizon.Sandbox] FROM DISK = ''C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\ + FileName + '''' from #tblgetfileList where isFile = 1 and FileName like ''horizon-sandbox-%.bak''
'
exec (#sqltext)
(The quotes of #sqltext might not be perfect, but I fixed them when trying to run it)
Also, any local file directory seen in the code here I have to prepend the IPv4 Address of the remote server and then change the file directory to "C$<insert rest of directory here>". So, it looks something like "\\C$<rest of directory>". This is because I am running the SSIS package on my local machine and it is doing this work on the remote server.
Long story short, I am stuck as to what to do. I do not know the best way of going about this nor do I know how to execute upon it.
I use TSQL all the time and would consider myself intermediate, but passing variables, recursive queries, and automation/programming are some things that I DEFINITELY need to work on. So, I could be making this way more complex than it needs to be and it could be a simple fix.
Is there an easier method? Can I utilize what I have already done? I would assume that I could just write one query to do this and then execute that in SSIS Execute SQL Task or Execute TSQL Statement Task.
The end goal is just to be able to grab the name of the new BAK file and restore that database in SQL Server
Let me know if you need more information! I can edit the question as necessary.
Any and all help is welcome!
Thank you in advance!
WITH MOVE needed to be used, but the DB name changed so all the logical filenames also had to change.
In short, what I did was use the UX in SSMS to set-up the database restore.
I picked my file from my device and changed the Restore To name as necessary. Then, I clicked "Script" in the top left of the Restore Database window and then clicked "New Query Editor Window".
This scripted everything out to a new query. It included the WITH MOVEs that needed to take place and a few other settings.
Although, how I got this to work in SSIS was I copied that new script to an Execute SQL Task in SSIS, but I added that text into another dynamic query that grabbed the filename I needed.
Here is the full query for the restore:
DECLARE #dirPath nvarchar(500) = '\\<IPv4 Address>\C$\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\'
DECLARE #tblgetfileList TABLE
(FileName nvarchar(500)
,depth int
,isFile int)
INSERT INTO #tblgetfileList
EXEC xp_DirTree #dirPath,1,1
declare #sqltext varchar(max)
select #sqltext=
'RESTORE DATABASE [Insite.Commerce.horizon.Sandbox] FROM DISK = N''\\<IPv4 Address>\C$\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\' + FileName + '''' +
' WITH FILE = 1, MOVE N''Insite.Commerce.horizon'' TO N''\\<IPv4 Address>\C$\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\Insite.Commerce.horizon.Sandbox.mdf'', ' +
'MOVE N''Insite.Commerce.horizon_log'' TO N''\\<IPv4 Address>\C$\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\Insite.Commerce.horizon.Sandbox_log.ldf'', NOUNLOAD, STATS = 5'
from #tblgetfileList where isFile = 1 and FileName like 'horizon-sandbox-%.bak'
exec (#sqltext)
Related
I am having a issue for restoring a partitioned database using the below script.
I have 7 partitions in the database.
here is the code .
declare #Sql varchar(max)
SET #Sql = 'RESTORE DATABASE [NEWS]
FILE = ''DEMO'',
FILEGROUP = ''DEMO''
FROM DISK = ''C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\DEMO_clone.bak
WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 10
GO
RESTORE LOG [NEWS]
FROM DISK = ''C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\DEMO_clone.bak''
WITH RECOVERY
GO'''
EXEC (#Sql)
Its showing the error as incorrect syntax near '\'.
Anyone knows what is the issue is ?
GO is not a T-SQL command so you can't include it in a dynamic SQL script. GO is a batch separator interpreted by SQL Server client tools.
There is no need for the GO batch separators or dynamic SQL in here so I'm guessing the SQL in your question is actually built dynamically. There are also some other errors like misplaced quotes in your code. Below is the corrected version. I think you may need to add NORECOVERY to the RESTORE DATABASE too:
SET #Sql = 'RESTORE DATABASE [NEWS]
FILE = ''DEMO'',
FILEGROUP = ''DEMO''
FROM DISK = ''C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\DEMO_clone.bak''
WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 10;
RESTORE LOG [NEWS]
FROM DISK = ''C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\DEMO_clone.bak'';
';
I am trying to understand the REPLACE option from various sources and have not clarified myself. I am using SQL Server 2014 version.
What is the difference between below 2 queries? Both are completing without any error. With and Without Replace.
USE [master]
RESTORE DATABASE [Test] FROM DISK = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\MyDatabase.bak'
WITH FILE = 3, NOUNLOAD, STATS = 5
GO
Vs
USE [master]
RESTORE DATABASE [Test] FROM DISK = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\MyDatabase.bak'
WITH REPLACE, FILE = 3, NOUNLOAD, STATS = 5
GO
When I try to Replace with the .mdf and .ldf of an existing database (Test2), I get an error. My understanding so far is that I can restore the backup of [Test1] db with the name [Test2] (This already exists in my server and Test1 DB also exists).
I got the statement for REPLACE "Restoring over an existing database with a backup taken of another database." from one of Microsoft Link.
USE [master]
RESTORE DATABASE [Test2] FROM DISK = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\MyDatabase.bak'
WITH REPLACE, FILE = 3, NOUNLOAD, STATS = 5
GO
Error:
Msg 1834, Level 16, State 1, Line 2
The file 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\test1.mdf' cannot be overwritten. It is being used by database 'test1'.
Msg 3156, Level 16, State 4, Line 2
'test1' cannot be restored to 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\test1.mdf'. Use WITH MOVE to identify a valid location for the file.
Msg 1834, Level 16, State 1, Line 2
What is the purpose of the REPLACE option and what it replaces behind the scene. Can any one please explain with any example?
The purpose of the REPLACE option is to allow you to overwrite a database name (clobber an existing database with a different name from the backup). Your errors are caused by you trying to overwrite the files of another database from the one you asked to restore over. So restoring over Test2 database but clobbering Test1 database files (Test1.MDB and Test1.LDB). If you don't use the MOVE clause then the RESTORE command will use the same filenames as the BACKUP. Probably not a good idea otherwise things are going to get pretty confusing. (Test2 database pointing to Test1.mdb and Test1.ldb)
My script below demonstrates the issue.
I create database Test1.
I Back it up.
I try to restore it to Test2 using REPLACE. It fails, because Test1.mdb and Test1.ldb are being used by the Test1 database.
I drop the Test1 database.
I try to restore it to Test2 using REPLACE and it now works. (But is using Test1.mdb and Test1.ldb).
CREATE DATABASE [Test1]
ON PRIMARY
( NAME = N'Test1', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\Test1.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
LOG ON
( NAME = N'Test1_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\Test1_log.ldf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
GO
BACKUP DATABASE [Test1] TO DISK = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\Test1.bak' WITH COPY_ONLY, NOFORMAT, NOINIT, NAME = N'Test1-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
--Fails... It is being used by database 'Test1'.
RESTORE DATABASE [Test2] FROM DISK = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\Test1.bak'
WITH REPLACE, NOUNLOAD, STATS = 5
GO
DROP DATABASE Test1
GO
--Now works, but the files are Test1.mdf and Test1.ldf
RESTORE DATABASE [Test2] FROM DISK = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\Test1.bak'
WITH REPLACE, NOUNLOAD, STATS = 5
GO
DROP DATABASE Test2
GO
CREATE DATABASE [Test2]
ON PRIMARY
( NAME = N'Test1', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\Test2.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
LOG ON
( NAME = N'Test1_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\Test2_log.ldf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
GO
--Now the same command works, because Test1.mdf and Test1.ldf are not in use.
RESTORE DATABASE [Test2] FROM DISK = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\Test1.bak'
WITH REPLACE, NOUNLOAD, STATS = 5
GO
This is Microsoft's explanation of the REPLACE option:
https://learn.microsoft.com/en-us/sql/t-sql/statements/restore-statements-transact-sql?view=sql-server-2017#REPLACEoption
REPLACE Option Impact
REPLACE should be used rarely and only after careful consideration. Restore normally prevents accidentally overwriting a database with a different database. If the database specified in a RESTORE statement already exists on the current server and the specified database family GUID differs from the database family GUID recorded in the backup set, the database is not restored. This is an important safeguard.
The REPLACE option overrides several important safety checks that restore normally performs. The overridden checks are as follows:
Restoring over an existing database with a backup taken of another database.
With the REPLACE option, restore allows you to overwrite an existing database with whatever database is in the backup set, even if the specified database name differs from the database name recorded in the backup set. This can result in accidentally overwriting a database by a different database.
Restoring over a database using the full or bulk-logged recovery model where a tail-log backup has not been taken and the STOPAT option is not used.
With the REPLACE option, you can lose committed work, because the log written most recently has not been backed up.
Overwriting existing files.
For example, a mistake could allow overwriting files of the wrong type, such as .xls files, or that are being used by another database that is not online. Arbitrary data loss is possible if existing files are overwritten, although the restored database is complete.
The way I found is like following:
Bring your database offline -> tasks-> bring it offline
Go to your Database in the Windows Explorer and delete your mdf and log.ldf
C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\Test1.mdf
Let your Sql script run
That's it.
In general I think it is better to create a backup and restore this. In the database.
right click on database -> Tasks -> Take Offline
right click on database -> Tasks -> Restore -> Database
Select a Page -> General -> chose your file under device
Select a Page -> Options -> mark Overwrite the existing database (with replace)
Let it run
I have a Visual Studio solution with a database project which I spit out to SSMS whenever I hit Publish.
Recently I noticed that the default Data File Location, for the DB and log files, is the server's C:\ drive. Obviously it's bad practice for to store a huge database, with it's files on the C:\ drive. So I want the files at some point during the Publish moved to another drive.
This is what I am trying to do:
I hit Publish, which creates the DB and puts the DB & log files onto C:\, as usual (1)
at this point, no data has been ingested, so the DB is just an empty shell with SPs, functions, etc (2)
I then execute the code block below which puts the DB & log files onto my Y:\ drive (3)
I then execute the rest of my Post Deployment script (4)
However, the script now only gets as far completing (3). As soon as it starts (4), it hits a line which calls a procedure and then fails with
Could not find stored procedure 'dbo.usp_mySP'
If I don't run the below code, and thus not move the DB files, the whole project runs smoothly.
-- SOME CODE HERE... WORKS FINE...
-- set DB offline
ALTER DATABASE [dbName] SET OFFLINE
-- physically move the DB's primary file and lof file (using the command line)
DECLARE #cmd VARCHAR(512)
SET #cmd = 'move "C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\dbName_Primary.mdf" "Y:\SQLData"'
EXEC xp_cmdshell #cmd
SET #cmd = 'move "C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\dbName_Primary.ldf" "Y:\SQLData"'
EXEC xp_cmdshell #cmd
-- logically move the files using T-SQL
ALTER DATABASE [dbName] MODIFY FILE
(
NAME = [dbName]
,FILENAME = 'Y:\SQLData\dbName_Primary.mdf'
)
ALTER DATABASE [dbName] MODIFY FILE
(
NAME = [dbName_log]
,FILENAME = 'Y:\SQLData\dbName_Primary.ldf'
)
-- set DB online
ALTER DATABASE [dbName] SET ONLINE
-- REST OF SCRIPT HERE, INCLUDING CALL TO [dbo].[usp_mySP]... CRASHES
Try inserting a GO statement after altering the database to online.
Edit
Since that didn't do it I begin to wonder if you're executing the statements on the correct database. You might need to explicitly name the database as [database].[schema].[spname], or insert a GO statement and a use database statement right after.
I want to copy a database A into database B (same SQL Server) entirely - what would be the easiest SQL or utility command to do that? (database B should be 100% erased before the copy)
Note that it can be non-SQL thing, but in any case I need to run it as one-click. So some utility that does that is also acceptable as far as I can run copying with one click or from command line.
SQL Server 2008R2 or 2012.
Best, Askar
I made a soultion based on David's thoughts. It looks like this (Prod - source DB, Demo - destination copy)
DECLARE #backup varchar(300) = 'e:\Prod.bak';
DECLARE #logic_db_file varchar(300) = 'koe';
DECLARE #logic_log_file varchar(300) = 'koe_log';
DECLARE #out_db_file varchar(300) = 'c:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\Demo.mdf';
DECLARE #out_log_file varchar(300) = 'c:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\Demo_log.ldf';
PRINT N'Backing up Production database.'
BACKUP DATABASE Prod
TO DISK = #backup WITH FORMAT;
PRINT N'Restoring FILELISTONLY, see log file for data.'
-- Restore the files to Demo
RESTORE FILELISTONLY
FROM DISK = #backup
PRINT N'Getting exclusive access to Demo'
Alter database Demo set single_user with rollback immediate
drop database Demo
PRINT N'Restoring backup to Test database'
RESTORE DATABASE Demo
FROM DISK = #backup
WITH REPLACE,
MOVE #logic_db_file TO #out_db_file,
MOVE #logic_log_file TO #out_log_file
GO
-- if you want you can do some SQL fixes to newly made DB
PRINT N'Changing normal users to demo users, if account type is OK'
USE Demo;
UPDATE USER_ACCOUNTS SET ACCOUNT_TYPE=3 WHERE (STATUS=1) AND (ACCOUNT_TYPE=1);
GO
I am a bit confused with my issue. I have a backup file on a remote server that I need to restore locally. I can restore the file without problem but some some reason when I put the variable for the path it appends to my path the default backup location. If I were to put the path directly it works so I don't believe the shared is the problem. I included the error and a the print results of my path variable. I have copied the printed path and replaced it with my variable and it works just fine. Since the path is appended it fails of course to find the file.
My script
--Declare the Network Drive
Exec XP_CMDSHELL 'net use Y: \\ProdServer\Backups'
--Declare the Filepath
declare #Backupfilename as nvarchar(500)
declare #filename as nvarchar(40)
Set #filename = ( Select Top(1) CONVERT(VARCHAR(36),name)+'.bak' from ProdServer.msdb.dbo.backupset WITH (nolock)
where database_name='ProdDB'
order by backup_set_id desc)
Set #Backupfilename = ''''+'Y:\' + #filename + ''''
Print #backupfilename
--Start the Actual Restore
RESTORE DATABASE [TESTRestore] FROM
DISK = #BackupFileName WITH FILE = 1,
MOVE N'ProdDB' TO N'D:\Data\ProdDB_Test.mdf',
MOVE N'ProdDB_Log' TO N'D:\ProdDB_Test.ldf',
NOUNLOAD, REPLACE, STATS = 10
GO
--Clear the Defined Network Path
EXEC XP_CMDSHELL 'net use Y: /delete'
Results
'Y:\ProdDB_backup_201206220600.bak'
Msg 3201, Level 16, State 2, Line 15
Cannot open backup device 'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Backup\'Y:\ProdDB_backup_201206220600.bak''.
Operating system error 123(The filename, directory name, or volume
label syntax is incorrect.).
Msg 3013, Level 16, State 1, Line 15
RESTORE DATABASE is terminating abnormally.
Thanks
I was able to solve the problem by passing the path into a temp table and then recalling when I needed it.