How to give the result of a query in a subtitution variable - oracle

sequel from this question
this SQL plus code is working
define a=22;
host powershell.exe echo &a;
22
But if the value from a comes from a query, it doesn't work anymore.
define a=2;
select 22 into a;
host powershell.exe echo &a;
2 instead of 22
I've tried that with a buffer but to no avails
variable buffer varchar2;
select 22 into :buffer from dual;
define a=b;
host powershell.exe echo &a;
:b

You can use the column .. new_value ... syntax. If you still want a bind variable too, as in your previous question, then define and populate that variable however you are now, e.g.:
SQL> variable buffer varchar2(2);
SQL> exec :buffer := '22';
PL/SQL procedure successfully completed.
SQL> print buffer
BUFFER
--------------------------------
22
Then define the column with a new value you can refer to later as a substitution variable:
SQL> column a new_value a
SQL> select :buffer as a from dual;
A
--------------------------------
22
SQL> host powershell.exe echo &a
22
SQL>
You can set termout off and back on around that extra query if you're running this as a script and don't want to see the output.
And you can query anything, it doesn't have to be a bind variable:
select 22 as a from dual;
or
SQL> select sysdate as a from dual;
A
---------
02-JUN-22
SQL> host powershell.exe echo &a
02-JUN-22
SQL>

Related

How to set Oracle bind variables when using SQLPlus?

How do I set Oracle bind variables when using SQLPlus?
Example:
SELECT orders.order_no FROM orders WHERE orders.order_date BETWEEN :v1 AND :v2
How do I set the dates of :v1 and :v2?
Notice the following:
VARIABLE is a SQLPlus command. You don't end it with a semicolon (;).
In the VARIABLE command, you do not precede the variable name with
colon (:).
Bind variable can't be of data type "date" - they are some sort of
character value.
For that reason, IN YOUR CODE you must use to_date() with the
proper format model, or some other mechanism, to convert string to
date. That is currently missing in your code. NEVER compare dates to
strings!
Brief demo below.
SQL> variable v1 varchar2(20)
SQL> exec :v1 := '2015/12/22';
PL/SQL procedure successfully completed.
SQL> select 1 as result from dual where to_date(:v1, 'yyyy/mm/dd') < sysdate;
RESULT
----------
1
In common
you may use define and use variable with &
define x = 12 ;
select &x from dual;
Or varable
variable x refcursor;
begin
open :x for select * from dual connect by level < 11;
end;
/
print x

How to pass a variable from a Windows Batch File to SQL*Plus

I want to pass a variable from a Windows Batch File to SQLPLUS,
while displaying sql result batch variable should print along with the sql result.
Result should be stored in csv file.
How can I do that.
This is possible in Unix(shell script) how can I do that in Windows(batch script).
I want to pass a variable from a Windows Batch File to SQLPLUS
Just pass it as an argument to the SQL script. And use substitution variables in the same order that of the arguments list &1 &2...
For example,
mybatchfile.BAT:
sqlplus -S username/password#sid
#c:\sql\mysqlfile.sql 1000 7369
mysqlfile.SQL:
update emp set sal = &1 where empno = &2
while displaying sql result batch variable should print along with the sql result.
To display the variables which you pass as arguments to the SQL script, first you need to define the bind variables, then assign the argument value and then print the value.
For example,
I have test.sql:
For NUMBER type
-- define the bind variable
var sal number
-- assign the first argument's value
exec :sal := &1
-- display the value
print :sal
-- define the bind variable
var empno number
-- assign the second argument's value
exec :empno := &2
-- display the value
print :empno
Now, let's test the script:
SQL> #D:\test.sql 1000 7369
PL/SQL procedure successfully completed.
SAL
----------
1000
PL/SQL procedure successfully completed.
EMPNO
----------
7369
SQL>
For STRING type
-- define the bind variable
var ename varchar2(10)
-- assign the argument's value
exec :ename := '&1'
-- display the value
print :ename
Now, let's test the script:
SQL> #D:\test.sql LALIT
PL/SQL procedure successfully completed.
ENAME
--------------------------------
LALIT
SQL>
Result should be stored in csv file.
Handle this in the SQL script. Use proper SQL*Plus formatting for comma separated result. To store the result set, you just need to SPOOL
For example,
set colsep , -- separate columns with a comma
set pagesize 0 -- No headers
set trimspool on -- remove trailing blanks
spool mycsvfile.csv
SELECT ....
spool off

