How to configure SQLcl prompt to be 2 lines? - oracle

For a long time now, I've had my login.sql file configured to set the prompt in SQLPLUS to two lines, so that it looks like so:
my_username#my_db_instance
SQL>
The code within login.sql that accomplishes this is below (the chr(10) is what creates the 2nd line):
define gname = 'SQL'
column global_name new_value gname
select user||'#'||instance_name||chr(10)||'SQL' as global_name
from v$instance;
set sqlprompt '&&gname> '
However, the same does not work for SQLcl, and the same code results in the SQLcl prompt appearing all one line, like so
my_username#my_db_instance SQL>
I tried replacing the chr(10) with chr(13), chr(13)||chr(10), and u'\000A', but the SQLcl prompt displays on one line regardless. I've confirmed that SQLcl is actually reading the login.sql in question by making other changes to the prompt (e.g. replacing SQL with SQL1), and those changes worked.
Does anyone know whether it's possible to separate the SQLcl prompt into 2 lines? And if so, how?
(ps, I realize this is a pretty petty annoyance, but though I like having the connection info in the prompt, having the 1st line of all my sql starting way off to the right is just...yuck :)

This is just a workaround.
I use a window "title" for this. I think it's more convenient:
You can create a script like this:
https://github.com/xtender/xt_scripts/blob/master/inc/title.sql
and add it into your on_login.sql, for example from my own on_login.sql:
#inc/title "&db_name / &my_user / &db_host_name SID=&my_sid SERIAL#=&my_serial SPID=&my_spid IS_DBA=&my_is_dba / INST_ID = &DB_INST_ID / DB_VERSION = &DB_VERSION"
Other my sql*plus tips: http://orasql.org/tag/sqlplus-2/

Related

Remove/Prevent First Blank from Oracle CSV MARKUP output file

I am currently writing scripts to output table data to CSV files so that they can be ingested into another platform. I'd much rather use the set markup CSV on quote on; SQL option to generate my output file. as it makes the script much cleaner and a whole lot simpler to write.
The problem, however, is that no matter how hard I try, I cannot seem to find an option that will prevent the output file from starting with a blank line. I need the column headers in the very first line and not in the second line.
The scripts need to run on a Windows Server against an Oracle 12c (12.1.0.2.0) Database, using SQLPLUS to execute the SQL commands and PowerShell/batch as the scripting wrapper.
After searching for some time and trying various options that only seem to have any effect on older approaches to CSV outputs. Eventually, I found the Oracle documentation for the SET command and discovered that things like SET NEWPAGE, SET TRIMSPOOL have no effect when using SET MARK[UP].
Oracle SET Command documentation is here: https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqpug/SET-system-variable-summary.html#GUID-0AA910C4-C22A-4A9E-BE13-AAA059CC7919
Is there a simple way to get rid of or suppress the first line that is blank? I really don't want to have to write further file processing scripts that go and remove the line from the file using PowerShell/Batch. That just seems like a really dumb thing to have to do...
A simplified version of my SQL is below and the output still includes the blank first line.
column thespoolfile new_value thespoolfile
select 'D:\Temp\outfile-detail-' || TO_CHAR( sysdate, 'YYYYMMDDHH24MI' ) || '.csv' as thespoolfile from dual;
set markup csv on quote on;
SET FEEDBACK OFF;
set trimspool on;
SET HEADSEP off;
SET SQLBLANKLINES off;
SET termout OFF;
spool &thespoolfile;
set define off;
select *
from <table>;
spool off;
exit
You need to use the following option
SET NEWPAGE NONE
It will suppress the first blank line, which is bothering you.
Cheers!!

Unable to export dynamic Oracle table to properly formatted CSV using sqlplus

