Pass substitution variable to nested script - oracle

I have a situation where I have a number of scripts that I need to run consecutively under the one connection. Some of the scripts require human input at runtime. The way I have organised this is that I have a Windows batch file which prompts the user for the required parameters. That batch file then passes the acquired parameter values to the SQL script.
The problem is that the variable values aren't getting to the nested script. If I bypass the intermediate script it works fine. It seems as though the problem is in proxying the values to the second.
See below for a compelte test case. In my example I am only calling one nested Script (Script1.sql). However, in a real world scenario I would potentially have multiple of these scripts.
Create Table
CREATE TABLE TEST_TABLE
(
TEST_ID NUMBER,
CREATED_BY VARCHAR2(100 CHAR)
)
LOGGING
NOCOMPRESS
NOCACHE
RESULT_CACHE (MODE DEFAULT)
NOPARALLEL
MONITORING;
SET DEFINE OFF;
Insert into TEST_TABLE
(TEST_ID, CREATED_BY)
Values
(1, 'FirstUser');
Insert into TEST_TABLE
(TEST_ID, CREATED_BY)
Values
(2, 'SecondUser');
Insert into TEST_TABLE
(TEST_ID, CREATED_BY)
Values
(3, 'ThirdUser');
COMMIT;
Windows Batch File (TEST_BAT.bat)
:begin
#ECHO oFF
cls
set /p SID=DB_SID:
set /p USER=USER:
set /p USERPASS=USER PASS:
set /p NEW_USER_NAME=NEW USER NAME:
ECHO %SID%
ECHO %USER%
sqlplus %USER%/%USERPASS%#%SID% #TEST_SCRIPTS.sql %NEW_USER_NAME%
ECHO.
Master SQL Script (TEST_SCRIPTS.sql)
SET PAGESIZE 100
SET DEFINE OFF
SET SCAN OFF
SET FEEDBACK ON
SPOOL INSTALL_LOG.txt
#'Script1.sql' &1
SET FEEDBACK OFF
Nested Script 1 (Script1.sql)
SET PAGESIZE 100
SET DEFINE OFF
SET SCAN OFF
SET FEEDBACK ON
UPDATE TEST_TABLE SET CREATED_BY='&1';
COMMIT;
So, in summary - what am I doing wrong in getting the substitution parameter to the nested Script

I'm not entirely sure from your post whether the problem was that the script prompts for &1 to be input, or whether the value &1 is being written for CREATED_BY instead of the provided command-line arg.
If the latter, this problem may be related to using SET DEFINE OFF prior to accessing the arg rather than the structure of the scripts themselves. (By the way SET SCAN is obsolete).
Using your example table and scripts unaltered, I get the below (with sql-plus 12.2):
sqlplus myuser/mypass#mydatabase #TEST_SCRIPTS.sql VOLTRON
SQL*Plus: Release 12.2.0.1.0 Production on Wed May 31 12:58:46 2017
3 rows updated.
Commit complete.
SELECT * FROM TEST_TABLE;
TEST_ID CREATED_BY
1 &1
2 &1
3 &1
But, if one drops the SET DEFINE OFF (and SET SCAN OFF), the substitutions take place, as below:
sqlplus myuser/mypass#mydatabase #TEST_SCRIPTS.sql VOLTRON
SQL*Plus: Release 12.2.0.1.0 Production on Wed May 31 13:11:53 2017
old 1: UPDATE TEST_TABLE SET CREATED_BY='&1'
new 1: UPDATE TEST_TABLE SET CREATED_BY='VOLTRON'
3 rows updated.
Commit complete.
Now the replacement has been passed through into the inner script.
SELECT * FROM TEST_TABLE;
TEST_ID CREATED_BY
1 VOLTRON
2 VOLTRON
3 VOLTRON

Related

How to rollback automatically if script having error in Oracle sql plus

