Making remote database backup into local folder - sql

I call this T-SQL script against a remote SQL Server database from a batch file in my local machine:
MyBatchFile.bat:
"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE"
-S RemoteIPaddress -U username -P userPassword -i D:\MyBackups\backup_db.sql
backup_db.sql:
declare #backupfile nvarchar(255)
set #backupfile = N'D:\MyLocalBackups\' +
CONVERT(varchar(4), datepart(yy, getdate())) +
right('0' + CONVERT(varchar(2), datepart(mm, getdate())),2) +
right('0' + CONVERT(varchar(2), datepart(dd, getdate())),2) +
N'_' +
right('0' + CONVERT(varchar(2), datepart(hour, getdate())),2) +
right('0' + CONVERT(varchar(2), datepart(minute, getdate())),2) +
N'_MyDbBackup.bak'
BACKUP DATABASE MyDatabase TO DISK = #backupfile
WITH NOFORMAT, INIT, NAME = N'MyDatabase Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
And I want the backup to be placed into my local machine from where I execute it but it seems it is trying to do the backup and place it into the remote machine instead so I get below error:
Cannot open backup device 'D:\MyLocalBackups\20131011_1200_MyDbBackup.bak'. Operating system error 21(The device is not ready.).
How can I do this?
Note that .bat file and .sql file are placed in my local machines, not in the remote.

You'll need to do two things:
Share that folder on your box so it can be accessed with a UNC path like \\MachineName\MyLocalBackups\20131011_1200_MyDbBackup.bak.
Give NETWORK SERVICE full access to that folder.

Maybe you can use sp_addumpdevice
EXEC sp_addumpdevice 'disk', 'temp1', '\\MachineName\MyLocalBackups\20131011_1200_MyDbBackup.bak'
go
sqlcmd -S. -T -q BACKUP DATABASE [temp_database] TO [temp1] WITH NOFORMAT, NOINIT, NAME = N'temp_database-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
Useful:
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/21ec66c2-955d-4c9f-a805-b96c93a240d2/how-to-backup-remote-ms-sql-server-database-to-local-disk-using-sqlcmd?forum=sqltools

Related

How Do I Save SQL Server Backup with Date Filename

