IF statement in Oracle? [duplicate] - oracle

This question already has answers here:
if (select count(column) from table) > 0 then
(3 answers)
Closed 7 months ago.
I have a table that has a column of years as values.
How would I construct an If statement within a stored procedure to check if a record exists that starts with the current YYYY? If there is no record, I will be dropping a sequence.
if (record exists LIKE SYSDATE(YYYY))
Continue
else
DROP MY_SEQ

Here's one option:
declare
l_cnt number;
begin
select count(*)
into l_cnt
from your_table
where extract (year from date_column) = extract (year from sysdate)
and rownum = 1;
if l_cnt > 0 then
-- do something
else
execute immediate 'drop sequence my_seq';
end if;
end;

Related

While loop PL/SQL read a string backwards [duplicate]

This question already has answers here:
How to reverse a string in Oracle (11g) SQL without using REVERSE() function
(5 answers)
A procedure to Reverse a String in PL/SQL
(7 answers)
Closed 10 months ago.
i need help with this question, Using PL/SQL how can I read a string backwards using the while loop?
I know that with the for loop there is a method called reverse but I don't know how I can do it with the while loop. If you can help me I appreciate it
Here's one option:
SQL> set serveroutput on
SQL>
SQL> declare
2 l_str varchar2(20) := 'Littlefoot';
3 i number;
4 retval varchar2(20);
5 begin
6 i := length(l_str);
7 while i <> 0 loop
8 retval := retval || substr(l_str, i, 1);
9 i := i - 1;
10 end loop;
11 dbms_output.put_line(retval);
12 end;
13 /
toofelttiL
PL/SQL procedure successfully completed.
SQL>
If it doesn't have to be PL/SQL, hierarchical query along with listagg might be another way to do it:
SQL> var l_str varchar2(20)
SQL> exec :l_str := 'Littlefoot';
PL/SQL procedure successfully completed.
SQL> select listagg(substr(:l_str, length(:l_str) - level + 1, 1), '') within group (order by level) result
2 from dual
3 connect by level <= length(:l_str);
RESULT
--------------------------------------------------------------------------------
toofelttiL
SQL>

oracle loop over date

I am having difficulties setting up a loop in Oracle. I have a table where values are stored for several days. Now I want to get the average of these values for each day.
I was attempting to set up a loop like this:
DECLARE
BEGIN
For iDay in 01.03.20, 02.03.20, 03.03.20
LOOP
SELECT
avg(values)
FROM
table
WHERE
date = 'iDay'
END LOOP;
END
You can simply get the average value using the following query:
SELECT DATE,
AVG (values)
FROM table
WHERE DATE BETWEEN DATE '2020-03-01' AND DATE '2020-03-03';
Or if you want to use the loop then use the query in FOR loop IN clause as follows:
SQL> DECLARE
2 BEGIN
3 FOR DATAS IN (
4 SELECT DATE '2020-03-01' + LEVEL - 1 DT
5 FROM DUAL CONNECT BY
6 LEVEL <= DATE '2020-03-03' - DATE '2020-03-01' + 1
7 ) LOOP
8 DBMS_OUTPUT.PUT_LINE(DATAS.DT);
9 -- YOUR_CODE_HERE
10 END LOOP;
11 END;
12 /
01-MAR-20
02-MAR-20
03-MAR-20
PL/SQL procedure successfully completed.
SQL>
One option would be using Dynamic Query within PL/SQL :
SQL> SET SERVEROUTPUT ON;
SQL> DECLARE
v_result NUMBER;
BEGIN
For iDay in 0..2
LOOP
EXECUTE IMMEDIATE 'SELECT AVG(values) FROM mytable WHERE mydate = :i_Day '
INTO v_result;
USING iDay + date'2020-03-01';
DBMS_OUTPUT.PUT_LINE( v_result );
END LOOP;
END;
/
Why not simply
SELECT "date", avg(values)
FROM "table"
WHERE "date" between DATE '2020-03-01' and DATE '2020-03-03'
GROUP by "date";
Note, date and table are reserved words, most likely the query will without quotes.

Basic pl/sql variable [duplicate]

This question already has answers here:
Using variables in PLSQL SELECT statement
(2 answers)
Closed 5 years ago.
What's the basic syntax for a pl/sql variable? I'm trying to add a variable in my select statement.
My query:
DECLARE
V_id number := 251 ;
BEGIN
SELECT *
FROM client
where 1=1
and clientid = V_id;
END;
Error:
PLS-00428 an INTO clause is expected in this Select statement
This example may work for you. Please check it out
DECLARE
V_Num NUMBER(15,0) := 150;
V_Col VARCHAR2(50);
BEGIN
SELECT col1 into V_col FROM tableA where id = V_num;
END ;

Using SELECT within SELECT statement in ORACLE