How to put a SELECT from Oracle into a bash variable?

I try to save the output of an Oracle SELECT command into a bash variable.
I tried the following lines but it didn't work really well...
ACCESS_SQL=`{
sqlplus << EOF
${USER}/${PASSWORD}#DB
set head off;
set feedback off;
set pagesize 5000;
set linesize 30000;
set serveroutput on;
DECLARE
data varchar(5000);
BEGIN
select ACCESS_ID, PROFILE_ID, START_DATE, END_DATE, PLATFORM, ACCESS_TYPE, PERM_FLAG, ACTIVE_FLAG into data from uam.access_list where USER_ID='${USER_ID}';
dbms_output.put_line(data);
END;
/
exit;
EOF
}`
The error statement I get is :
SQL> SQL> SQL> SQL> SQL> SQL> 2 3 4 5 6 7 select ACCESS_ID, PROFILE_ID, START_DATE, END_DATE, PLATFORM, ACCESS_TYPE, PERM_FLAG, ACTIVE_FLAG into data from uam.access_list where USER_ID='PZ230';
*
ERROR at line 4:
ORA-06550: line 4, column 110:
PL/SQL: ORA-00947: not enough values
ORA-06550: line 4, column 2:
PL/SQL: SQL Statement ignored
I was wondering if using a varchar is the right thing to do...
You don't need to select into a variable and then use dbms_output.put_line to print it out. (Your select into statement won't work anyway, because you can't select multiple columns into a single data variable.)
Instead, do it like this:
data=$(sqlplus -S ${USER}/${PASSWORD} << EOF
set head off
set feedback off
set pagesize 5000
set linesize 30000
select ACCESS_ID, PROFILE_ID, START_DATE, END_DATE, PLATFORM, ACCESS_TYPE, PERM_FLAG, ACTIVE_FLAG from uam.access_list where USER_ID='${USER_ID}';
exit
EOF)
echo "$data"

Default value for paramteters not passed SQLPlus script

Is there a way to set default value of paramter in sqlplus script without user input?
For example, I have an SQL script sessions.sql:
SET VERIFY OFF
SET TERMOUT OFF
DEFINE uname = '&1'
COLUMN search_uname new_value search_uname
SELECT CASE WHEN '&uname' = '' THEN '%' ELSE UPPER('&uname') END AS search_uname
FROM dual;
SET TERMOUT ON
SELECT sid, serial, username FROM v$session WHERE username LIKE '&search_uname';
And I want to invoke it from sqlplus like this:
SQL> #sessions
Enter value for 1:
SID SERIAL# USERNAME
---------- ---------- ------------------------------
56 20577 CONTEXT
.....
236 rows selected.
SQL> #sessions ""
SID SERIAL# USERNAME
---------- ---------- ------------------------------
56 20577 CONTEXT
.....
236 rows selected.
SQL> #sessions SDE
SID SERIAL# USERNAME
---------- ---------- ------------------------------
113 56675 SDE
165 64881 SDE
.....
43 rows selected.
SQL>
I can only pass an empty value for parameter when I am asked to enter it, or I am able to pass an empty parameter after script name through "". But this behaviour is very annoying. Some kind of IF DEFINED "&1" will be very usefull.
Do you have any tips or tricks how this should be achieved to apply WHERE conditions in sqlplus script wheter parameter is defined or not without unnecessary user interaction?
Solution
According to the article linked by Martin I modified previous script to be working without aksing for parameter values:
SET VERIFY OFF
SET TERMOUT OFF
column 1 new_value 1
SELECT '' "1" FROM dual WHERE ROWNUM = 0;
define uname = '&1'
SET TERMOUT ON
SELECT sid, serial#, username FROM v$session
WHERE username LIKE UPPER(DECODE('&uname', '', '%', '&uname'));
undefine 1
For those who don't fancy chasing and perusing links that can go away anytime, here's a quick cut'n paste snippet.
set termout on
set serveroutput on
set feedback off
set verify off
-- start
column 1 new_value 1 noprint
select '' "1" from dual where rownum = 0;
define param = &1 "default"
-- end
begin
dbms_output.put_line ( 'Param 1 value is &param' );
end;
/
exit 0
/
Execution:
$ sqlplus -s SCOTT/TIGER#ORCL #a.sql
Param 1 value is default
$ sqlplus -s POSF/POSF#ECMDB #a.sql nondef
Param 1 value is nondef
Please read "On SQL*Plus Defines" for an answer to your question.
Quote:
SQL> COLUMN 1 NEW_VALUE 1
SQL> COLUMN 2 NEW_VALUE 2
SQL> COLUMN 3 NEW_VALUE 3
SQL> COLUMN 4 NEW_VALUE 4
SQL> SELECT '' "1", '' "2", '' "3", '' "4"
2 FROM dual
3 WHERE ROWNUM = 0
4 /
no rows selected
SQL> DEFINE 1
DEFINE 1 = "1" (CHAR)
SQL> DEFINE 2
DEFINE 2 = "2" (CHAR)
SQL> DEFINE 3
DEFINE 3 = "" (CHAR)
SQL> DEFINE 4
DEFINE 4 = "" (CHAR)
SQL>
SQL> REM ...but...
SQL>
SQL> DEFINE 5
SP2-0135: symbol 5 is UNDEFINED

