Windows batch file executes only the first line - sql-server

I have created a batch with the following. ( Batch file name is BACKUP_TASK.bat )
SQLCMD -E -S SQLEXPRESS
DECLARE #DatabaseName sysname = N'DEMO_DB',
#DatabaseBackupFileName varchar(255);
SET #DatabaseBackupFileName = 'C:\sql\' + #DatabaseName + '_' + REPLACE(replace(convert(varchar(40),getdate()),' ','_'),':','_') + '.bak';
BACKUP DATABASE #DatabaseName TO DISK = #DatabaseBackupFileName;
GO
exit
exit
If I copy paste this code directly to Command Prompt it Executes as Expected.But if I double click on the batch file then the Command Prompt opens up and only the first line is compiled and nothing happen further more.
So what I am doing here wrong ? Please help me solve this.

Related

SQL Server 2016 and SSDT: rebuild using devenv works in command line, not from TSQL xp_cmdshell

I have a TSQL script to automate deployment of SSDT solutions into SQL Server SSIS Catalog. It uses several calls to command line to perform operations on files , which work fine (xp_cmdshell is enabled in configuration)
But the call to devenv to rebuild the .ispac file fails
with error message :
C:\Users\user1\DWH_home\01. SSIS Development\Log_BI\Log_BI\Log_BI.dtproj : error : Operation is not valid due to the current state of the object.
One or more projects in the solution were not loaded correctly.
Please see the Output Window for details.
========== Rebuild All: 0 succeeded, 0 failed, 0 skipped ==========
command:
SET #cmd = #devenv + ' "' + #DWH_home + #ispac_path + '\'+ #project_name+'.sln" /Rebuild Development /Out '+ #current_log_file
print #cmd --debug
/* print output:
C:\PROGRA~2\MIB055~1\2017\SQL\Common7\IDE\devenv.exe "C:\Users\user1\DWH_home\01. SSIS Development\Log_BI\Log_BI\Log_BI.sln" /Rebuild Development /Out C:\Windows\Temp\SSIS_Current_build_log.txt
*/
DECLARE #result int;
EXEC #result = xp_cmdshell #cmd;
print #result
--#result = 1
whereas the exact same command works OK in command line

Set variable in SQL equal to database name

I want to execute a .sql file by .bat file (where db=input name in cmd)
The top of the .sql file looks like this:
USE $(db)
DECLARE #Database varchar(500)
SET #Database = $(db)
But after executing the .bat file, an error occurs at line 4 of the .sql file
Apparently, variable = $(db) does not work.
Is there another way in order to do something like this?
Use SQLCMD variables, so change your batch file to call SQLCMD rather than ISQL
#echo off
sqlcmd -E -S myserver -i sample.sql -v db=YourDBName
sample.sql content would be like this
USE $(db)
DECLARE #Database varchar(500)
SET #Database = $(db)

Running .sql file within a SQL query