I am trying to substitute a Python/pandas export process and go direct from Oracle to csv. I have seen a couple of posts such as this one here
Suppose I have a table in Oracle with three columns: ColA, ColB, ColC. I want to employ a command line utility that takes as input an SQL command and generates a CSV file that would look like any standard CSV file with a header line and rows of values:
ColA,ColB,ColC
A,B,C
D,E,F
...
In SQL Server, there is a utility called bcp I can use which looks like this:
bcp "SELECT 'ColA', 'ColB', 'ColC' UNION ALL Select ColA, ColB, ColC From
myTable" queryout "C:\Temp\csvfiles\output.csv" -c -CRAW -S localhost -u
my_userid -p my_password -d my_database
Easy-peasy. But in looking for the Oracle equivalent, not so much.
I took a look here but the author wants you to create a UTL_FILE. That doesn't seem like a possibility since this is supposed to be a completely generic process that gets built and run from Python. I took a look at sqlplus but I can't seem to come up with a way to create a typical CSV similar to bcp. The docs here weren't terribly clear on this either. It's such a common format I expected to see tons of examples.
Sites like this here show how to output a fixed-length CSV using sqlplus but don't show you how to add a header row and values are padded, which might be OK, but not desirable. This was about the best I could come up with:
set colsep ,
set headsep off
set pagesize 0
set trimspool on
set linesize 200
set numwidth 50
SET TERMOUT OFF
Spool output.csv
SELECT ColA,
ColB,
ColC
FROM MyTable;
Spool off
exit
So, is there an equivalent tool/command in Oracle to the trusty bcp, or is there a sample somewhere using sqlplus that can generate a csv similar to the one above with a header line and without all the leading spaces? Or is there another option to generate dynamic CSV files from random Oracle tables? Or am I stuck using Python, pyodbc and pandas to get my nicely-formatted CSV files? TIA
Oracle's SQLcl utility(commandline executable sql or sql.exe) could help you achieve it.
Here's the download link SQLcl. It's free.
In order to export a file in the CSV format, you may simply specify
SET SQLFORMAT CSV
If you want a different delimiter, use
SET SQLFORMAT DELIMITED '|'
Here's a sample output with the header
SQL> select * from employees;
"EMPLOYEE_ID","FIRST_NAME","LAST_NAME","EMAIL","PHONE_NUMBER","HIRE_DATE","JOB_ID","SALARY","COMMISSION_PCT","MANAGER_ID","DEPARTMENT_ID"
198,"Donald","OConnell","DOCONNEL","650.507.9833",21-06-07,"SH_CLERK",2600,,124,50
199,"Douglas","Grant","DGRANT","650.507.9844",13-01-08,"SH_CLERK",2600,,124,50
200,"Jennifer","Whalen","JWHALEN","515.123.4444",17-09-03,"AD_ASST",4400,,101,10
201,"Michael","Hartstein","MHARTSTE","515.123.5555",17-02-04,"MK_MAN",13000,,100,20
202,"Pat","Fay","PFAY","603.123.6666",17-08-05,"MK_REP",6000,,201,20
203,"Susan","Mavris","SMAVRIS","515.123.7777",07-06-02,"HR_REP",6500,,101,40
204,"Hermann","Baer","HBAER","515.123.8888",07-06-02,"PR_REP",10000,,101,70
205,"Shelley","Higgins","SHIGGINS","515.123.8080",07-06-02,"AC_MGR",12008,,101,110
206,"William","Gietz","WGIETZ","515.123.8181",07-06-02,"AC_ACCOUNT",8300,,205,110
100,"Steven","King","SKING","515.123.4567",17-06-03,"AD_PRES",24000,,,90
101,"Neena","Kochhar","NKOCHHAR","515.123.4568",21-09-05,"AD_VP",17000,,100,90
102,"Lex","De Haan","LDEHAAN","515.123.4569",13-01-01,"AD_VP",17000,,100,90
103,"Alexander","Hunold","AHUNOLD","590.423.4567",03-01-06,"IT_PROG",9000,,102,60
104,"Bruce","Ernst","BERNST","590.423.4568",21-05-07,"IT_PROG",6000,,103,60
105,"David","Austin","DAUSTIN","590.423.4569",25-06-05,"IT_PROG",4800,,103,60
106,"Valli","Pataballa","VPATABAL","590.423.4560",05-02-06,"IT_PROG",4800,,103,60
107,"Diana","Lorentz","DLORENTZ","590.423.5567",07-02-07,"IT_PROG",4200,,103,60
108,"Nancy","Greenberg","NGREENBE","515.124.4569",17-08-02,"FI_MGR",12008,,101,100
109,"Daniel","Faviet","DFAVIET","515.124.4169",16-08-02,"FI_ACCOUNT",9000,,108,100
Additionally, all the SQL* Plus commands are supported with few more specific to SQLcl. See this command line reference
SET MARKUP CSV ON - use this in sqlplus before executing the query to get the data in csv format

Spooling to a file with a name containing a space and script's parameter in sqlplus?

