partitioned Database Restore issue - sql-server

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'';
';

Related

SSIS Restore Database with Dynamic File Name

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)

SQL Server 2014 Create a Copy of an Existing Database

I've been trying to make a copy of a SQL Server Database (2014) and the recommended way to do this using SQL Server Management Studio seems to be the following.
Right Click Database >
Tasks >
Generate Scripts >
Advanced (Schema and Data) (Single file per object)
Then I have to update the references to the database name to use the new database name.
This won't work for me though because some of the object files it outputs can be over a GB which means I can't open the file to change the database name.
Is there another way to create a copy of a database to a new database with a different name?
I use this script for that.
declare #nameSuffix varchar(50) = 'DB_NEW_NAME'
declare #path varchar(250) = 'C:\Program Files\Microsoft SQL Server\YOUR PATH\MSSQL\'
declare #backupfile varchar(250) = #path + 'Backup\' + #nameSuffix + '.bak'
declare #moveFile varchar(300) = #path + 'DATA\' + #nameSuffix + '.mdf'
declare #moveLogFile varchar(300) = #path + 'DATA\' + #nameSuffix + '_log.ldf'
backup database DB1
to disk = #backupfile
with init, noformat, skip, stats=10
use master
restore database DB_NEW_NAME
from disk = #backupfile
with replace,
recovery,
move 'DB1' to #moveFile,
move 'DB1_Log' to #moveLogFile
you can copy the database by:
right click database to be copied > tasks > copy database
the database wizard will guide you to create your new copy.
more resources here: https://msdn.microsoft.com/en-us/library/ms188664.aspx

Restore SQL Database with Replace option

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

Management Studio Diffrent files after backup

I have database in SQL Server Managment Studio. I make a backup of my database using this script:
use mydatabase
BACKUP DATABASE mydatabase
TO DISK = 'D:\mydatabase\backup.BAK'
GO
BACKUP DATABASE mydatabase
TO DISK = 'E:\mydatabase\work.BAK'
GO
My problem is that the files backup.BAK and work.BAK have the same size. I check every byte and this files are not the same. Did anyone know why?
Depending on the size of your database, it may take a while to generate the backup. Depending on the activity, a lot can change in the database during this time. To create exact copies of your backup file, you should just copy the first backup file. You can do this in SQL, for example:
DECLARE #SourceFile AS VARCHAR(500);
DECLARE #DestinationFile AS VARCHAR(500);
DECLARE #Cmd AS VARCHAR(500);
BACKUP DATABASE mydatabase
TO DISK = 'D:\mydatabase\backup.BAK'
GO
SET #SourceFile = 'D:\mydatabase\backup.BAK'
SET #DestinationFile = 'E:\mydatabase\work.BAK'
SET #Cmd = 'COPY ' + #SourceFile + ' ' + #DestinationFile;
EXEC master.dbo.xp_cmdshell #Cmd;

How can I copy an entire database to another on the same server?

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

Resources