I have ksh script which is calling a SQL script called report.sql.
$ORACLE_HOME/bin/sqlplus swb/swb4gdeprod#gdeprod #$reportHome/report.sql
Currently this SQL script is fetching data for sysdate from the database.
I want to pass a date as input to the SQL script so that it picks data corresponding to that date instead of sysdate.
How can I pass a date from ksh to SQL*Plus?
With substitution variables; start is equivalent to # here.
You haven't shown the SQL your report contains, but assuming at some point you have something like:
where some_col > trunc(sysdate)
you would change that to:
where some_col > to_date('&1', 'YYYY-MM-DD')
and then pass a date string in the same format on the command line:
$ORACLE_HOME/bin/sqlplus swb/swb4gdeprod#gdeprod #$reportHome/report.sql 2016-07-27
The value you pass in, e.g. 2016-07-27, is the first positional parameter so it can be referenced as a substitution variable using &1. As it's a string that has to be enclosed in single quotes when you reference it in SQL. And because it's a string you have to convert it to a date. The format of the string you pass in has to match the format you specify with the to_date() function.
Also be wary of passing in month names as you may hit language issues at some point, and ideally you'd use a format that is unambiguous. I've used the ISO format YYYY-MM-DD, and if you stick with that you could also use a date literal as the substitution will be done by SQL*Plus before it is interpreted by the SQL engine:
where some_col > date '&1'
Related
I have got a piece of software which has in-built code processor and support the shell scripting.I have multiple SQL strings in a file which will be processed through the software one-by-one and values of certain sub-string constants will be overridden by that software without changing the original file which contains the original SQLs.you can pass the replacement parameters at runtime to that software.
Below is the example sed for one of the SQLs:
echo " select * from TABLE where DATE(TSP_DATE) between (CURRENT DATE -1 DAY) AND (CURRENT DATE)" | sed -e 's/CURRENT DATE - 1 DAY/'08/30/2018'/; s CURRENT DATE/'08/31/2018'/
I want to replace sub-strings
CURRENT DATE - 1 DAY
with '08/30/2018' and
CURRENT DATE
with '08/31/2018' using one command. Date Strings include the quotes.
When I ran the above script,I got below error :
sed: -e expression #1,char 29: unknown option to 's'
Regards,
Ankit
Not sure, if you want to implement a solution, that's more complicated than necessary.
Whatever DBMS you're using, I'm pretty sure it has a function for the current date. So you don't have to do this in your shell script.
For example, when you use MySQL, you can simply use this query:
select * from TABLE where DATE(TSP_DATE) between CURDATE() - INTERVAL 1 DAY AND CURDATE();
When you want to do it with sed anyway, you can do it like this:
echo "select * from TABLE where DATE(TSP_DATE) between (CURRENT DATE -1 DAY) AND (CURRENT DATE)" | sed "s#CURRENT DATE -1 DAY#'08/30/2018'#;s#CURRENT DATE#'08/31/2018'#"
As delimiter you can choose whatever you want. When you choose something other than / you don't have to escape it all the time, when you use it in your replacement string.
I'm using this code to write the results of a Hive query to the specified file:
INSERT OVERWRITE DIRECTORY '/user/test.user/test.csv'
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' ESCAPED BY '"' STORED AS TEXTFILE
SELECT
...
I don't want the filename to be test.csv however but the unix timestamp, that is 1517213651.csv or something like that.
I understand I can't use the concat function to manipulate the filename, but that is as far as I got.
How do I get the timestamp of the moment of query execution to be the filename of my output?
EDIT: We're using Cloudera.
Another option is to put the Hive insert inside of a Shell Script. Define a Date variable in the script and then use the Date Variable to define the output file.
TIMESTAMP_VAR=date +"%Y-%m-%d-%H-%M-%S"
FILENAME_VAR=/user/test/${TIMESTAMP_VAR}.csv
You can manipulate the timestamp layout in numerous ways.
you have to add TalendDate.getDate("CCYYMMDD") in file path.
"/File1/Output_File_" + TalendDate.getDate("CCYYMMDD") + ".csv"
I have a shell script that calls an Oracle Stored Procedure. The SP has two parameters - the first is of type VARCHAR2 and the second is of type DATE
CREATE OR REPLACE PROCEDURE MY_SCHEMA.MY_SP_NAME(firstParameter IN VARCHAR2, dateParameter IN DATE)
IS
BEGIN
DBMS_OUTPUT.PUT_LINE('Successfully called Procedure');
END;
/
In my shell script, I'm trying to execute the procedure using the following command:
echo "EXECUTE MY_SCHEMA.MY_SP_NAME('TEST', '20170909') " | $ORACLE_HOME/bin/sqlplus $ORAUSER/$ORAPASS
The problem is that when the script runs I get the following error: ORA-01861: literal does not match format string. My guess is that there is an issue with the '20170809' value that I'm passing to the date parameter but I'm unsure how to resolve this. Any help is appreciated.
(PS: The ORACLE_HOME/USER/PASS environment variables are all set correctly and I can successfully run SQLPLUS from the script so there are no problems connecting to the Oracle database)
You can try to use the to_date function:
Execute my_schema.my_sp_name(‘test’,to_date(‘20170909’, ‘yyyymmdd’))
Or use ISO date format in your date parameter.
the script:
accept ztablename
select count(*) from &ztablename||_tables
/
It return ORA-00933 error.
I know execute immediate(sql) method, can not use the method?
Thanks.
You don't need to use the concatenation character, you just need the substitution variable and your fixed string. But you need to mark the end of the substitution variable name with a period:
accept ztablename
select count(*) from &ztablename._tables
/
Without the period, it would prompt for a variable using the too-long name ztablename_tables.
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.