How to Pass a sqlplus parameter from shell script to sql file - sql

I am having a Shell script that has a variable storing the date value using sqlplus connection as below. I want to pass the shell variable 'var_Date' value to the sql file.
cat extract.sh
#!/bin/ksh
var_Date=`sqlplus -s $DB_USER/$DB_PASS#$DB_HOST:$DB_PORT/$DB_SID << EOF
SELECT MAX(SAMPLE_DATE)-1 FROM SAMPLE_CASES WHERE KEY IN ('ab','bc');
EXIT;
EOF`
export var_Date
echo $var_Date
sqlplus -s $DB_USER/$DB_PASS#$DB_HOST:$DB_PORT/$DB_SID #data_extract.sql $var_Date
cat extract.sql
set echo off
set trimspool on
set pagesize 0
set colsep ~
spool extract.csv
SELECT CASE_ID FROM SAMPLE_CASE1 WHERE TIME_START>='&1'
spool off
I have tried to execute this script but it is failing with invalid identifier. Please help to understand what is the mistake I am doing here.

After searching in the internet for almost a week, could arrive at a working code. Below is the working code.
cat extract.sh
#!/bin/ksh
var_Date=`sqlplus -s $DB_USER/$DB_PASS#$DB_HOST:$DB_PORT/$DB_SID << EOF
SET HEADING OFF
SELECT ''''||TRIM(MAX(SAMPLE_DATE)-1)||'''' FROM SAMPLE_CASES WHERE KEY IN ('ab','bc');
EXIT;
EOF`
export var_Date
echo $var_Date
sqlplus -s $DB_USER/$DB_PASS#$DB_HOST:$DB_PORT/$DB_SID #data_extract.sql $var_Date
cat extract.sql
set echo off
set trimspool on
set pagesize 0
set colsep ~
spool extract.csv
SELECT CASE_ID FROM SAMPLE_CASE1 WHERE to_char(TIME_START,'DD-MON-YYYY') >='&1'
spool off
Firstly, we to need to pass the argument $var_Date to sqlplus within single quotes which is done within the variable declaration itself by concatenating ''''. We also need to use SET HEADING OFF to make the variable var_Date hold only the date value and not the header value.
Secondly, there was a ora error: "ORA-01858: a non-numeric character was found where a numeric was expected". To mitigate this, I had type-casted the field time_start to to_char post which the filter is applied and stored in the csv file.
Hope this helps others who had trouble like me.

Related

Running SQL from Batch File [duplicate]

I write shell script and want to use sqlplus, when I write:
#!/bin/bash
result=$(sqlplus -s user/pass#DB << EOF
set trimspool on;
set linesize 32000;
SET SPACE 0;
SELECT MAX(DNNCMNT_ANSWER_TIME) FROM TKIMEI.DNNCMNT_IMEI_APPRV;
/
exit;
EOF)
echo "$result"
the result is in txt file (I'm executing it as ksh sql.sh > result.txt):
MAX(DNNCM
---------
10-MAR-14
MAX(DNNCM
---------
10-MAR-14
it is automatically putting an empty line at the beginning of file and writing the result twice.
How can I fix it ?
Remove the slash. It's causing the previous command (the select) to be repeated:
http://docs.oracle.com/cd/B10501_01/server.920/a90842/ch13.htm#1006932
Also, talk to your DBA about setting up external OS authentication so you don't have to hardcode the password in a shell script for security reasons. Once set up, you can replace the login/password combo with just a slash:
http://docs.oracle.com/cd/E25054_01/network.1111/e16543/authentication.htm#i1007520

Calling SQL*PLUS from UNIX Shell script and print the status message about the query

I want to run a SQL code using shell script and return the message whether the SQL query executed successfully or not. For this I have used unix script given below.
#!/bin/sh
sqlplus -S hr/hr#xe<<EOF
#emp.sql
EOF
var1=$(cat /cygdrive/d/scripts/output.txt | grep -c 'COUNT')
if [ $var1 -ge 1 ];
then
echo "success"
else
echo "failure"
fi
exit;
and emp.sql(called sql file) as
SET ECHO OFF
SPOOL D:\scripts\output.txt
SET LINESIZE 100
SET PAGESIZE 50
SELECT count(*) FROM employees;
SPOOL OFF;
EXIT 0;
When I execute the script I am getting output as
COUNT(*)
----------
107
./script1.sh: line 13: syntax error: unexpected end of file.
I don't know where I should put EOF statement exactly. Also I am not getting the status message whether it is success or failure which I want as output. Please help. Thanks in advance
SPOOL D:\scripts\output.txt Isnt this windows way of referring to a file where as in the shell script you referred to the file as /cygdrive/d/scripts/output.txt. I assume you are using linux shell to execute so I executed your script changing the spool line in sql file. It worked fine.
Edit: Also the \ that you used, for the spooled output.txt path, will cause the sqlplus to terminate. Hence the error line 13: syntax error: unexpected end of file. Perhaps add quotes to the path or use the same file path as you used in shell

Return a scalar query result into a batch file variable

I would like to perform a scalar database query and return the result into a variable in a batch file.
How would one do this? The closest I example in our system that I see is if I return an exit code based on a scalar query result.
Z:\SQL2005\90\Tools\Binn\sqlcmd -S servername -dCLASS -E -Q "EXIT(select case run_type when 'Q' then 200 else 100 end from cycle_date where cycle = '1')">NUL
if %errorlevel% == 200 call %SQLSERVER%
QRTLY.BAT
if %errorlevel% == 100 call %SQLSERVER%
MTHLY.BAT
Can someone help me with the syntax?
Here's some sqlcmd help info:
-v var = value[ var=value...]
Creates a sqlcmdscripting variable that can be used in a sqlcmd script. Enclose the value in quotation marks if the value contains spaces. You can specify multiple var="values" values. If there are errors in any of the values specified, sqlcmd generates an error message and then exits.
sqlcmd -v MyVar1=something MyVar2="some thing"
sqlcmd -v MyVar1=something -v MyVar2="some thing"
-x disable variable substitution
Causes sqlcmd to ignore scripting variables. This is useful when a script contains many INSERT statements that may contain strings that have the same format as regular variables, such as $(variable_name).
How about saving it to a file without headers then reading the contents back in?
sqlcmd -S(local)\SQLExpress -dMyDatabase -Umyuser -Pmypassword -W -h -1 -Q "SELECT Top 1 MyValue FROM MyTable" -o sqlcmdoutput.txt
set /p x= <sqlcmdoutput.txt
del sqlcmdoutput.txt
echo My scalar value is %x%
I use this in a batch file. It returns the LogicalFilename for a SQL Server Database data file. This only works if there is one data file in the DB.
So the result is the environment variable DATABASEFILENAME is set to say AdventureWorks_Data.
FOR /F "usebackq tokens=1" %%i IN (`sqlcmd -w200 -h-1 -E -Q"set nocount on; Select df.name From sysdatabases as d Inner Join sysaltfiles as df on d.dbid=df.dbid Where d.name ='$(DatabaseName)' and df.Fileid =1"`) DO set DATABASEFILENAME=%%i
Have you looked at sqlcmd?

Unix putting extra spaces/lines while passing values to sql statement

I have a unix script like this:
value1=`sqlplus -s ivr/ivr <<EOF
set heading off;
set feedback off;
set linesize 500;
set serveroutput on;
set wrap off;
SELECT FM.getSequence_n('$b_period', '$t_period', '$opr', '$fran', '$poi_s')
FROM DUAL;
exit;
EOF` ,
The parameters are taken as input from the user. when i run the script in debug mode using 'ksh -x filename.sh' i notice that when the unix script is passing values to the select statement it breaks it like this:
SELECT FM.getSequence_n('
2010/12/01 - 2010/12/31','
2010/12/01 - 2010/12/31','TTSLAP','UWAP','TTSL-LOC')
FROM DUAL
...which gives the wrong output. When i run the same sql statement with the passed values in sqlplus with all the values in a single line i get the correct output.
I need to know why unix is breaking the statement into multiple lines and how can this be removed. This has been giving me nightmares. Firstly i was thinking that values were not being passed correctly that's why output was wrong . But only this linefeed by unix while passing values is the cause of error. Please help.
It seems like your $b_period and $t_period variables contain newline characters. If they are input directly from users you really should do some input validation first before using them.
Try something like
filtered_b_period=`echo $b_period | sed 's/[^0-9\/]*//g'`
filtered_t_period=`echo $t_period | sed 's/[^0-9\/]*//g'`
Probably you should add further check as well, but at least you should be able to filter out unwanted characters this way.
The values of your variables include newlines. Do something like this to check:
echo "$b_period" | hexdump -C

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%