pass sqlplus value to shell variable - oracle

the below picture shows what gets returned when I run sqlplus in shell
but when I run this from the "run" command:
powershell.exe -noexit c:\sqltriggers\voicetrigger2.ps1
with voicetrigger2.ps1 as this:
$(sqlplus user/pass#OMP1 '#C:\sqltriggers\VOICEBLOCKTRIG.SQL');
I get this:
I should expect a 3 back. The issue is, I try to set that as a variable, and if the integer is greater than zero, run a BAT file. But I don't think the SQLPlus is returning JUST an integer value. I think its actually returning this:
count(*)
3
How do I get it to just return the integer value from the SQLplus command?

SQL*Plus isn't returning anything, it's displaying the result of the query on standard output. To get the direct call to only show 3 you can set heading off in the SQL script, and also call SQL*Plus with the -s flag to suppress the banner. You probably also want an exit at the end of the SQL script so it doesn't stay sitting at the SQL> prompt.
The same applies to the powershell call, but there's something else going on there; the 17 is a line number which means it's waiting for more input and hasn't executed the commands in the SQL script, which suggests either a query without a terminating ; or /, or a PL/SQL block without a terminating /. But if it's exactly the same SQL you ran in the first example then that is a bit odd as they should behave the same. You should add the SQL script contents to the question to see what might be wrong.
The only thing I can think of that would change behaviour like that is if you had a login.sql that includes a set sqlterminator command, but you'd have to be picking up different login.sql files from the two calls... which is plausible if powershell has its own environment variables, perhaps.

It won't work this way. As Alex mentioned, sqlplus doesn't return anything as a function - it only writes whatever output you generate to standard output.
You can have variables in sqlplus, but there is no easy way to pass them to host environment. The only way I can think of is to use spool command to generate another batch file, which will actually set your host variables, and then process them the way you want in your host script.
Something like this:
16:30:20 SYSTEM#sandbox> get host.sql
1 SET VERIFY OFF TRIMSPOOL ON TERMOUT OFF HEADING OFF LINESIZE 4000 PAGES 0 FEEDBACK OFF timing off
2 spool s:\.tmp\host.ps1
3 select '$env:MY_VAR="'||dummy||'"' from dual;
4 spool off
5* exit
16:30:25 SYSTEM#sandbox> #host.sql
Disconnected from Oracle Database 11g Express Edition Release 11.2.0.2.0 - Production
PS S:\.tmp> cat host.ps1
$env:MY_VAR="X"
PS S:\.tmp> .\host.ps1
PS S:\.tmp> $env:my_var
X
PS S:\.tmp>

sqlplus -s /nolog <<EOF > query_result.txt
set heading off feedback off pagesize 0 linesize 30000 trimout on ;
select 5 from dual;
exit;
EOF
for i in `cat query_result.txt `
do
exit $i
done

try adding SET HEADING OFF in the beginning of your file. Check this answer (check the second best voted answer)

Related

Oracle SQL Script - Why spool creates file twice

I run the following SQL-script using Oracle SQL Developer. I don't know why it creates two spool file and it also displays the entire operations in the Oracle SQL Developer console which it should not. Maybe it is due to the SET FEEDBACK ON and SET FEEDBACK OFF for each delete statement.
It creates two files and displays everything in script-output only when there are some records for deletion.
The script's call
#"C:\RM.sql"
The script
SET PAGES 0
SET LINESIZE 10000
SET TRIMS ON
SET ECHO OFF
SET HEADING ON
SET VERIFY OFF
SET FEEDBACK OFF
SET TERMOUT OFF
SET SERVEROUTPUT on size 1000000
SET TIMING OFF
SET COLSEP '|'
alter session set NLS_DATE_FORMAT = 'dd.mm.yyyy hh24:mi:ss';
whenever oserror exit -1
whenever sqlerror exit -2
-- The current timestamps into 'times' variable
column times new_value times noprint
select to_char(sysdate, 'YYYYMMDD_HH24MISS') times from DUAL;
-- variables definition
define output_file="C:\temp\filename_&times..log"
-- echo some text to the standard output
SET TERMOUT ON
PROMPT
PROMPT "The script counts and reports the records to be deleted..."
PROMPT
SET TERMOUT OFF
-- write the results to the 'output_file' file
spool &output_file
PROMPT
PROMPT "BEGIN------------------------------"
PROMPT "delete from the_table1"
select 'Total records BEFORE delete: ' || count (*) as count_records from the_table1;
SET FEEDBACK ON
PROMPT "Actual deletion of records..."
delete from the_table1;
commit;
SET FEEDBACK OFF
PROMPT "END------------------------------"
PROMPT
PROMPT "BEGIN------------------------------"
PROMPT "delete from the_table2"
select 'Total records BEFORE delete: ' || count (*) as count_records from the_table2;
SET FEEDBACK ON
PROMPT "Actual deletion of records..."
delete from the_table2;
commit;
SET FEEDBACK OFF
PROMPT "END------------------------------"
PROMPT
PROMPT "The script completed..."
SPOOL OFF
SET TERMOUT ON
PROMPT
PROMPT "&output_file has been successfully ended."
PROMPT
PROMPT
EXIT
;
I seem to recall TERMOUT and ECHO options depend on how sqlplus is being run and can give different results, similar to what you are seeing.
I'm using sqlplus as a example of how interactions with the run environment can affect output. This isn't really an answer, and I cannot reproduce the scenarios I used to see often, but I hope the following perhaps will offer some pointers as to what might be encountered.
Start with a simple test script test_off.sql:
set echo off
set termout off
prompt text1
spool f1.txt
prompt text2
spool off
prompt text 3
quit
Now let's run it a number of different ways:
1 Non-interactively Parameterised
$ sqlplus -S un/pw#idb #test_off.sql
$ cat f1.txt
text2
No output to screen, spool file created, with only the spooled contents.
2. Interactively
$ sqlplus -S un/pw/#db
#test_off.sql
$ cat f1.txt
text2
No output to screen, spool file created, with only the spooled contents.
3. Run as piped feed
$ cat test_off.sql | sqlplus -S un/pw#db
text1
text2
text 3
Here we see all the PROMPT command results on screen.
Similar effects may be seen if run within a HEREDOC block.
I've definitely seen (in older versions) some strange inconsistencies and perhaps your SQL Developer is similarly afflicted.

Run sqlplus commands from multiple files with query logging or spool in Windows Batch File

I am quite new to batch scripting, and I am trying to run multiple sql files, which in turn may contain multiple sql DML/DDL queries from bat file. The output files must contain all the queries being executed and the query output. Unlike this example , I don't have spool command inside my sql file, and I can not edit the input sql files. The following command works for me in ksh file (thanks to here-document):
$sqlplus /nolog <<! >>$sqlLogs.lst
connect $USERNAME/$PASSWORD#${DBNAME}
set echo on timing on
spool ${SCRIPTRUNFILE_SPOOL}
select name from v\$database;
#${SCRIPTRUNFILE};
spool off
exit
!
I want the exact same in Windows bat file. I have tried using ^. I can't do combine all sql files into one, as I need logging for each sql file into different file. My attempt at the bat file script is as follows and I have played around this much, and it fails with spool command not recognized. I also prefixed below commands with sqlplus, but still unable to achieve something like above ksh file:
sqlplus -s username/pwd#DBName >> sqlLogs.lst
set echo on timing on
spool %RUNFILENAME%.lst
#%RUNFILENAME% > %RUNFILENAME%.lst
select name from v\$database;
spool off
quit
Following logic executes my scripts but does not log the query being executed. Also, I don't want to connect twice to the database.
echo select name from v$database; | sqlplus -s username/pwd#DBName >> sqlLogs.lst
echo quit | sqlplus -s username/pwd#DBName #%SCRIPTRUNFILE%>> %SCRIPTRUNFILE_SPOOL%.lst
Can someone here please help to spool to a file where I can log the queries as well, while maintaining a single DB Connection?
Pass your immediate SQL*Plus commands to your sqlplus via stdout, grouped together by Windows' ( and ) symbols...
(
echo.set echo on timing on
echo.spool %SCRIPTRUNFILE_SPOOL%
echo.select name from v$database;
echo.#%SCRIPTRUNFILE%
echo.spool off
echo.exit
) | sqlplus -s %USERNAME%/%PASSWORD%#%DBNAME% >> sqlLogs.lst

Use oracle SET values in PL/SQL

I was requested to set some environment parameters to migration files. However, such parameters as SQLBLANKLINES for instance, are only valid in sqlplus, other tools (e.g. Flyway) would be broken by its usage. Same is for autocommit.
Is there any way to perform following:
declare
v1 varchar2(60)
begin
v1 := SHOW SQLBLANKLINES
if (v1 is not empty) then
SET SQLBLANKLINES ON
end if;
end;
/
Or somehow query environment for available parameters to set?
Or somehow determine that exactly sqlplus is being used?
I'm aware of SHOW and SET commands, but I don't know how to place their results to variable and call SET inside PL/SQL.
Oracle is 11g.
You can't reference SQL*Plus commands in PL/SQL, as PL/SQL doesn't recognise them. Moreover, you can't use conditional statements directly in a SQL*Plus script, so you have to get a bit creative. You can, however, have a script that creates and runs another script, which you can use to inject conditional statements.
For example, this is a script that I use to either let my release script continue or not (it exits SQL*Plus):
continue_or_exit.sql:
prompt Do you want to continue script execution?
accept yn prompt 'Y / N : ';
set termout off;
set verify off;
set heading off;
set pause off;
set echo off;
column aaaa newline;
spool continue_or_exit_output.sql
select decode(upper('&&yn'), 'Y', 'prompt Executing ...',
'prompt Stopped'
),
decode(upper('&&yn'), 'Y', '', 'accept return_key prompt ''Press <Return>''') aaaa,
decode(upper('&&yn'), 'Y', '', 'exit') aaaa
from dual;
spool off;
set termout on;
#continue_or_exit_output.sql
set termout on;
set verify on;
set heading on;
You ought to be able to amend that for your case to decide whether to print out the relevant SQL*plus commands or not.
You cannot call SQL*Plus, or any client, commands from within PL/SQL. It is executed entirely on the server. You can tell which client is being used, at least if the client is well-behaved, but that doesn't really help you as you still can't use that information to control which client commands are issued.
The simplest approach may be to write a core script with the migration commands, and then a wrapper script for specific clients; so if you had core_migration.sql you could have another script called sqlplus_migration.sql that just did:
SET SQLBLANKLINES ON
-- any other SQL*Plus-specific set-up you want
SET PAGESIZE 0
SET LINESIZE 200
SET SERVEROUTPUT ON SIZE UNLIMITED
WHENEVER SQLERROR EXIT FAILURE
-- etc.
-- Run core migration script
#core_migration
exit 0;
SQL*Plus needs to be able to find the core script though, so it might be better/necessary to pass the full path to that with a substitution variable:
...
SET DEFINE ON
-- Run core migration script passed via command line
#&&1
exit 0;
... then call it as:
sqlplus -s -l usr/pwd #sqlplus_migration /path/to/core_migration.sql
(I don't like putting the credentials on the command line; your script could prompt for them instead but you suggested you wanted it to be non-interactive).
I'm not familiar with Flyway - it may just want to call the core script with no extra steps.

Can I keep the session in SQLPlus alive, and reconnect to the same session? BASH-related

I have a loop in Bash, it was working like a charm until today. The loop looks like:
while read line1 ; do
while read line2 ; do
stringArray=($line2)
string=$line1.${stringArray[1]}
sqlplus /nolog <<EOF
connect sysuser/syspassword#db_instance
alter system flush shared_pool;
quit
EOF
sqlplus -s /nolog > /dev/null 2>&1 <<EOF
connect user/password#db_instance
variable rc refcursor;
SPOOL ${line1}_${stringArray[0]}.DATA
exec :rc := $string;
print rc;
spool off
exit
EOF
done < file2.txt
done < file1.txt
To clarify one thing, the contents of the variable $string are Oracle packages with functions and parameters:
SOMEPACKAGE.SOMEFUNCTION(some,'parameters',here,'sometimes',NULL,'or',numbers)
Now - Until the package was doing what it should do in just one parametrized run - everything was perfectly fine. But now I have encountered a package that does its job in 5 steps, steps determined by the last parameter. It looks like this:
SOMEPACKAGE.SOMEFUNCTION(some,'parameters',here,'sometimes',NULL,'or',1)
SOMEPACKAGE.SOMEFUNCTION(some,'parameters',here,'sometimes',NULL,'or',2)
SOMEPACKAGE.SOMEFUNCTION(some,'parameters',here,'sometimes',NULL,'or',3)
SOMEPACKAGE.SOMEFUNCTION(some,'parameters',here,'sometimes',NULL,'or',4)
SOMEPACKAGE.SOMEFUNCTION(some,'parameters',here,'sometimes',NULL,'or',5)
The first one, with the 1 on end, is producing a TEMPORARY_TABLE on which the other jobs (2 to 5) are working. The Job number 5 is supposed to give the results of the whole chain too.
Until I had packages doing their Job in 1 step, running this loop was just perfect. But the TEMPORARY_TABLE is dissappearing after disconnecting, and I cannot just add a special section in my bash script just for this one package, cause there could be much more packages, with different number of steps. This has to be done automatically, without too much effort from the users that will consume this script.
So is there a way of keeping the session alive? Or is there any other way to do this?
Instead of storing just a single procedure call in $string try writing an anonymous block to the variable and executing that. The block can contain multiple calls to to the procedure (along with other things) and won't return until they have all completed.

Running pl/sql in Korn Shell(AIX)

I have a file to execute in Ksh written by someone. It has a set of commands to execute in sqlplus.
It starts with,
sqlplus -s $UP <<- END
followed by a set of ddl commands such as create,drop,etc.,
When I execute the file in the shell, I get the error in the starting line quoted above.
I understand "-s" starts the sqlplus in silent mode and $UP is the connection string with username/password. But I couldn't make heads or tails of "<<- END" part(Many sites from google says input redirection is "<<" not "<<-"). So I presumed the error must be in that part and removed it from the file.
Now it reads,
sqlplus -s $UP
But once I execute the file, It waits for input from the shell, instead of reading the rest of the lines from the file. How would I make sqlplus to execute the ddl commands in the rest of the file?. Thanks in advance.
Here "END" is a block marker and "-" is not required.
For running sqls from a shell script , One simple example is given below.
sqlplus system/manager << ENDOFSQL
whenever sqlerror exit sql.sqlcode;
select sysdate from dual;
exit;
ENDOFSQL
Thanks,
Rinson KE
DBA

Resources