Unable to pass in parameters to SQL Server Stored procedure from Windows batch script - sql

I tried searching for the solution here but didn't find one that can solve my problem. I have following batch script:
for /f "tokens=1-3 delims=, " %%a in ('\path\batch_output.txt') do (
echo %%a, %%b, %%c
sqlcmd -S server -E -i path\spu_update_src_trg_ref.sql -v SourceName= %%a Instancname= %%b exitcode= %%c
ping 1.1.1.1 -n 1 -w 5000 > nul
)
Inside spu_update_src_trg_ref.sql I have below code:
use dbname
go
EXEC dbo.spu_update_src_trg_ref $(SourceName), $(Instancname), $(exitcode)
I am running the below batch script via a job scheduler so unable to see the direct error in the cmd. But my job is getting failed and the stored proc is also not getting executed. If need, stored proc is as below:
CREATE PROCEDURE dbo.spu_update_src_trg_ref
#SourceName VARCHAR(100),
#Instancname VARCHAR(100),
#exitcode INT
AS
BEGIN
IF #exitcode=0
BEGIN
UPDATE dbo.t_ctrm_ref_src_trg SET LoadStatus='Completed' WHERE SourceTableName=#SourceName;
UPDATE dbo.t_ctrm_instance_status SET InstanceStatus='Completed' WHERE InstanceName=#Instancname;
END
END
Its a simple sp that updates two tables, but I am unable to pass the input parameters from batch script. Please advice.
Update:
Thanks everyone for the help. I just removed some spaces and quotes('') from '\path\batch_output.txt' and it worked just fine. Appreciate all your help

There are syntax errors in your sqlcmd command. Remove the spaces between the var name, the equal sign, and the value in the "-v" portion.

Related

Suppress SQL*PLUS error in batch script

I have a script db.bat as below:
#echo off
setlocal enabledelayedexpansion
for /F "tokens=*" %%A in (user.txt) do (
sqlplus -s %%A #fetch.sql >> output.txt
)
where user.txt (list of all user details for which I need expiry date. this list may have around 40-50 rows) is:
dbuser/password#database1
readuser/p#ssw0rd#database1
adminuser/Pa$$word#database2
.......
.......
.......
and fetch.sql is:
set pagesize 20
set linesize 200
select username, expiry_date from user_users;
exit;
The problem I am facing here is, whenevey my script db.bat encounters any SQL ERRORS like given below, its not moving further and getting hanged at that point until I manually stop that.
SQL ERRORs:
ERROR:
ORA-12154: TNS:could not resolve the connect identifier specified
ERROR:
ORA-28000: the account is locked
I have checked that there is a WHENEVER SQLERROR command that works in this situation but don't know how I can use it here.
For those kinds of errors, SQL*Plus is 'hanging' at a username prompt, as it hasn't been able to connect. You don't see that because of the -s flag. By default it will allow three attempts, which is useful when running interactively, but isn't helpful when run from a script like this. You can make it exit after the failed login with the -l 'logon' option:
sqlplus -s -l %%A #fetch.sql >> output.txt
Try this, when using the fetch.sql in a script, you need to set the termout to off.
The error is still there, only that your script will continue to execute after it.
set pagesize 20
set linesize 200
whenever sqlerror continue
set termout off
select username, expiry_date from user_users;
exit;

Correct Output to File When Using SQLCMD

I've been playing around with SQLCMD to output a .SQL results to a file. It is working but the actual SQL statements are also being displayed in the output file which I obviously don't want. I am using a .bat file to run the SQL File. The following command is what I have in my .bat:
SQLCMD -S MyServerName -d MyDBName -i C:\test\start.SQL -o C:\test\out.txt -e
In my start.SQL I have the following:
set nocount on
SELECT '<HEADER>', getDate(), '<HHEADER>'
SELECT UPPER(ACCTNUM),
CONVERT(VARCHAR(10),DATEEXP,126),
UPPER(OPERID),
CONVERT(VARCHAR,CREATE_TMSTMP,120)
FROM RETURNS
WHERE CREATE_TMSTMP < getDate()
AND CREATE_TMSTMP > getDate() - 1
SELECT '<TRAILER>', getDate(), '<HHEADER>'
set nocount off
In the output file the correct information is shown but it's a little ugly with dashes and such and even shows the SQL command that was executed. Is there any way to fix this problem. Am I doing something wrong here? Any help would be greatly appreciated.
Why are you using the -e option?
-e
Writes input scripts to the standard output device (stdout).
The dashes are part of the header. Use -h-1 to specify no header. If that is not acceptable use something like FINDSTR /B /V "----" to exclude that header line... assuming none of the lines you want to keep start with dashes.

save the result of a operation into a variable within a .BAT file