I have a table name SAMPLETABLE this has the tablenames of the tables I require in column TABLENAMES. Lets say the tablenames are TABLEA, TABLEB and TABLEC.
On query
SELECT TABLENAMES FROM SAMPLETABLE WHERE ROWNUM = 1
I get the output the output of TABLENAMES column with TABLEA value.
My problem is, now I want to use this selected value in a select statement. That is,
SELECT * FROM (SELECT TABLENAMES FROM SAMPLETABLE WHERE ROWNUM = 1)
My idea is that it'd return the contents of TABLEA because when the nested SELECT returns TABLEA, the outer SELECT should capture and display it.
On the contrary, I get the output only of the inner statement, that is,
SELECT TABLENAMES FROM SAMPLETABLE WHERE ROWNUM = 1
and
SELECT * FROM (SELECT TABLENAMES FROM SAMPLETABLE WHERE ROWNUM = 1)
return the same output.
I want the first SELECT statement to fetch the returned value of second SELECT and display the table. They above query doesn't do that, so how do I do it? And what is wrong with my idea?
I am on Oracle 10g, any help appreciated.
As table name is not known at compile time you need to use dynamic SQL(execute immediate, native dynamic SQL, for instance) to be able to select from a table, name of which is stored as a string literal - you cannot accomplish it with static SQL
Here is an example:
-- table which contains names of other tables
-- in the table_name column
SQL> create table Table_Names as
2 select 'employees' as table_name
3 from dual
4 ;
Table created
SQL> set serveroutput on;
-- example of an anonymous PL/SQL block
-- where native dynamic SQL (execute immediate statement)
-- is used to execute a dynamically formed select statement
SQL> declare
2 type T_record is record( -- example of record for fetched data
3 f_name varchar2(123),
4 l_name varchar2(123)
5 );
6
7 l_table_name varchar2(123); -- variable that will contain table name
8 l_select varchar2(201);
9 l_record T_Record; -- record we are going to fetch data into
10 begin
11 select table_name
12 into l_table_name -- querying a name of a table
13 from table_names -- and storing it in the l_table_name variable
14 where rownum = 1;
15
16 l_select := 'select first_name, last_name from ' ||
17 dbms_assert.simple_sql_name(l_table_name) ||
18 ' where rownum = 1'; -- forming a query
19
20 execute immediate l_select -- executing the query
21 into l_record;
22 -- simple output of data just for the sake of demonstration
23 dbms_output.put_line('First_name: ' || l_record.f_name || chr(10) ||
24 'Last name: ' || l_record.l_name);
25 exception
26 when no_data_found
27 then dbms_output.put_line('Nothing is found');
28 end;
29 /
First_name: Steven
Last name: King
PL/SQL procedure successfully completed
As a second option you could use weakly typed cursors - refcursors to execute a dynamically formed select statement:
SQL> variable refcur refcursor;
SQL> declare
2 l_table_name varchar2(123);
3 l_select varchar2(201);
4 begin
5 select table_name
6 into l_table_name
7 from table_names
8 where rownum = 1;
9
10 l_select := 'select first_name, last_name from ' ||
11 dbms_assert.simple_sql_name(l_table_name) ||
12 ' where rownum = 1';
13
14 open :refcur
15 for l_select;
16
17 exception
18 when no_data_found
19 then dbms_output.put_line('Nothing is found');
20 end;
21 /
PL/SQL procedure successfully completed.
SQL> print refcur;
FIRST_NAME LAST_NAME
-------------------- -------------------------
Steven King
SQL> spool off;
Find out more about cursors and cursor variables
You can do this with help of dynamic sql. Since the table name is obtained during run time you have to frame the query dynamically and run it.
Declare
Tab_Name Varchar2(30);
Begin
SELECT TABLENAMES into Tab_Name FROM SAMPLETABLE WHERE ROWNUM = 1;
Execute Immediate 'Select * into (Collection Variable) from ' || Tab_Name;
End
/
I just gave it as example. You declare a variable to get the data out or something else as you need. But when you try to use execute immediate with input parameter read about sql injection and then write your code.

if (select count(column) from table) > 0 then

I need to check a condition. i.e:
if (condition)> 0 then
update table
else do not update
end if
Do I need to store the result into a variable using select into?
e.g:
declare valucount integer
begin
select count(column) into valuecount from table
end
if valuecount > o then
update table
else do
not update
You cannot directly use a SQL statement in a PL/SQL expression:
SQL> begin
2 if (select count(*) from dual) >= 1 then
3 null;
4 end if;
5 end;
6 /
if (select count(*) from dual) >= 1 then
*
ERROR at line 2:
ORA-06550: line 2, column 6:
PLS-00103: Encountered the symbol "SELECT" when expecting one of the following:
...
...
You must use a variable instead:
SQL> set serveroutput on
SQL>
SQL> declare
2 v_count number;
3 begin
4 select count(*) into v_count from dual;
5
6 if v_count >= 1 then
7 dbms_output.put_line('Pass');
8 end if;
9 end;
10 /
Pass
PL/SQL procedure successfully completed.
Of course, you may be able to do the whole thing in SQL:
update my_table
set x = y
where (select count(*) from other_table) >= 1;
It's difficult to prove that something is not possible. Other than the simple test case above, you can look at the syntax diagram for the IF statement; you won't see a SELECT statement in any of the branches.
Edit:
The oracle tag was not on the question when this answer was offered, and apparently it doesn't work with oracle, but it does work with at least postgres and mysql
No, just use the value directly:
begin
if (select count(*) from table) > 0 then
update table
end if;
end;
Note there is no need for an "else".
Edited
You can simply do it all within the update statement (ie no if construct):
update table
set ...
where ...
and exists (select 'x' from table where ...)
not so elegant but you dont need to declare any variable:
for k in (select max(1) from table where 1 = 1) loop
update x where column = value;
end loop;

Resources