I need to execute the multiple script having one master sql file. Whenever I used to execute the master calling script named as calling_test.sql if anything error comes need to be rollbacked.
sqlplus USERNAME/PWD#SIR_NAME;
##calling_test.sql
here is content of calling_test.sql script.
SET echo ON;
SET define ON;
SET scan ON;
define PATH =/krishna/test
define AB_SCHEMA=AIM
spool Test_incremental.log
SET define ON;
##&&PATH/AUG/2019-08-28/test1.sql
SET define ON;
##&&PATH/AUG/2019-08-29/test2.sql
SET define ON;
##&&PATH /AUG/2019-08-30/test3.sql
SET define ON;
The scrip should contain something like this:
whenever sqlerror exit rollback
Example:
SQL> create table test (col number);
Table created.
SQL>
SQL script (named p.sql)
whenever sqlerror exit rollback
insert into test values (100);
insert into test values ('A');
Calling it:
M:\>sqlplus scott/tiger#orcl #p.sql
SQL*Plus: Release 11.2.0.1.0 Production on ╚et Ruj 26 13:38:50 2019
Copyright (c) 1982, 2010, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
1 row created.
insert into test values ('A')
*
ERROR at line 1:
ORA-01722: invalid number
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
M:\>
Result:
SQL> select * From test;
no rows selected
SQL>
You can rollback the actions from called scripts, but in addition to WHENEVER command you must also SET AUTOCOMMIT OFF. Normally when Sqlplus exits a script invoked in a separate file it commits. However the preceding overrides that action. See below: (save each script to the indicated file.)
---------------------------------------------------------------------------- -- script mst_0.sql
create table multi_script_test( id integer, description varchar2(50));
insert into multi_script_test values( 0, 'Initial before script.');
commit;
-- script mst_1.sql
insert into multi_script_test values( 1, 'Insert from script mst_1');
-- script mst_2.sql
insert into multi_script_test values ( 2, 'Insert from script mst_2');
-- script mst_3.sql
insert into multi_script_test values ( 3/0, 'oops');
-- script mst_4.sql
insert into multi_script_test values ( 4, 'Insert from script mst_4');
-- main script mst_main.sql
set echo on
set autocommit off
whenever sqlerror continue rollback
##c:/so/ora/mst_0.sql
##c:/so/ora/mst_1.sql
##c:/so/ora/mst_2.sql
-- following should display rows 0, 1, 2
select * from multi_script_test;
-- generate error and due to whenever directive 'rollback' discard rows 1,2
#c:/so/ora/mst_3.sql
-- continue script processing, also due to whenever directive 'contunue'
#c:/so/ora/mst_4.sql
commit;
----------------------------------------------------------------------------
sqlplus -- complete the signon
-- run main script
#mst_main
-- following show show display 0, 4
select * from multi_script_test;
exit

SQLPLUS connection to different dbs

Hello i want to connect to following dbs in loop and execute statements on each:
conn support/support#sp0666to
conn support/support#sp0667to
conn support/support#sp0668to
Is there any way to do this in sqlplus?
Thank you for your answers in advance!
Create one script (doWork.sql) that contains the majority of what you want to do:
conn &1/&2#&3
select EMPLOYEE, AUTHORIZED, TIME, DAT, WORKSTATION
from EMPLOYEE
where status = 25;
In a separate script (goToWork.sql):
set lines 1500 pages 10000
set colsep ';'
set sqlprompt ''
set heading on
set headsep off
set newpage none column tm new_value file_time noprint
select to_char(sysdate, 'DDMMYYYY_HH24.MI') tm from dual;
accept user
accept pass
spool C:\Users\NANCHEV\Desktop\parked.csv
##doWork &user &pass sp0666to
##doWork &user &pass sp0667to
##doWork &user &pass sp0668to
spool off;
exit
If you want separate files, then move the two spool commands to the doWork.sql file.
Assuming you want to run the same set of queries for each database, I'd create a script file (e.g. main_statements.sql) containing those statements.
Then, if the list of databases was static, I'd create a second script file (e.g. run_me.sql) in the same directory, with contents along the lines of:
connect &&user/&&password#db1
##main_statements.sql
connect &&user/&&password#db2
##main_statements.sql
connect &&user/&&password#db3
##main_statements.sql
...
If, however, the databases are static but the list is contained in a database somewhere, then I'd write a script (e.g. run_me.sql) that generates a script, something like:
set echo off
set feedback off
set verify off
spool databases_to_run_through.sql
select 'connect '||username||'/'||password||'#'||database_name||chr(10)||
'##main_statements.sql'
from list_of_databases_to_query;
spool off;
##databases.run_through.sql
N.B. untested. Also, I have assumed that your table contains the usernames and passwords for each db that needs to be connected to; if that's not the case, you'll have to work out how to handle them; maybe they're all the same (in which case, you can hardcode them - or better yet, use substitution variables (e.g. &&username) to avoid having to store them in a plain file. You'd then have to enter them at runtime.
You'll also need to run the script from the same directory, otherwise you could end up with the generated script not being created in the same directory as your main_statements.sql equivalent script.
Yes it's possible, you can use oracle DBLink to connect to different dbs just like your example.