I have a SQL script I need to run on about 20 different databases.
I basically just need to be able to run some SQL, then have it load and run a file from the disk, do more SQL, run that same script again, etc.
I was hoping to make a SQL script that would basically look something like this:
use database1
go
exec c:\release.sql
go
use database2
go
exec c:\release.sql
go
use database3
go
exec c:\release.sql
go
--etc....
I've looked online a bunch and found a way to do something similar in a batch file with sqlcmd but it isn't working and I don't see how to switch databases that way, either.
Thanks a ton!
Ben
You can switch management studio to sqlcmd mode (query menu) and then run a script with :r script.sql
To do this on a dynamically generated list of databases you have to do some sqlcmd trickery:
set output to file
generate the command to execute
set output to stdout
execute the file
delete the temp file
I assume in this example that the file script.sql exists in c:\temp. Note that the GO statements are important in the script or the sqlcmd parser will get confused.
:OUT $(TEMP)\db.sql
declare #script nvarchar(max)
select #script = isnull(#script, '')
+ 'use ' + name + char(13) + char(10)
+ ':r c:\temp\script.sql' + char(13) + char(10)
from sys.databases
where name like N'%[_]db'
print #script
GO
:OUT stdout
:r $(TEMP)\db.sql
GO
!!del $(TEMP)\db.sql /s /q
You don't need to do this in SSMS. You just need to create a CMD script.
IF you have a static set of databases to run on, then use the following:
#ECHO OFF
SET MyServer="(local)"
SET MyScript="c:\release.sql"
SQLCMD -S %MyServer% -E -i %MyScript% -d database1
SQLCMD -S %MyServer% -E -i %MyScript% -d database2
...
SQLCMD -S %MyServer% -E -i %MyScript% -d database20
IF you have a dynamic set of databases that can be queried for, then use the following:
#ECHO OFF
SET MyServer="(local)"
SET MyScript="c:\release.sql"
SET MyQuery="SET NOCOUNT ON; SELECT [Name] FROM [sys].[databases] sd WHERE sd.[name] LIKE N'%%[_]db' ORDER BY sd.[name];"
FOR /F %%B IN ('SQLCMD -h -1 -S %MyServer% -E -Q %MyQuery%') DO (
REM remove the "echo" from the next line to run the scripts
echo SQLCMD -S %MyServer% -E -i %MyScript% -d %%B -o results-%%B.txt
)
Using the %%B in the output filename will give you a different output file per database, as in:
results-database1_db.txt
results-database2_db.txt
...
Other notes:
Use (local) instead of localhost when connecting to the local, default instance as it uses shared memory while localhost forces a TCP connection.
If you are searching for an underscore in a LIKE statement, enclose it in square brackets else it is a single-character wild card (which still technically works sometimes, but could also match other characters): [_]
Thanks everyone who pitched in! The following seems like it might work (based on #srutzky's answer)
sqlcmd -S "localhost" -E -i "c:\release.sql" -d database1 -o results.txt
The thing I am missing by using a cmd prompt instead of SSMS is that I don't think I can write cursor to loop through each database that ends with "_db" and then execute against that... Here's the SQL I have but I just need to be able to put the link to the SQL file to execute.
link
If I put the release script SQL into this file into the #text variable it doesn't work because it blows up on each GO statement I have in my release.sql file.
declare #text as nvarchar(max)
set #text = N'
-- GET AND RUN SCRIPT FROM DISK!
'
declare C_CURSOR CURSOR FOR
select [Name] from sys.databases
where name like '%_db'
order by name
declare #runtext as nvarchar(max)
declare #DB_Name as nvarchar(200)
OPEN C_CURSOR
fetch next from C_CURSOR INTO #DB_Name
WHILE(##FETCH_STATUS = 0)
BEGIN
print #DB_Name
set #runtext = 'select ''' + #DB_Name + ''' as DatabaseName
use ' + #DB_Name + N'
' + #text
exec sp_executesql #runtext
fetch next from C_CURSOR INTO #DB_Name
END
CLOSE C_CURSOR
DEALLOCATE C_CURSOR
Thanks again!
I ended up combining 2 things. I made a SQL script that creates a cursor to find the databases and then prints a list of commands for a CMD prompt. I then run that in the command prompt. Below is what we output with our sql script and then save as a .bat file that we run. It's working great!
That script is essentially created with the following SQL script:
/*** GET DATABASES IN THE CURSOR QUERY BELOW! */
declare C_CURSOR CURSOR FOR
select [Name] from sys.databases
where name like '%_db'
order by name
/* THIS IS WHERE THE CURSOR STARTS*/
declare #DB_Name as nvarchar(200)
OPEN C_CURSOR
fetch next from C_CURSOR INTO #DB_Name
WHILE(##FETCH_STATUS = 0)
BEGIN
print 'SQLCMD -S "localhost" -E -i "C:\release.sql" -d ' + #DB_Name + ' -o ' + #DB_Name + '_results.txt'
fetch next from C_CURSOR INTO #DB_Name
END
CLOSE C_CURSOR
DEALLOCATE C_CURSOR
That outputs the following which we then run in a .bat file
SQLCMD -S "localhost" -E -i "C:\release.sql" -d database1 -o database1_results.txt
SQLCMD -S "localhost" -E -i "C:\release.sql" -d database2 -o database2_results.txt
SQLCMD -S "localhost" -E -i "C:\release.sql" -d database3 -o database3_results.txt
Thanks everyone!

How do I prevent SQL Server 2008 stored procedure from writing line breaks to a file?

This is what we have so far, which works, but it writes out line breaks to the file. We would like to not send the CRLF character if at all possible.
set #dosvar = #JobNumber
set #doscmd2 = 'ECHO' + #dosvar +' >> \\test1\websites\testcontrol\js\misc1.js'
Exec master..xp_cmdshell #doscmd2
Thanks
You could try this trick:
'echo/|set /p="' + #dosvar +'" >> \\test1\websites\testcontrol\js\misc1.js'
If you run this batch file:
#echo off
echo/|set /p="a"
echo/|set /p="b"
echo/|set /p="c"
It prints:
abc
So it seems to work.

SQL server 2008: Copy a file and rename it

I have a file inside a directory \\myServer\Admin\temp\testtemp.txt
I need to write a TSQL to
Search for testtemp.txt file.
If exists, create a copy of it and rename it to Copytesttemp.txt
If there's testtemp.txt already in the above directory like this
\\abcd\Admin\temp\Copytesttemp.txt
then delete it and recreate Copytesttemp.txt
How do I achieve it? Thanks.
You can use xp_cmdshell to run any DOS commands you like, e.g.
declare #cmdstring varchar(1000)
set #cmdstring = 'copy \\myServer\Admin\temp\testtemp.txt \\myServer\Admin\temp\Copytesttemp.txt'
exec master..xp_cmdshell #cmdstring
Just make sure xp_cmdshell is enabled on your installation.
Create a SQL Agent job which runs a command script to do the actions.
You can try this for Copy a file and rename
EXEC master..xp_cmdshell 'COPY D:\T1\a.txt D:\T2\b.txt'
Only copy and move just like CMD
EXEC master..xp_cmdshell 'COPY D:\T1\abcd.txt D:\T2'
EXEC master..xp_cmdshell 'Move D:\T1\abcd.txt D:\T2'

Resources