Can i use a variable in oracle sql script? - oracle

I am using a SQL script to spool data and load data into XML
I want to check whether I can use variable in the SQL script which get it value from another SQL query.
Something like this:
var1= select count(1) from emp
spool filename
select * from dept where empcnt=var1
Will it work? Is this the best way or any other way of doing it?

If you are using SQLplus, and you only want SQL ( not PLSQL) you can do something like the following, with bind variables:
spool yourFile
variable var1 number
select count(1) into :var1 from dual;
select * from dual where rownum = :var1;
Another way could be with substitution variables:
spool yourFile
column var1 new_value valueFor_var1
select count(1) as valueFor_var1 from dual;
select * from dual where rownum = &var1;
If you can use a PLSQL block, you can do:
spool yourFile
declare
var1 number;
vDummy varchar2(100);
begin
select count(1) into var1 from dual;
select dummy into vDummy from dual where rownum = var1;
dbms_output.put_line(vDummy);
end;
/

Related

Getting many column list in a variable in Oracle

How to pass many string values in a variable in oracle?
This is what Im trying, but this returns nothing.
SET DEFINE ON;
DEFINE column_name ='"column_1","column_2","column_3","column_4","column_5"';
SELECT * FROM SYS.all_tab_columns WHERE column_name in ('&column_name');
For one value in variable it works fine, but how to pass many string value?
All the examples that I've seen here did not help me
You have:
the wrong quotes in the substitution variable; and
don't need the quotes around the substitution variable in the query if they are present in the replacement text of the substitution variable.
Like this:
SET DEFINE ON;
DEFINE column_name='column_1','column_2','column_3','column_4','column_5'
SELECT * FROM SYS.all_tab_columns WHERE column_name in (&column_name);
The client application (i.e. SQL*Plus or SQL Developer, which are some of the few clients that support this syntax) will effectively do a find-replace on &column_name and replace it with the string assigned in your DEFINE command.
The documentation for substitution variables is here.
Here's one option (if it must be DEFINE):
SQL> define column_name = 'EMPNO,DEPTNO'
SQL> select table_name, column_name from user_tab_columns where column_name in
2 (select regexp_substr('&&column_name', '[^,]+', 1, level) from dual
3 connect by level <= regexp_count('&&column_name', ',') + 1
4 );
TABLE_NAME COLUMN_NAME
------------------------------ ------------------------------
EMP EMPNO
DEPT DEPTNO
EMP DEPTNO
SQL>
Though, why bother? What's wrong with simple
SQL> select table_name, column_name from user_tab_columns where column_name in ('EMPNO', 'DEPTNO');
TABLE_NAME COLUMN_NAME
------------------------------ ------------------------------
DEPT DEPTNO
EMP EMPNO
EMP DEPTNO
SQL>
If you are looking for dynamism to procedure column list to be added to IN clause then something like this can be useful -
Idea is to use LISTAGG.
select listagg('''column'||'_'||level||'''',',') as column_list from dual connect by level<5;
COLUMN_LIST
--------------------------------------------------------------------------------
'column_1','column_2','column_3','column_4'
Use above generated column list in your IN query.
Else, if you are only concerned about all_tab_columns then you are better off specifying column names, as mentioned by #Littlefoot.

Oracle - using bind variable in LIKE clause of dynamic cursor

I am using dynamic cursor for fetching data. Query that is being executed looks similar to:
query := 'SELECT column1, column2
FROM my_table
WHERE column1 LIKE ''%:bv1%''';
And the cursor itself is executed like this:
OPEN my_cursor FOR query USING my_var1;
I also tried to check the query and print it:
... WHERE column1 LIKE '%:bv1%' ...
so apostrophes are escaped, but the cursor fetches no data. Is it even possible to use bind variables in LIKE clause and if yes, what did I do wrong?
This is a subtle one. It's often useful to start with a static statement, get that right, then convert it to dynamic SQL.
In non-dynamic SQL we might do it like this:
SELECT column1, column2
FROM my_table
WHERE column1 LIKE '%' || local_var || '%';
The dynamic equivalent is
query := 'SELECT column1, column2
FROM my_table
WHERE column1 LIKE ''%''||:bv1||''%'' ';
Take the bind variable out of the string:
VARIABLE mycursor REFCURSOR;
VARIABLE bv1 VARCHAR2;
BEGIN
:bv1 := 'X'; -- set the bind variable
END;
/
DECLARE
query VARCHAR2(200) := 'SELECT * FROM DUAL WHERE DUMMY LIKE :value';
BEGIN
OPEN :mycursor FOR query USING '%' || :bv1 || '%';
END;
/
PRINT mycursor;
Output
MYCURSOR
--------
DUMMY
-----
X

Define date variable in Oracle

How to define date variable and assign that variable from the table in oracle?
I tried below
DEFINE EXTRACTION_DATE = SELECT DATA_EXTRACTION_DATE FROM tbl1
SELECT PA.PERSON_ID,A.PERIOD_END_DATE,PA.OPT_OUT_OF_PLAN_DATE,A.TERMINATION_DATE,
CASE WHEN A.PERIOD_END_DATE <= ADD_MONTHS(TRUNC(&EXTRACTION_DATE), -3) THEN 'Y' ELSE 'N' END
FROM
tbl2
it throwing invalid statement error.
its not duplicate of another. Because I need to get variable from the table not by static variable.
I dont fully understand what you are tyring to do but as far as I understand
you can set a variable such a way as follows
1 - ) if you write a procedure,
declare
EXTRACTION_DATE date;
begin
SELECT DATA_EXTRACTION_DATE into EXTRACTION_DATE FROM tbl1;
end;
2 - ) If your data reference to a table, you can user cursor
declare
cursor crs is SELECT * into EXTRACTION_DATE FROM tbl1;
then use crs in for loop
3 - ) You can write upper query in you second query.
SELECT PA.PERSON_ID,A.PERIOD_END_DATE,PA.OPT_OUT_OF_PLAN_DATE,A.TERMINATION_DATE,
CASE WHEN A.PERIOD_END_DATE <= ADD_MONTHS(TRUNC(SELECT DATA_EXTRACTION_DATE FROM tbl1), -3) THEN 'Y' ELSE 'N' END
FROM
tbl2
I'm going to assume that this is required for some sort of script. If so, you can do this using the COLUMN command and its new_value parameter in SQL*Plus:
SQL> column my_val new_value my_val_subst_param
SQL> define my_val_subst_param
Symbol my_val_subst_param is UNDEFINED
SQL> select 'hello!' my_val from dual;
MY_VAL
------
hello!
SQL> select '&my_val_subst_param' some_val from dual;
'HELLO!'
--------
hello!
I highly recommend you read all of this article, and specifically this section.
ETA: Bear in mind that if you use this method, DATEs are output as strings, so you will have to ensure that you do the appropriate conversion in your select statement, eg.:
SQL> column dt new_value dt_val
SQL> select to_char(sysdate, 'dd/mm/yyyy') dt from dual;
DT
----------
29/09/2016
SQL> define dt_val;
DEFINE DT_VAL = "29/09/2016" (CHAR)
SQL> select * from dual where trunc(sysdate) = to_date('&dt_val', 'dd/mm/yyyy');
DUMMY
-----
X
Try something like:-
declare
var1 <dtatatype same as your table column>;
var2 <dtatatype same as your table column>;
var3 <dtatatype same as your table column>;
var4 <dtatatype same as your table column>;
var5 <dtatatype same as your table column>;
var_dt date;
begin
SELECT EXTRACTION_DATE
into var_dt
FROM tbl1;
SELECT PA.PERSON_ID,
A.PERIOD_END_DATE,
PA.OPT_OUT_OF_PLAN_DATE,
A.TERMINATION_DATE,
CASE WHEN A.PERIOD_END_DATE <= ADD_MONTHS(var_dt), -3)
THEN 'Y'
ELSE 'N' END
into
var1,
var2,
.
.
var5
FROM tbl2;
end;

How to use dynamic sql in with clause of oracle plsql

I am using with clause in my function where passing table name as parameter. So want use this table name in the query but giving table doesnot exits.Sample query
with EMP_A as(
select EMPNO, SAL
from EMP
where DEPTNO in (select DEPTNO from P_TABLE_NAME))
select * from EMP;
In your below posted query:
With emp_a as (
select empno,sal
from emp
where deptno in(select deptno from p_table_name)
)
select * from emp;
Firstly, you cannot have dynamic table name in SQL. Object names must be static. You need to (ab)use EXECUTE IMMEDIATE in PL/SQL to make it a dynamic SQL.
Secondly, your CTE and tablename are different. Your CTE is emp_a, while the table you are referring to is emp.
Thirdly, you use the WITH clause, i.e. subquery factoring when you have to use the subquery multiple times. Therefore, the CTE would act as a temporary taboe to hold the subquery resultset.
See the documentation to learn more about EXECUTE IMMEDIATE.
http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/executeimmediate_statement.htm
UPDATE An example
You could use a string variable to assign the dynamic query.
DECLARE
p_table_name VARCHAR2(30);
l_sql VARCHAR2(32767);
l_value. NUMBER;
BEGIN
p_table_name := 'DEPARTMENT';
l_sql := 'WITH clause...' || p_table_name || ' with clause contunied';
EXECUTE IMMEDIATE l_sql INTO l_value;

oracle select from table if values not exists

I need to write oracle query (Just query)
to select values from table, and if not found select from another table.
any help to do this in pl/sql?
SELECT * FROM firstTable
UNION ALL
SELECT * FROM secondTable WHERE (SELECT count(*) FROM FIRST_TABLE ) = 0
You can enclose the SELECT statement within a block and add an exception handler to it.
So, if there are no rows selected from the first table, then you select from the second table. The structure would be something like below:
Begin
select <many columns> into <many variables or row type>
From Table1
where <conditions>;
EXCEPTION
WHEN NO_DATA_FOUND THEN
select <many columns> into <many variables or row type>
From Table2
Where <Conditions>;
End;
References:
Another related SO question
Exception Handlers
Documentation for the SELECT INTO statement
Here is an example of a PL/SQL function that will perform a test, and then execute a secondary query based upon the results of the test. You can adjust it to fit your needs:
set serveroutput on;
declare
row_count number;
column1 varchar(10);
column2 varchar(10);
column3 number;
begin
/*Perform your test*/
select count(target_column) into row_count
from my_table
where condition_column = 'x';
/*Run your secondary query based on the output of the first*/
if row_count > 0 then
select
col_x into column1,
col_y into column2,
col_z into column3
from my_other_table_A;
else
select
col_a into column1,
col_b into column2,
col_c into column3
from my_other_table_B;
end if;
/*Show the results*/
dbms_output.put_line('column1: ' || column1);
dbms_output.put_line('column2: ' || column2);
dbms_output.put_line('column3: ' || column3);
end;
/

Resources