Hi can I convert the following code so that the backup includes the date and time in the filename.
USE SysproCompany
GO
EXEC('BACKUP DATABASE [Company] TO DISK = N''G:\SQLBackups\INSTANCE1\MonthEndBackup\Company\MonthEndBackup.bak'' WITH NOFORMAT, COPY_ONLY,INIT,
NAME = N''MonthEndBackup'', SKIP, NOREWIND, NOUNLOAD, STATS = 10
')
PRINT 'Backup of Syspro Company started'
GO
PRINT 'Backup of Syspro Company complete'
You don't need exec to begin with. Just execute
BACKUP DATABASE [Company]
TO DISK = N''G:\SQLBackups\INSTANCE1\MonthEndBackup\Company\MonthEndBackup.bak''
WITH NOFORMAT, COPY_ONLY,INIT,
NAME = N''MonthEndBackup'', SKIP, NOREWIND, NOUNLOAD, STATS = 10
You'll have to specify the file name yourself, paths don't use formatting characters or patterns. After all, different DBAs use completely different folder and naming conventions. You can calculate the name in a variable before you use it.
A far better option though, the one used by most DBAs, is to use Ola Hallengren's backup scripts to specify settings, folder and filename patterns, for multiple databases at a time.
The default pattern filename pattern is
'{ServerName}${InstanceName}_{DatabaseName}_{BackupType}_{Partial}_{CopyOnly}_{Year}{Month}{Day}_{Hour}{Minute}{Second}_{FileNumber}.{FileExtension}',
A single command can be used to perform multiple operations, eg both backup all user databases and verify the backups, and clean up old backups :
EXECUTE dbo.DatabaseBackup
#Databases = 'USER_DATABASES',
#Directory = 'C:\Backup',
#BackupType = 'FULL',
#Verify = 'Y',
#Compress = 'Y',
#CheckSum = 'Y',
#CleanupTime = 24
Try this:
EXEC('BACKUP DATABASE [Company] TO DISK = N''G:\SQLBackups\INSTANCE1\MonthEndBackup\Company\MonthEndBackup' + CURRENT_TIMESTAMP + '.bak'' WITH NOFORMAT, COPY_ONLY,INIT,
NAME = N''MonthEndBackup'', SKIP, NOREWIND, NOUNLOAD, STATS = 10
')

Dynamic SQL to backup DB and copy to different locations based on day

We take daily backups of all DB's. There isn't enough space on the server so we copy it to a different server and also a different disk based on what day it is. i.e
Day 1 goes to \\SERVER2\E:\SqlBackups\Day1
Day 2 goes to \\SERVER2\E:\SqlBackups\Day2
Day 3 goes to \\SERVER2\E:\SqlBackups\Day3
Day 4 goes to \\SERVER2\H:\SqlBackups\Day4
Day 5 goes to \\SERVER2\H:\SqlBackups\Day5
etc
I want to use dynamic SQL and CMD but its not working, it either can't find the path or says the credentials are wrong even though the account has access to the shared drive
I've now decided to try getting the CMD to call a .bat file to do the copy but i'm not really familiar with how to do this.
I can obviously create a simple copy statement, but i do not know how to include the parameters etc
DECLARE #SQL NVARCHAR(MAX)
DECLARE #Location nvarchar(200)
DECLARE #Day int
SET #Day = DATEPART(dw, getdate())
IF #Day in (1,2,3) SET #Location =
'\\Server2\BackUps\SqlBackups\'
IF #Day in (4,5,6,7) SET #Location =
'\\Server\BackUps2\SqlBackups2\'
SET #Location = #Location + 'Day'+ cast(#Day as nvarchar(1)) + '\'
SET #Location = #Location + 'DB1.bak'
SET #SQL = 'master..xp_cmdshell ''copy /Y
F:\SqlBackups\LatestToCopyToServer2\DB1.bak ' + #location +
''''
EXEC #SQL
The System cannot find the path specified.
if i just do a select the string looks good to me ...
master..xp_cmdshell 'copy /Y F:\SqlBackups\LatestToCopyToServer2\DB1.bak
\Server2\BackUps\SqlBackups\Day5\DB1.bak'
To clarify i need assistance with the batch file and what to include :)

Sending query results via email via email attachment every first day of every month on SQL Server 2012

My requirement:
Send the query result via email attachment on first day of every month.
The work I've been doing manually:
I have to run this query every first day of each month by changing the date range.
Then I export the result acquired in .csv format and send this csv file as an attachment
I needed suggestions from you people on how shall I automate this process:
Shall I set up a Job on SQL Server 2012, but yes, the I'll have to modify the date range.
Please suggest on how to move forward.
Any help, much appreciated.
As you mentioned, Create a Job and schedule it to run on first day of every month. Considering you have enough knowledge on creating a job.
Go to Job properties -> schedules -> and make the following setting
Occurs every first day of every 1 month(s) at 12:00:00. Schedule will
be used starting on 07-12-2016.
Change the timing(at which time it should run on first day of month) based on your business requirement. It can be set under Daily frequency-> Occurs once at:
This process can also be automated by another way by using a Windows batch file.You can schedule it using Windows scheduler.
Below will be contents of batch file
Echo off
sqlcmd -u <username> -p <password> -S <server name> -d <database name> -i <sql file location> -o <output result file location>
Powershell.exe -executionpolicy remotesigned -File <location of powershell file>
The powershell file trigger an email when bat file is run.
Contents of powershell file
$smtpserver = "<smtp server name>"
$from="mail id"
$to="<mail id"
$a = Get-Date
$subject= "<subject line> `r"+ $a.Month +"/"+$a.Day +"/"+ $a.Year
$body=""
$attachment="File location"
Thanks,`n "
$mailer = new-object Net.Mail.SMTPclient($smtpserver)
$msg = new-object Net.Mail.MailMessage($from,$to,$subject,$body,$data1,$a)
$msg.IsBodyHTML = $true
$mailer.send($msg)
I use SQL Agent for send results via email like this:
/*
First you should set up SQL Mail Profile.
Please change #dbName, #SQLscript, #mailbody and mail account values. When changing your #SQLscript value be careful that replace (with CTRL+H) single quota (') to double quotas ('').
*/
DECLARE #dbName nvarchar(50), #SQLscript nvarchar(4000), #subject varchar(100), #mailfrom varchar(100), #mailbody nvarchar(4000), #jobName varchar(100)
SELECT #jobName = name from msdb..sysjobs where job_id = $(ESCAPE_NONE(JOBID))
SELECT #mailfrom = ##SERVICENAME + ' <' + cast(SERVERPROPERTY('ComputerNamePhysicalNETBIOS') as varchar(50)) + '#domain.com>'
SELECT #subject = N'SQL Server Job Result [Job: ' + #jobName + ']'
SELECT #dbName = 'Database'
SELECT #SQLscript = '
INSERT INTO [Database].[Schema].[Table] (
Column1
,Column2
) VALUES (
''Value1''
,''Value2'' )
'
SELECT #mailbody = N'
Depending on case number 1234-5678-90 your script executed on <b>' + ##SERVERNAME + N'</b> instance and <b>' + #dbName + '</b> database. Script info and results are shown below. <br><br>' +
'<b>Script: </b><br>' + #SQLscript + '<br><br>' +
'<b>Result: </b><br>'
EXEC msdb.dbo.sp_send_dbmail
#profile_name = 'sqlmailprofile',
#recipients = '<mail1#domain.com>;<mail2#domain.com>',
#copy_recipients = '<mail3#domain.com>',
#from_address = #mailfrom,
#reply_to = '<mail3#domain.com>',
#subject = #subject,
#body = #mailbody,
#body_format = 'HTML',
#importance = 'HIGH',
#execute_query_database = #dbName,
#query = #SQLscript
/* If you want to send results with attached file:
#attach_query_result_as_file = 1,
#query_attachment_filename = 'script_output.csv',
#query_result_separator=#tab,
#query_result_width =32767,
#query_result_no_padding=1,
#exclude_query_output=1,
#query_result_header=1
*/

Passing in a date variable or check if no date is passed in then use getdate()

I would like to pass in a date variable using sqlcmd and do a checking condition where if there is no date passing in, then set the variable to getdate().
Can anyone advise me on this? Thank you. Below is my sql script.( the getdate() part should be modify)
--Declare variable to store back up file location
DECLARE #DBBackupFile as nvarchar(128);
SET #DBBackupFile = N'C:\sqlbackup\MOL_POSHistory\MOL_POSHistory_backup_' + convert(varchar(12),(year(GETDATE()) * 10000) + (month(GETDATE()) * 100) + Day(GETDATE()) -4 ) + N'0201.bak';
--Retrive the Logical file name of the database from backup.
RESTORE FILELISTONLY
FROM DISK = #DBBackupFile
GO
--Make Database to single user Mode
ALTER DATABASE [MOL_POSHistory]
SET SINGLE_USER WITH
ROLLBACK IMMEDIATE
--Restore Database
DECLARE #DBBackupFile as nvarchar(128);
SET #DBBackupFile = N'C:\sqlbackup\MOL_POSHistory\MOL_POSHistory_backup_' + convert(varchar(12),(year(GETDATE()) * 10000) + (month(GETDATE()) * 100) + Day(GETDATE()) -4 ) + N'0201.bak';
USE master;
RESTORE DATABASE [MOL_POSHistory] FROM DISK = #DBBackupFile WITH FILE = 1,
MOVE N'MOL_POSHistory' TO N'D:\SQLData01\MOL_POSHistory.mdf',
MOVE N'MOL_POSHistory_log' TO N'F:\SQLLog\MOL_POSHistory.ldf',
NOUNLOAD, REPLACE, STATS = 10
--Set database to multi user mode
ALTER DATABASE [MOL_POSHistory] SET MULTI_USER
GO
You will need to call the SQLCMD like this making use of the –v parameter:
// Date format is YYYYMMDD
sqlcmd -S YOUR_SERVER -v inputDate="20010101" -i "YOUR_INPUT_FILE" -E
You can access the parameters passed in by SQLCMD (inputDate in this example) like this:
DECLARE #inputDate NVARCHAR(50)
DECLARE #date DATETIME
SET #inputDate = '$(inputDate)'
IF (LEN(ISNULL(#inputDate, '')) = 0) BEGIN
SET #date = GETDATE()
PRINT 'Using default date'
END
ELSE BEGIN
SET #date = #inputDate
PRINT 'Using varaible date'
END

Add date to SQL database backup filename

I'm using the below to backup a db from a SQL job. Can someone tell me how to add the current date to the output filename? Preferably in YYYYMMDD format.
BACKUP DATABASE [myDB] TO  DISK = N'\\myPath\myDB.bak' WITH NOFORMAT, INIT,  NAME = N'myDB', SKIP, REWIND, NOUNLOAD,  STATS = 10
GO
Thanks!
DECLARE #MyFileName varchar(1000)
SELECT #MyFileName = (SELECT '\\ServerToSave\Path\MyDB_' + convert(varchar(500),GetDate(),112) + '.bak')
BACKUP DATABASE [myDB] TO DISK=#MyFileName ...
If you want to include the date and time, so you can use:
DECLARE #MyFileName varchar(200)
SELECT #MyFileName='\\ServerToSave\Path\MyDB_' + REPLACE(convert(nvarchar(20),GetDate(),120),':','-') + '.bak'
BACKUP DATABASE [myDB] TO DISK=#MyFileName ...
The 120 in the Convert gives you the yyyy-mm-dd hh:mi:ss(24h)
The REPLACE function is necessary because the filename can not have the : character.
Try this.
DECLARE #MyFileName varchar(50)
SELECT '\\ServerToSave\Path\MyDB_' + convert(nvarchar(20),GetDate(),112) + '.bak'
BACKUP DATABASE [myDB] TO DISK=#MyFileName ...
The 112 in the Convert gives you the YYYYMMDD format
Use the following
DECLARE #BackupFileName varchar(20)
SELECT #BackupFileName = '\\ServerName\SharedFolder\DatabaseName_' + CONVERT (VarChar, GetDate(), 112) + '.bak'
BACKUP DATABASE [myDB] TO DISK = #BackupFileName WITH NOFORMAT, INIT, NAME = N'myDB', SKIP, REWIND, NOUNLOAD, STATS = 10
Read up on Cast and Convert here http://msdn.microsoft.com/en-us/library/ms187928.aspx
Maybe you want to use windows task, just put this code in a .BAT file and add to your Windows tasks:
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%"
set "fullstamp=%YYYY%%MM%%DD%-%HH%%Min%%Sec%"
set bkfile=D:\bk-sqlserver\dbname%fullstamp%.bak
set path_sqlcmd="C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\110\Tools\Binn\SQLCMD.exe"
%path_sqlcmd% -S .\SQLEXPRESS -E -Q "BACKUP DATABASE dbname TO DISK='%bkfile%' WITH FORMAT"
It's a bit long, but i think it's a practical solution.
Use sqlcmd for SQL Server 2005 or later
Use osql for SQL Server 2000 or oldies
DECLARE #var nvarchar(max) ='C:\Projects\myDatabase ' +replace(rtrim(convert(char,getdate())), ':',',')+'.bak';
BACKUP DATABASE myDatabase TO DISK = #var
output:
C:\Projects\myDatabase Jun 3 2015 6,33AM.bak
You can use any of them.
These Are Sample For Use Date And DateTime In Backup Database:
SELECT 'TestDb' + '_'+CAST(CAST(GETDATE() AS datetime2) AS NVARCHAR(22))+
'_Log.trn';--TestDb_2019-09-28 13:54:42.54_Log.trn
SELECT 'TestDb' + '_'+CAST(CAST(GETDATE() AS DATE) AS NVARCHAR(MAX))+
'_Log.trn';--TestDb_2019-09-28_Log.trn
SELECT 'TestDb' + '_'+CAST(sysdatetime() as nvarchar(max))+ '_Log.trn';--TestDb_2019-09-28 13:54:42.5536994_Log.trn
SELECT 'TestDb'+'_' + convert(varchar(500),GETDATE(),120) + '_Log.trn';--TestDb_2019-09-28 13:54:42_Log.trn
SELECT 'TestDb'+'_' + convert(varchar(500),GETDATE(),112) + '_Log.trn';--TestDb_20190928_Log.trn
SELECT 'TestDb' + '_'+CAST(FORMAT(getdate(), N'yyyy-MM-ddThh:mm:ss') as nvarchar(max))+ '_Log.trn';--TestDb_2019-09-28T02:08:38_Log.trn