How to export half a million records from PL/SQL

I've a table with around 500,000 records. I need all records to be exported in excel. When I query I'm not able to get all as I was said as Out Of memory
Table doesn't have any primary key/Index.
Is there any way to extract?
it would be very easy in to write file output form sqlplus .
mycsv.sql:
SET DEFINE OFF
SET ECHO OFF
SET SERVEROUTPUT OFF
SET TERMOUT OFF
SET VERIFY OFF
SET FEEDBACK OFF
SET PAGESIZE 10000
SET ARRAYSIZE 5000
REM SET HEAD OFF
SET LINE 500
spool /tmp/mycsvfile.csv;
select * from MY_table;
spool off;
exit;
and from Linux prompt you can run like
$> sqlplus username/password #/tmp/mycsv.sql

PL SQL output is not getting displayed

I have fairly simply code ..running in Oracle Virtualbox. However for some reason it is not displaying pl/sql output.
Here is code snippet
SQL> set serveroutput on
SQL> list
1 Create or Replace procedure mytz
2 IS
3 v_mytz TIMESTAMP WITH TIME ZONE DEFAULT '2013-05-05 12:00:00 AM';
4 BEGIN
5 DBMS_OUTPUT.PUT_LINE ('Default timestamp is ' );
6* end mytz ;
SQL> /
Procedure created.
SQL>
Is there anything I need to do special to see the output on SQL prompt ?
You have to actually run the procedure, not just create it, e.g.:
set serverputput on
exec mytz;
The set serveroutput SQL*Plus command has to be in the session the procedure is executed, not the one where it is created (if they are different).
You are not showing the value of your variable at the moment; maybe you wanted this?
dbms_output.put_line('Default timestamp is: ' || v_mytz);

Oracle 11g Report Problem

Hey friends i am using Oracle 11G. I wanted to generate reports for printing , SO i write this script
rem Employee Salary Report
set headsep !
ttitle 'Salary Report'
btitle 'From Employees'
column employee_id format 999.99
column first_name format a20
column last_name format a20
column Salary format 999.99
break on employee_id skip 1 on report
set linesize 80
set pagesize 5
set newpage 0
set feedback off
set pause 'More...'
set pause on
spool activity.lst
select employee_id,first_name,last_name,salary from Employees order by employee_id ;
spool off
When running this script oracle gives
line 3: SQLPLUS Command Skipped: set headsep !
line 15: SQLPLUS Command Skipped: set linesize 80
line 16: SQLPLUS Command Skipped: set pagesize 5
line 17: SQLPLUS Command Skipped: set newpage 0
and then it executes query and gives output. But my report doesn't include any title in it.Means reports is not generated properly. It just simply executes the select query and gives an output which is not a report.
Did you have a question?
What you show us looks very much like the output we would expect if your script was run from the SQL Worksheet in Oracle SQL Developer.
Those commands that are being skipped are specific to SQL*Plus, and are not supported in SQL Developer (at least, in the version I'm running).
To get a formatted report produced by SQL*Plus, I would run the sqlplus executable from the OS e.g.
> $ORACLE_HOME/bin/sqlplus /
SQL> #/home/spencer7593/myreport.sql
SQL> exit
>
I'm not sure that answers a question, since I don't know what your question was.

Resources