I'm trying to change a script with a parameter to spool the output into specific path. After searching Stack Overflow I came up with:
column filename new_val filename
select '"i:\Direct bank\incoming\ROSE\report_zgod_' || '^1' ||'.csv"' filename from dual;
spool &filename
This creates correct filename "i:\Direct bank\incoming\ROSE\report_zgod_2017-08-28.csv" (I have tried to put it literally instead of &filename and the file has been created), but it still does not write a file. My guess is that's because there is a space in the path.
I have also tried
spool "&filename"
spool '&filename'
but to no avail.
I can't avoid parameter (it's used in other places in script and it can't be really calculated from SYSDATE) and I can't change the path (it has to be somewhere under "I:\Direct bank").
How can I have both the parameter and the space in spool file's name?
OK, I found the answer in comments to https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:3581757800346555562 .
The author of the original script has changed the defaults, so that I have to use
spool ^filename
instead of
spool &filename
In case you have similar problem, the orginal code contained:
set define "^"
set sqlprefix "^"
And that was the reason I could not get the file created.
When the path has a space in it then try using the short form of the path name. So, to SPOOL to /opt/oracle/oradata/Custom Scripts/orders_between_dates.txt; it's...
SQL> SPOOL /opt/oracle/oradata/Custom~1/orders_between_dates.txt;
If you're running it from a .sql script then put "" around it, like this...
SET FEEDBACK OFF;
SET MARKUP CSV ON;
SET VERIFY OFF;
SPOOL "/opt/oracle/oradata/Custom~1/orders_between_dates.txt"
SELECT * FROM orders_detail WHERE order_date BETWEEN '&1' AND '&2';
SPOOL OFF;
EXIT;
The command to run this script for a rolling seven day window would be something like...
> sqlplus ot/Orcl1234#xepdb1 #"/opt/oracle/oradata/Custom Scripts/orders_between_dates.sql" $(date +%d-%b-%Y -d '-7 days') $(date +%d-%b-%Y)

How to create a "one-liner" for oracle that includes "set" commands as well as sql statements

I want to execute a dynamic sql containing some set commands. Is it possible to do so without embedding newlines?
set heading off ; set lines 1000 ; select * from my_table;
Note the above does not work due to the semicolons between the set commands:
SP2-0158: unknown SET option ";"'
Update The whole point of this question is to do it on one line.
The best I have found for my own purposes is to put my standard SET commands in a file called sql_settings.txt in a directory with an environment variable holding its path and another variable for the connect string:
sqlsets=/directory/where/sql_settings/stored/sql_settings.txt
db_conn=<ConnectStr>
& then execute a one-liner as such with a shell here-string:
sqlplus -s $db_conn #$sqlsets <<< "select * from my_table;" | less
(The "less" pipe will prevent from cluttering your shell session)
You could also get fancy and create a shell function to minimize typing to the SQL query:
function mydb { sqlplus -s $db_conn #$sqlsets <<< "$#;" ; }
Then call as such:
mydb 'select * from my_table;'
set command is a directive for sqlplus and is not related to sql and you can do it this way
set heading off lines 1000
select * from my_table;
After extensive research, I have concluded this is not possible to perform with oracle.

Parameterizing table name in sqlplus input file

I am trying to export some data using sqlplus and the Oracle spool functionality. The problem is that the SQL input file where I am defining my export is not letting me parameterize the table name from which I am exporting data -- it wants a literal :(
Calling sqlplus in a shell script:
sqlplus $USER/$PASSWD#$ORADB<<!
#export.sql $OUT_FILE $SOME_VAR $ENV
exit
!
export.sql:
set heading off
set head off
set term off
set tab off
set embedded on
set feedback off
set pagesize 0
set linesize 800
set trimspool on
set verify off
spool &1
SELECT '&2|' || some_col
FROM &3_TABLE
/
spool off
When $ENV is set to 'dev', I get
Enter value for 3_TABLE
whereas I want it to use dev_TABLE. When I unparameterize the table names in the sql file, the output runs fine. Also note that there is param &2, which is $SOME_VAR from the shell and it gets displayed evaluated fine. The only problem is in the FROM statement.
Is there any way to tell the sql input file to replace the parameterized table names before running SQL?
Thanks
The problem is that SQL*Plus is treating the whole string after the &, up to the next whitespace or simlar, as the substitution variable name. Clearly that isn't what you want here.
Fortunately they've thought of this, and you can denote the end of the variable name with a .:
FROM &3._TABLE
(At least, that works for named variables, and I'm almost sure it will for positional ones... if not then you'd need to define a new variable set to &3 as a workaround).
It is in the documentation, but blink and you'll miss it:
If you wish to append characters immediately after a substitution
variable, use a period to separate the variable from the character.
There's a related effect that you may want to bear in mind for the future. If the next character after the substitution variable is a . anyway - between the schema and table, or between table and column, for example - then that will be interpreted as the substitution terminator. Say you were passing the schema separately as &4, with value 'scott'; this:
FROM &4.&3._TABLE
looks reasonable but would be substituted as scottdev_TABLE, which won't be recognised. So in that instance you need to have an extra one:
FROM &4..&3._TABLE
which would be substituted as scott.dev_TABLE.

Resources