I have the following BAT file working ok:
it connects to an specific sql server and select getdate()
what I really wanted is to test whether the server is connectable.
I would like something like:
set is_connectable = call sqlcmd.exe %%SERVITORE%%
is there any way I could achieve this?
thanks and regards
marcelo
#echo off
color fc
cls
echo.
#ECHO --- BEGIN THE SCRIPT 1 ----
echo.
#echo the SERVITORE is "%1"
echo.
echo.
if "%1"=="" GOTO USAGE
set SERVITORE=-Stcp:%1% -Q " USE MASTER select getdate() "
call sqlcmd.exe %%SERVITORE%%
color 6
GOTO THE_END
:USAGE
echo.
echo USAGE:
echo.
ECHO the first parameter is the SERVITORE server.
echo example 1 SERVITORE108
echo.
ECHO the second parameter is optional
echo but if not supplied the default is \\SERVITORE\folder2$
echo.
echo ATB
echo.
:THE_END
color 8
It is easy to run a query and set the result to a DOS environment variable. For instance, you can do the following to get the date/time from the SQL Server instance (SQL Server is running locally in my instance):
for /f "skip=2 delims=" %%i in ('sqlcmd -S localhost -E -Q "set nocount on; select getdate() as [Now]"') do set is_connectable=%%i
However, the is_connectable environment variable set in this example will have an arbitrary value, which will make it hard to evaluate. Since you are just trying to verify that the SQL Server is there, alive, and responsive, you should run a query that creates a more predictable output, like this:
#echo off
:: Make sure the variable is undefined to start with
set is_connectable=
:: Make the connection and run a query that should always return '1'
for /f "skip=2 delims= " %%i in ('sqlcmd -S localhost -E -Q "set nocount on; select 1 as [Rows] into #temp; select ##rowcount as [Rows]; drop table #temp"') do set is_connectable=%%i
:: Verify if SQL Server is avaialble
if not defined is_connectable goto NotFound
if "%is_connectable%"=="1" goto Found
goto UnknownError
:Found
echo SQL Server was found and returned '1' as expected...
goto TheEnd
:NotFound
echo SQL Server was not found...
goto TheEnd
:UnknownError
echo SQLServer was found, but the return value was '%is_connectable%' instead of '1'...
goto TheEnd
:TheEnd

Msg 102, Level 15, state 1 Line 1 Incorrect syntax near 'n'

I have the following query which I am running using a batch file. In the batch file I use the following syntax:
echo populating Application table with values...
SET "installFile=%sqlDir%\Install\DataFiles\Insert_ApplicationNames.sql"
OSQL /n /i "%installFile%" /d%db% /U%user% /P%pswd% /S%serv%
echo
echo populated Application table with values in Insert_ApplicationNames.sql
echo
The sql shown below runs without any errors when executed from the SQL Management Studio, but it keeps erroring out when run as a part of the batch script. Could some one help me find what I may be doing wrong here?
Also, the rows do get inserted, but our nightly QA install breaks because of the error thrown by the batch script.
IF NOT EXISTS(SELECT * FROM Application WHERE name = '')
BEGIN
INSERT INTO Application
(Name)
VALUES
('')
END
GO
IF NOT EXISTS(SELECT * FROM Application WHERE name = 'App1.exe')
BEGIN
INSERT INTO Application
(Name)
VALUES
('App1.exe')
END
GO
IF NOT EXISTS(SELECT * FROM Application WHERE name = 'App2.exe')
BEGIN
INSERT INTO Application
(Name)
VALUES
('App2.exe')
END
GO is the (default) batch separator keyword in Management Studio, but it isn't a real SQL keyword (i.e., SQL Server doesn't recognize it).
Remove those from your script -- in the script you've provided, they are irrelevant anyway -- and you should be good to, um, go.
Curious whether your variables should be right up against the switches. Try this?
OSQL -n -i "%installFile%" -d %db% -U %user% -P %pswd% -S %serv%
What happens when you use the line above with your known good values right in the command?
OSQL -n -i "C:\foo.sql" -d MyDB -U MyUser -P MyPwd -S MyServ

How to set a local variable to the result of sql query in a batch file?

Is there any way to retreive the result set of a sql query in a local variable; the query is to be run in a batch file. What I am trying to do is something like this:
set varname = osql -S%dstserver% -d%dstDB% -Q"SELECT name from table_name where Id = %siteId%" %osqluser% -b
varname is my local variable.
I am quite new in sql so any help would be greatly appreciated1
Write the result to the file and then read the file. In your case you need to read the first line (and possibly trim it).
Add following parameters to your query:
osql -S%dstserver% -d%dstDB% -Q"SET NOCOUNT ON;SELECT name from table_name where Id = %siteId%" %osqluser% -b -w 9999 -h-1 -o tempres.txt
-o ...: output file (which you need to read later)
-h-1: disable header
-w 9999: to ensure that it handles correctly cases when your name is longer then default 80 characters
SET NOCOUNT ON; before real query to disable the status string like (1 row affected)
You can use for /f to iterate over the output of a command:
for /f "usebackq delims=" %%x in (`your command`) do ...
You don't need a temporary file at all; it doesn't gain you anything here (except having to think about where you may have write permissions and remember to delete the file afterwards).
for iterates line-wise over the output, tokenizing as it goes. That's why there is a delims= at the end which effectively disables any tokenizing so you don't get your output split at spaces. There are other options, such as skip=n which will skip n lines before starting processing which you can use to ignore a header or so.
Inside that loop you can then do the following:
for /f "usebackq delims=" %%x in (`your command`) do set VAR=%%x
Be very careful what you do afterwards with that variable, though, as it may contain characters the shell treats as special, such as >, <, &, etc. You may create yourself here some sort of Batch Injection vulnerability when doing something like the following:
echo %VAR%
and someone decides to put the following string in his name:
foo & rd /s q \
If you know that only a single line with usable content returns and the rest is useless junk then you can break the loop prematurely:
for /f "usebackq delims=" %%x in (`your command`) do set VAR=%%x&goto break
:break
Use set /p:
osql -S%dstserver% -d%dstDB% -Q"SET NOCOUNT ON;SELECT name from table_name where Id = %siteId%" %osqluser% -b -w 9999 -h-1 -o tempres.txt
set /p varname=<tempres.txt
(Borrowing osql parameters from van's answer)
You can write the result to a file containing set statements.
#echo off
osql -E -S servername -h-1 -Q "set nocount on; select 'set var=42'" > c:\set.bat
call c:\set.bat
echo %VAR%
This results in 42 being written to the screen. To select a name from a table, use a SQL statement like:
select 'set var=' + name from table_name where Id = %siteId%