Problems with Path Variable for Restore - sql-server

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.

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 Bulk Copy dynamic script

I've quite a bunch of CSV files I would like to import into a SQL Server database. Each of these files contain over 50 million rows which I need to import into a single table called ControlExperimentTable.
A total of 500 of these files will be sent to me over the next few weeks to import into the database, so I wrote a script to automate the process it is obviously long and cumbersome.
In a nutshell, the process works as follows -- CSV files are copied into a repository folder for processing. All files have the same prefix and a unique suffix e.g ExportData0001.txt, ExportData0002.txt, ExportData0003.txt, ExportData0004.txt, etc.
The script sequentially processes each file, importing its contents into the SQL Server database. After all rows have been imported, the processed file is then moved to an archive folder, a full database backup is taken and the process moves on to the next file.
The following is the code I'm using to accomplish the task:
--Int variable declaration section.
DECLARE #totalFilesToProcess INT = 500 /*The number of files in the repository.*/
DECLARE #count INT = 0
--VarChar variable declaration section.
DECLARE #sqlBulkInsertCommand VARCHAR(255)
DECLARE #sqlMoveCommand VARCHAR(255)
DECLARE #sourceFilename VARCHAR(255)
DECLARE #errorFilename VARCHAR(255)
DECLARE #suffix VARCHAR(4)
--Ensure that the xp_cmdshell server configuration option is enabled.
EXEC master.dbo.sp_configure 'show advanced options', 1
RECONFIGURE
EXEC master.dbo.sp_configure 'xp_cmdshell', 1
RECONFIGURE
--Change to the target database instance.
USE [DataCollectionTable]
--Set the script to loop the number of times as there are as may files to import
WHILE (#count <= #totalFilesToProcess)
BEGIN
--Set variables.
SET #count = #count + 1
SET #suffix = RIGHT('0000' + CAST(#count AS VARCHAR(4)), 4)
SET #errorFilename = FORMATMESSAGE('E:\SharedDocs\ControlExportData%s.csv', #suffix)
SET #sourceFilename = FORMATMESSAGE('E:\SharedDocs\ControlExportData%s.txt', #suffix)
--COMMAND CONSTRUCT: Insert data from flat file into the ControlExperimentTable table.
SET #sqlBulkInsertCommand = FORMATMESSAGE('BULK INSERT ControlExperimentTable FROM ''%s'' WITH (FIRSTROW = 2, FIELDTERMINATOR = '','', ROWTERMINATOR = ''\n'', ERRORFILE = ''%s'', TABLOCK)', #sourceFilename, #errorFilename)
--COMMAND CONSTRUCT: Move the source file to the archive folder.
SET #sqlMoveCommand = FORMATMESSAGE('MOVE E:\SharedDocs\ControlExportData%s.txt E:\SharedDocs\Archive\ControlExportData%s.txt', #suffix, #suffix)
--Display record count before every update.
SELECT sys.sysindexes.rows FROM sys.sysindexes INNER JOIN sys.sysobjects
ON sys.sysobjects.id=sys.sysindexes.id
WHERE sys.sysindexes.first IS NOT NULL AND sys.sysobjects.name = 'ControlExperimentTable'
--Execute the BULK INSERT command.
EXEC #sqlBulkInsertCommand
--Execute the source file MOVE command.
EXEC master.dbo.xp_cmdshell #sqlMoveCommand
--Backup database after each commitment, maintaining the current and previous copies.
IF (#count % 2) = 0
BEGIN
BACKUP DATABASE [ExperimentDataCollection] TO DISK = N'E:\Backups\ExperimentDataCollectionBackup-01.bak' WITH NOFORMAT, INIT, NAME = N'ExperimentDataCollection-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
END ELSE
BEGIN
BACKUP DATABASE [ExperimentDataCollection] TO DISK = N'E:\Backups\ExperimentDataCollectionBackup-02.bak' WITH NOFORMAT, INIT, NAME = N'ExperimentDataCollection-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
END
END
After running this code, I'm getting the following error:
Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
Configuration option 'xp_cmdshell' changed from 1 to 1. Run the RECONFIGURE statement to install.
Msg 911, Level 16, State 4, Line 48
Database 'BULK INSERT ControlExperimentTable FROM 'E:\SharedDocs\ExportData0001' does not exist. Make sure that the name is entered correctly.
Completion time: 2021-02-18T18:06:15.0003210+02:00
Mind you, everything is where they are supposed to be and correctly specified in the code. So much so that manually running the following code, which is exactly what I'm trying to parse works without a hassle.
USE [ExperimentDataCollection]
BULK INSERT [ExperimentDataCollection].[dbo].[ControlExperimentTable]
FROM 'E:\SharedDocs\ControlExportData0001.txt'
WITH (FIRSTROW = 2,
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n',
ERRORFILE = 'E:\SharedDocs\ControlExportData0001.csv',
TABLOCK)
Where is it I'm going wrong?
When executing dynamic sql, you need to wrap the variable in parentheses. So change this:
EXEC #sqlBulkInsertCommand
to this:
EXEC(#sqlBulkInsertCommand)

partitioned Database Restore issue

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

How to get .bak file name automatically from directory to restore?

I have used below script to restore databases where I have given .bak file name manually. I need to do the automate process to restore databses. so I tried using stored procedure with xp_DirTree to get .bak file name from remote server folder. but stored procedure executing with no results. when I tried the local path I can able to see .bak files into folder. at first I thought it is permission issue but permissions are fine. could anyone suggest me what is the error causing?
script used to restore databases:
CREATE TABLE #CustomerrestoreFiles(
backupfile VARCHAR(100))
--Drop Table #CustomerrestoreFiles (backupfile)
VALUES
('Customer_backup_2016_09_15_203001_9888161'),
('Customer_backup_2016_10_10_203001_7101588'),
('Customer_backup_2016_10_14_203001_6621303'),
('Customer_backup_2016_10_15_203001_5397847'),
('Customer_backup_2016_10_16_203002_0291343'),
('Customer_backup_2016_10_17_203002_2861353')
DECLARE #CustomerDBfileToRestore VARCHAR(100), #backupLocation varchar(500), #mdfLocation varchar(500), #ldfLocation varchar(500)
DECLARE restorecursor CURSOR FOR
SELECT backupfile FROM #CustomerrestoreFiles
OPEN restorecursor
FETCH NEXT FROM restorecursor
INTO #CustomerDBfileToRestore
WHILE ##FETCH_STATUS = 0
BEGIN
SET #backupLocation = 'F:\Customer bak files' + '\' + #CustomerDBfileToRestore + '\' + #CustomerDBfileToRestore +'.bak'
SET #mdfLocation = 'F:\Files\Customer_Restore_Files\' + #CustomerDBfileToRestore + '.mdf'
SET #ldfLocation = 'F:\Files\Customer_Restore_Files\' + #CustomerDBfileToRestore + '.ldf'
RESTORE DATABASE #CustomerDBfileToRestore
FROM DISK = #backupLocation
WITH FILE = 1,
MOVE 'Customer_Data' TO #mdfLocation,
MOVE 'Customer_Log' TO #ldfLocation,
NOUNLOAD, REPLACE, STATS = 1
FETCH NEXT FROM restorecursor
INTO #CustomerDBfileToRestore
END
CLOSE restorecursor
DEALLOCATE restorecursor
I bet this is a mapped network drive issue. The drive can't be seen by the sql user. Try UNC naming instead. The article below may prove useful.
How to backup a database to a network drive

Getting following error when executing the SP which creates backup and restores it with new name

Could any one help me finding the error in the below SP.
USE [master]
GO
/****** Object: StoredProcedure [dbo].[CopyDB] Script Date: 08/22/2011 12:20:33 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[CopyDB](#DBName varchar(100),#Newname varchar(100))
as
DECLARE #FileName AS nvarchar(4000)
set #FileName = 'D:\'+#DBName+'.bak'
/*Backup the database*/
BACKUP DATABASE #DBName
TO DISK = #FileName
WITH CHECKSUM, INIT;
/*to restore it with new name*/
declare #st1 varchar(100)
declare #st2 varchar(100)
set #st1 = 'C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA\'+#Newname+'.mdf';
set #st2 = 'C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA\'+#Newname+'_log.LDF';
declare #DBName_Log varchar(100)
set #DBName_Log = #DBName+'_Log'
RESTORE database #Newname
FROM DISK = #FileName
with
MOVE #DBName TO #st1,
MOVE #DBName_Log TO #st2,
CHECKSUM;
I am getting the below error
Msg 5133, Level 16, State 1, Procedure CopyDB, Line 34
Directory lookup for the file "C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA\back.mdf" failed with the operating system error 3(The system cannot find the path specified.).
Msg 3156, Level 16, State 3, Procedure CopyDB, Line 34
File 'pubs' cannot be restored to 'C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA\back.mdf'. Use WITH MOVE to identify a valid location for the file.
Msg 5133, Level 16, State 1, Procedure CopyDB, Line 34
Directory lookup for the file "C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA\back_log.LDF" failed with the operating system error 3(The system cannot find the path specified.).
Msg 3156, Level 16, State 3, Procedure CopyDB, Line 34
File 'pubs_log' cannot be restored to 'C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA\back_log.LDF'. Use WITH MOVE to identify a valid location for the file.
Msg 3119, Level 16, State 1, Procedure CopyDB, Line 34
Problems were identified while planning for the RESTORE statement. Previous messages provide details.
Msg 3013, Level 16, State 1, Procedure CopyDB, Line 34
RESTORE DATABASE is terminating abnormally.
Did you check this path:
C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA\
?
Does it exist?
Try to restore your DB to another place (just for experiment).

Resources