How to run multiple SQL scripts, in SSMS, against SQL Azure? - azure-sql-database

I would like to execute multiple SQL (*.sql) TSQL script files, in SSMS, against a SQL Azure DB. I happen to be using SSMS 2008 R2
The code, I tried to execute in a SSMS query window, linked to the relevant DB instance, as picked up from a previous SO question, was :
/*
execute a list of .sql files against the server and DB specified
*/
SET NOCOUNT ON
SET XACT_ABORT ON
BEGIN TRAN
DECLARE #DBServerName VARCHAR(100) = 'DBServerName '
DECLARE #DBName VARCHAR(100) = 'DBName'
DECLARE #FilePath VARCHAR(200) = 'c:\temp\scripts'
/*
create a holder for all filenames to be executed
*/
DECLARE #FileList TABLE (Files NVARCHAR(MAX))
INSERT INTO #FileList VALUES ('script1.Sql')
INSERT INTO #FileList VALUES ('script2.Sql')
INSERT INTO #FileList VALUES ('script3.Sql')
WHILE (SELECT COUNT(Files) FROM #FileList) > 0
BEGIN
/*
execute each file one at a time
*/
DECLARE #FileName NVARCHAR(MAX) = (SELECT TOP(1) Files FROM #FileList)
DECLARE #command VARCHAR(500) = 'sqlcmd -S ' + #DBServerName + ' -d ' + #DBName + ' -i "' + #FilePath + #Filename +'"'
EXEC xp_cmdshell #command
PRINT 'EXECUTED: ' + #FileName
DELETE FROM #FileList WHERE Files = #FileName
END
COMMIT TRAN
Unfortunately SQL Azure does not support "xp_cmdshell".
How can I execute multiple SQL scripts for an Azure SQL instance?
Thanks in advance.
P.S I am aware of how one can open a file in SSMS

When using SSMS the script is send to the server and then executed there. As I mentioned in the comment in SQL Database the server does not have access to files on the machines they are hosted on nor can you actually upload them to these machines. So you approach does not work. Opening files that you have locally on your machine is also not possible.
To execute a set of scripts from your local machine against a SQL Database you have to translate your SQL script for example into a PowerShell script:
Get-ChildItem "c:\temp\scripts" -Filter script*.sql | `
Foreach-Object{
Write-Host 'Executing' $_.FullName
sqlcmd -U <username>#<server> -P <Password> -S <server>.database.windows.net -d <DatabaseName> -i $_.FullName
}

Related

How to execute sql file using another sql file MSQL

Im creating database which need few sql scripts. Running them one by one is not effective , so I wanted to create main sql query which will load all files. I tried this :
Declare
#DBServerName Varchar(100),
#DBName Varchar(100),
#FilePathName Varchar(100),
#strSql varchar(1000)
Set #DBServerName='USER-PC'-- Server Name
Set #DBName='testo' -- DB Name
Set #FilePathName='some path here'
Set #strSql= 'sqlcmd -S ' + #DBServerName + ' -d ' + #DBName + ' -i ' + #FilePathName
EXEC xp_cmdshell #strSql
After executing this, It is showing that my query was executed succesfully but in my database nothing is appearing. Ive seen lot of websites but there is no working answear.
I don't think you want xp_cmdshell here. If you want to execute dynamic SQL you should be using the code below:
sp_executesql #strsql;

Using bcp utility to export SQL queries to a text file

I debug a stored procedure (SQL Server 2005) and I need to find out some values in a datatable.
The procedure is run by an event of the application and I watch just the debugging output.
I do the following my stored procedure (SQL Server 2005), I took a system table (master.dbo.spt_values) as example:
set #logtext = 'select name, type from master.dbo.spt_values where number=6'
--set #logtext = 'master.dbo.spt_values'
SET #cmd = 'bcp ' + #logtext + ' out "c:\spt_values.dat" -U uId -P uPass -c'
EXEC master..XP_CMDSHELL #cmd
So, when I uncomment the second like everything works, a file apprears on the C:\ drive... but if I coment it back leaving only the first line, any output is generated.
How to fix this problem?
bcp out exports tables.
To export a query use queryout instead - you'll need to wrap your query in "double quotes"
set #logtext = '"select name, type from master.dbo.spt_values where number=6"'
--set #logtext = 'master.dbo.spt_values'
SET #cmd = 'bcp ' + #logtext + ' queryout "c:\spt_values.dat" -U uId -P uPass -c'
EXEC master..XP_CMDSHELL #cmd
http://msdn.microsoft.com/en-us/library/ms162802.aspx

Microsoft SQL xp_cmdshell doesn't like filenames with spaces. Can I replace the space with something else?

I have this TSQL code that dumps data from tables using BCP. It looks complicated, but it simply creates a #command string to be executed once for each table, then BCP dump the table records to disk. It's a nice way to backup all the table data quickly. Below I show the resolved version which is a little easier to read.
set #command =
'if (''?'' <> ''[dbo].[sysdiagrams]'')
BEGIN;
create table #result (result nvarchar(2048) null );
declare #temp nvarchar(1000);
set #temp = ''' + #bcpPath + ' ' + #database + '.dbo.'' +
substring( ''?'', 8, len(''?'')- 8) +
'' out "' + #driveLetter + #drivePath +
'\'' + substring( ''?'', 8, len(''?'')- 8) +
''.out" -c -x -t"|" -Uuser -Ppassword'';
insert into #result (result)
exec xp_cmdshell #temp;
drop table #result;
END;'
exec sp_msforeachtable #command
the #bcppath is C:\Program Files\Microsoft SQL Server\90\Tools\Binn\bcp.exe which has a space.
Without using double quotes around the path "", it gives an error of 'C:\Program' is not recognized... With using double quotes, it gives the same error. With using double double quotes "" "", it says The filename, directory name, or volume label syntax is incorrect.
#command resolves to this when printed:
if ('?' <> '[dbo].[sysdiagrams]')
BEGIN;
create table #result (result nvarchar(2048) null );
declare #temp nvarchar(1000);
set #temp = '"C:\Program Files\Microsoft SQL Server\90\Tools\Binn\bcp.exe"
myDB.dbo.' +
substring( '?', 8, len('?')- 8) +
' out "E:\DataExports\' +
substring( '?', 8, len('?')- 8) + '.out" -c -x -t"|" -Uuser -Ppassword';
insert into #result (result)
exec xp_cmdshell #temp;
drop table #result;
END;
EDIT:
Oddly, I put an ECHO ? && in front of the "path" and it worked (surrounded by double quotes.) .... Why?
You have to put something before quoted path to avoid error C:\Program' is not recognized... so I used CALL statement and it worked for me ...
declare #cmd nvarchar(1000)
set #cmd = 'call "C:\Program Files\Microsoft SQL Server\90\Tools\Binn\bcp.exe" myDB.dbo.'
exec xp_cmdshell #cmd
Try specifying the short name for the parts of the path containing spaces For example, PROGRA~1 rather than Program Files. So, your first path would be something like C:\PROGRA~1\MI6841~1\90\Tools\Binn\bcp.exe. If you don't have any spaces, you should be able to drop the quotes.
If you perform a dir /x in the directory containing the long directory/file names you can obtain the short 8.3 name.
As workaround, you could use subst.
subst p: "C:\Program Files\Microsoft SQL Server\"
so you didn't need the spaced path anymore.
Or you try to find out why it fails.
exec xp_cmdshell 'cmd /c echo %cmdcmdline% "C:\Program Files\Microsoft SQL Server\90\Tools\Binn\bcp.exe"'
The cmdcmdline should show you the complete command, if the quotes are already there this should work
exec xp_cmdshell 'cmd /c "C:\Program Files\Microsoft SQL Server\90\Tools\Binn\bcp.exe" <the rest of your command>'
This weird construction also working:
exec xp_cmdshell '""%ProgramFiles%\WinRAR\"rar.exe a -v20M "C:\test\test.rar" "C:\test\data\""'

Is it possible to execute a text file from SQL query?

I have a number of generated .sql files that I want to run in succession. I'd like to run them from a SQL statement in a query (i.e. Query Analyzer/Server Management Studio).
Is it possible to do something like this and if so what is the syntax for doing this?
I'm hoping for something like:
exec 'c:\temp\file01.sql'
exec 'c:\temp\file02.sql'
I am using SQL Server 2005 and running queries in management studio.
use xp_cmdshell and sqlcmd
EXEC xp_cmdshell 'sqlcmd -S ' + #DBServerName + ' -d ' + #DBName + ' -i ' + #FilePathName
Very helpful thanks, see also this link:
Execute SQL Server scripts
for a similar example.
To turn xp_cmdshell on and off see below:
On
SET NOCOUNT ON
EXEC master.dbo.sp_configure 'show advanced options', 1
RECONFIGURE
EXEC master.dbo.sp_configure 'xp_cmdshell', 1
RECONFIGURE
Off
EXEC master.dbo.sp_configure 'xp_cmdshell', 0
RECONFIGURE
EXEC master.dbo.sp_configure 'show advanced options', 0
RECONFIGURE
SET NOCOUNT OFF
Or just use openrowset to read your script into a variable and execute it (sorry for reviving an 8 years old topic):
DECLARE #SQL varchar(MAX)
SELECT #SQL = BulkColumn
FROM OPENROWSET
( BULK 'MeinPfad\MeinSkript.sql'
, SINGLE_BLOB ) AS MYTABLE
--PRINT #sql
EXEC (#sql)
This is what I use. Works well and is simple to reuse. It can be changed to read all files in the directory, but this way I get to control which ones to execute.
/*
execute a list of .sql files against the server and DB specified
*/
SET NOCOUNT ON
SET XACT_ABORT ON
BEGIN TRAN
DECLARE #DBServerName VARCHAR(100) = 'servername'
DECLARE #DBName VARCHAR(100) = 'db name'
DECLARE #FilePath VARCHAR(200) = 'path to scrips\'
/*
create a holder for all filenames to be executed
*/
DECLARE #FileList TABLE (Files NVARCHAR(MAX))
INSERT INTO #FileList VALUES ('script 1.sql')
INSERT INTO #FileList VALUES ('script 2.sql')
INSERT INTO #FileList VALUES ('script X.sql')
WHILE (SELECT COUNT(Files) FROM #FileList) > 0
BEGIN
/*
execute each file one at a time
*/
DECLARE #FileName NVARCHAR(MAX) = (SELECT TOP(1) Files FROM #FileList)
DECLARE #command VARCHAR(500) = 'sqlcmd -S ' + #DBServerName + ' -d ' + #DBName + ' -i "' + #FilePath + #Filename +'"'
EXEC xp_cmdshell #command
PRINT 'EXECUTED: ' + #FileName
DELETE FROM #FileList WHERE Files = #FileName
END
COMMIT TRAN
I wouldn't recommended doing this, but if you really have to then the extended stored procedure xp_cmdshell is what you want. You will have to first read the contents of the file into a variable and then use something like this:
DECLARE #cmd sysname, #var sysname
SET #var = 'Hello world'
SET #cmd = 'echo ' + #var + ' > var_out.txt'
EXEC master..xp_cmdshell #cmd
Note: xp_cmdshell runs commands in the background, because of this, it must not be used to run programs that require user input.
Take a look at OSQL. This utility lets you run SQL from the command prompt. It's easy to get installed on a system, I think it comes with the free SQL Server Express.
Using the osql Utility
A qick search of "OSQL" on stack overflow shows a lot of stuff is available.
The main thing to handle properly is the user and password account parameters that get passed in on the command line. I have seen batch files that use NT file access permissions to control the file with the password and then using this file's contents to get the script started. You could also write a quick C# or VB program to run it using the Process class.
For Windows Authentication, if you are running as another user:
Open Command Prompt as your Windows user (Right click on it, Open File Location, Shift + Right Click, Run as a different user)
sqlcmd -S localhost\SQLEXPRESS -d DatabaseName-i "c:\temp\script.sql"
Or if you are using Sql Server user:
sqlcmd -S localhost\SQLEXPRESS -d DatabaseName-i "c:\temp\script.sql" -U UserName -P Password
Replace localhost\SQLEXPRESS with you server name if not local server.
Open windows command line (CMD)
sqlcmd -S localhost -d NorthWind -i "C:\MyScript.sql"
For anybody stumbling onto this question like I did and might find this useful, I liked Bruce Thompson's answer (which ran SQL from files in a loop), but I preferred Pesche Helfer's approach to file execution (as it avoided using xp_cmdshell).
So I combined the two (and tweaked it slightly so it runs everything from a folder instead of a manually created list):
DECLARE #Dir NVARCHAR(512) = 'd:\SQLScriptsDirectory'
DECLARE #FileList TABLE (
subdirectory NVARCHAR(512),
depth int,
[file] bit
)
INSERT #FileList
EXEC Master.dbo.xp_DirTree #Dir,1,1
WHILE (SELECT COUNT(*) FROM #FileList) > 0
BEGIN
DECLARE #FileName NVARCHAR(MAX) = (SELECT TOP(1) subdirectory FROM #FileList)
DECLARE #FullPath NVARCHAR(MAX) = #Dir + '\' + #FileName
DECLARE #SQL NVARCHAR(MAX)
DECLARE #SQL_TO_EXEC NVARCHAR(MAX)
SELECT #SQL_TO_EXEC = 'select #SQL = BulkColumn
FROM OPENROWSET
( BULK ''' + #FullPath + '''
, SINGLE_BLOB ) AS MYTABLE'
DECLARE #parmsdeclare NVARCHAR(4000) = '#SQL varchar(max) OUTPUT'
EXEC sp_executesql #stmt = #SQL_TO_EXEC
, #params = #parmsdeclare
, #SQL = #SQL OUTPUT
EXEC (#sql)
DELETE FROM #FileList WHERE subdirectory = #FileName
PRINT 'EXECUTED: ' + #FileName
END

How can I schedule a daily backup with SQL Server Express? [duplicate]

This question already has answers here:
SQL Server Automated Backups [closed]
(3 answers)
Closed 5 years ago.
I'm running a small web application with SQL server express (2005) as backend. I can create a backup with a SQL script, however, I'd like to schedule this on a daily basis. As extra option (should-have) I'd like to keep only the last X backups (for space-saving reasons obviously) Any pointers?
[edit] SQL server agent is unavailable in SQL server express...
You cannot use the SQL Server agent in SQL Server Express.
The way I have done it before is to create a SQL Script, and then run it as a scheduled task each day, you could have multiple scheduled tasks to fit in with your backup schedule/retention. The command I use in the scheduled task is:
"C:\Program Files\Microsoft SQL Server\90\Tools\Binn\SQLCMD.EXE" -i"c:\path\to\sqlbackupScript.sql"
Eduardo Molteni had a great answer:
SQL Server Automated Backups
Using Windows Scheduled Tasks:
In the batch file
"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE" -S
(local)\SQLExpress -i D:\dbbackups\SQLExpressBackups.sql
In SQLExpressBackups.sql
BACKUP DATABASE MyDataBase1 TO DISK = N'D:\DBbackups\MyDataBase1.bak'
WITH NOFORMAT, INIT, NAME = N'MyDataBase1 Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
BACKUP DATABASE MyDataBase2 TO DISK = N'D:\DBbackups\MyDataBase2.bak'
WITH NOFORMAT, INIT, NAME = N'MyDataBase2 Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
Just use this script to dynamically backup all databases on the server. Then create batch file according to the article. It is usefull to create two batch files, one for full backup a and one for diff backup. Then Create two tasks in Task Scheduler, one for full and one for diff.
-- // Copyright © Microsoft Corporation. All Rights Reserved.
-- // This code released under the terms of the
-- // Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
USE [master]
GO
/****** Object: StoredProcedure [dbo].[sp_BackupDatabases] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Microsoft
-- Create date: 2010-02-06
-- Description: Backup Databases for SQLExpress
-- Parameter1: databaseName
-- Parameter2: backupType F=full, D=differential, L=log
-- Parameter3: backup file location
-- =============================================
CREATE PROCEDURE [dbo].[sp_BackupDatabases]
#databaseName sysname = null,
#backupType CHAR(1),
#backupLocation nvarchar(200)
AS
SET NOCOUNT ON;
DECLARE #DBs TABLE
(
ID int IDENTITY PRIMARY KEY,
DBNAME nvarchar(500)
)
-- Pick out only databases which are online in case ALL databases are chosen to be backed up
-- If specific database is chosen to be backed up only pick that out from #DBs
INSERT INTO #DBs (DBNAME)
SELECT Name FROM master.sys.databases
where state=0
AND name=#DatabaseName
OR #DatabaseName IS NULL
ORDER BY Name
-- Filter out databases which do not need to backed up
IF #backupType='F'
BEGIN
DELETE #DBs where DBNAME IN ('tempdb','Northwind','pubs','AdventureWorks')
END
ELSE IF #backupType='D'
BEGIN
DELETE #DBs where DBNAME IN ('tempdb','Northwind','pubs','master','AdventureWorks')
END
ELSE IF #backupType='L'
BEGIN
DELETE #DBs where DBNAME IN ('tempdb','Northwind','pubs','master','AdventureWorks')
END
ELSE
BEGIN
RETURN
END
-- Declare variables
DECLARE #BackupName varchar(100)
DECLARE #BackupFile varchar(100)
DECLARE #DBNAME varchar(300)
DECLARE #sqlCommand NVARCHAR(1000)
DECLARE #dateTime NVARCHAR(20)
DECLARE #Loop int
-- Loop through the databases one by one
SELECT #Loop = min(ID) FROM #DBs
WHILE #Loop IS NOT NULL
BEGIN
-- Database Names have to be in [dbname] format since some have - or _ in their name
SET #DBNAME = '['+(SELECT DBNAME FROM #DBs WHERE ID = #Loop)+']'
-- Set the current date and time n yyyyhhmmss format
SET #dateTime = REPLACE(CONVERT(VARCHAR, GETDATE(),101),'/','') + '_' + REPLACE(CONVERT(VARCHAR, GETDATE(),108),':','')
-- Create backup filename in path\filename.extension format for full,diff and log backups
IF #backupType = 'F'
SET #BackupFile = #backupLocation+REPLACE(REPLACE(#DBNAME, '[',''),']','')+ '_FULL_'+ #dateTime+ '.BAK'
ELSE IF #backupType = 'D'
SET #BackupFile = #backupLocation+REPLACE(REPLACE(#DBNAME, '[',''),']','')+ '_DIFF_'+ #dateTime+ '.BAK'
ELSE IF #backupType = 'L'
SET #BackupFile = #backupLocation+REPLACE(REPLACE(#DBNAME, '[',''),']','')+ '_LOG_'+ #dateTime+ '.TRN'
-- Provide the backup a name for storing in the media
IF #backupType = 'F'
SET #BackupName = REPLACE(REPLACE(#DBNAME,'[',''),']','') +' full backup for '+ #dateTime
IF #backupType = 'D'
SET #BackupName = REPLACE(REPLACE(#DBNAME,'[',''),']','') +' differential backup for '+ #dateTime
IF #backupType = 'L'
SET #BackupName = REPLACE(REPLACE(#DBNAME,'[',''),']','') +' log backup for '+ #dateTime
-- Generate the dynamic SQL command to be executed
IF #backupType = 'F'
BEGIN
SET #sqlCommand = 'BACKUP DATABASE ' +#DBNAME+ ' TO DISK = '''+#BackupFile+ ''' WITH INIT, NAME= ''' +#BackupName+''', NOSKIP, NOFORMAT'
END
IF #backupType = 'D'
BEGIN
SET #sqlCommand = 'BACKUP DATABASE ' +#DBNAME+ ' TO DISK = '''+#BackupFile+ ''' WITH DIFFERENTIAL, INIT, NAME= ''' +#BackupName+''', NOSKIP, NOFORMAT'
END
IF #backupType = 'L'
BEGIN
SET #sqlCommand = 'BACKUP LOG ' +#DBNAME+ ' TO DISK = '''+#BackupFile+ ''' WITH INIT, NAME= ''' +#BackupName+''', NOSKIP, NOFORMAT'
END
-- Execute the generated SQL command
EXEC(#sqlCommand)
-- Goto the next database
SELECT #Loop = min(ID) FROM #DBs where ID>#Loop
END
And batch file can look like this:
sqlcmd -S localhost\myDB -Q "EXEC sp_BackupDatabases #backupLocation='c:\Dropbox\backup\DB\', #backupType='F'" >> c:\Dropbox\backup\DB\full.log 2>&1
and
sqlcmd -S localhost\myDB -Q "EXEC sp_BackupDatabases #backupLocation='c:\Dropbox\backup\DB\', #backupType='D'" >> c:\Dropbox\backup\DB\diff.log 2>&1
The advantage of this method is that you don't need to change anything if you add new database or delete a database, you don't even need to list the databases in the script. Answer from JohnB is better/simpler for server with one database, this approach is more suitable for multi database servers.
The folks at MSSQLTips have some very helpful articles, the one most relevant for this is "Automating SQL Server 2005 Express Backups and Deletion of Older Backup Files"
The basic approach is to set up two tasks using the Windows Task Scheduler. One task runs a TSQL script that generates separate backup files for all MSSQL databases (except TEMPDB) with the database name and a date/time stamp in the file name into a specified directory. The second task runs a VBScript script that goes through that directory and deletes all files with a .BAK extension that are more than 3 days old.
Both scripts require minor editing for your environment (paths, how long to keep those database dumps) but are very close to drop-in-and-run.
Note that there are possible security implications if you're sloppy with these or with directory permissions, since they are plain text files that will need to run with some level of privilege. Don't be sloppy.
We have used the combination of:
Cobian Backup for scheduling/maintenance
ExpressMaint for backup
Both of these are free. The process is to script ExpressMaint to take a backup as a Cobian "before Backup" event. I usually let this overwrite the previous backup file. Cobian then takes a zip/7zip out of this and archives these to the backup folder. In Cobian you can specify the number of full copies to keep, make multiple backup cycles etc.
ExpressMaint command syntax example:
expressmaint -S HOST\SQLEXPRESS -D ALL_USER -T DB -R logpath -RU WEEKS -RV 1 -B backuppath -BU HOURS -BV 3
You can create a backup device in server object, let us say
BDTEST
and then create a batch file contain following command
sqlcmd -S 192.168.1.25 -E -Q "BACKUP DATABASE dbtest TO BDTEST"
let us say with name
backup.bat
then you can call
backup.bat
in task scheduler according to your convenience