Connecting to two different databases and compare the table result using shell script

I have a task of copying the data from one database to another.I don't have privileges to create DB Link.So, I have achieved this task using COPY command in shell script. But now, I need to compare the count of records between the databases. I used to do this manually. But now,I want to automate this.
As per my knowledge, Sqlplus allows me to connect to one database at a time. But I want something like
sqlplus -s un/pwd#sid <<EOF
SELECT count(*) FROM table1 WHERE column1 = 'abc' -- first database
UNION ALL
SELECT count(*) FROM table1 WHERE column1 = 'abc'; -- second database
exit
EOF
Is it possible to omit sqlplus string and add it in the query?
Thanks,
Savitha
You might want to use sqlplus substitution variables to store the query results:
http://docs.oracle.com/cd/B19306_01/server.102/b14357/ch5.htm#sthref1114
These variables are global to a SQL*Plus instance, so they retain their values upon connecting to another database.
Example:
SQL> variable var1 number
SQL> variable var2 number
SQL> conn a/b#ccc
Connected.
SQL> begin
2 select 1111 into :var1 from dual;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> print var1
VAR1
----------
1111
SQL> conn a/b#ddd
Connected.
SQL> print var1
VAR1
----------
1111
SQL> begin
2 select 2222 into :var2 from dual;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL> print :var2
VAR2
----------
2222
SQL>
We can also see them like this:
SQL> print :var2 :var1
VAR2
----------
2222
VAR1
----------
1111
SQL>
And use them in PL/SQL:
SQL> set serveroutput on
SQL> declare
2 v1 number := :var1;
3 v2 number := :var2;
4 begin
5 dbms_output.put_line('The difference is: '||to_char((v2-v1)));
6 end;
7 /
The difference is: 1111
PL/SQL procedure successfully completed.
SQL>
you can rush something like this:
A sql file, let's name it tmp.sql:
select count(*) from user_tables;
--SELECT count(*) FROM table1 WHERE column1 = 'abc';
exit;
A sh file, let's name it tmp.sh:
echo pass1 | sqlplus -s user1#sid1 #tmp.sql
echo pass2 | sqlplus -s user2#sid2 #tmp.sql
./tmp.sh would output something like:
Enter password:
COUNT(*)
----------
1717
Enter password:
COUNT(*)
----------
68
(chmod +x tmp.sh)
These scripts can be improved, but this can be a start.
The COPY command is deprecated in SQL*Plus, and has a lot of limitations.
Data pump would be a much more robust way of handling this situation.

Resources