How to populate variable in pl sql on declaration in store procedure with sql statement return - sql

So I have a variable on the declaration on the store procedure. It must have a default value that is populated on the return of a sql statement. The thing is that that variable is used in the declaration of the query of a cursor, thats why it needs to be populated on the declaration. How am i supposed to do this?
create or replace
PROCEDURE PROCESAR AS
ultimaejecucion date := select fecha from table where rownum<=1;
--I know I have to use the word INTO but throws me error when i compile.
cursor cursor_licencias is
select lic.campo1
from lic lic
where lic.licfhing >= ultimaejecucion
BEGIN
open cursor
.
.
.
END PROCESAR;

Your problem is quite unclear. If your cursor always depends on values from another table, you should include this table to query, as Multisync advised. If your cursor also has to depend on different rows of that table, you can use cursor parameters to choose that row:
create or replace
PROCEDURE PROCESAR AS
cursor cursor_licencias (cursor_parameter number default 1234) is
select lic.campo1
from lic lic
where lic.licfhing >= (select fecha from table where column = cursor_parameter);
BEGIN
open cursor cursor_licencias; -- using with default value
open cursor cursor_licencias (5678); -- using with value '5678'
END PROCESAR;
Example in oracle documentation.

You may move it into the cursor declaration:
create or replace
PROCEDURE PROCESAR AS
cursor cursor_licencias is
select lic.campo1
from lic lic
where lic.licfhing >= (select fecha from table where rownum<=1);
BEGIN
open cursor
.
.
.
END PROCESAR;
if you need this field somewhere else you can assign the value to the ultimaejecucion right after BEGIN

I would do something like:
declare
l_date date;
-- the value of l_date does not matter at this point
cursor sel_cur is
select 'It works' as val
from dual
where sysdate > l_date;
begin
-- populate l_date using query
select sysdate - 1
into l_date
from dual;
-- open cursor (implicitly).
-- here the value of l_date is used in the execution of the query
for rec in sel_cur
loop
dbms_output.put_line(rec.val);
end loop;
end;

Related

Oracle variable from select statement is empty value

In Oracle SQL statement I need to assign variable value from Select Statement. I am doing it according to line documentation but the variable value is empty.
In SQL server the following is what I need to do.
DECLARE #variable INT;
SELECT #variable= mycolumn from myTable;
In Oracle here is the output and query that I am having problem with. I am using Toad client.
My goal is to use the variable value as part of a query.
Here is a simple example intended use.
SELECT * FROM mytable WHERE DateField >= :varCurrMoDateBeg
DECLARE
varCurrMoDateBeg DATE;
varCurrMoDateEnd DATE;
BEGIN
SELECT MONTH_BEG_DATE INTO varCurrMoDateBeg FROM
(
SELECT
CALENDAR.MONTH_BEG_DATE MONTH_BEG_DATE
FROM
CALENDAR
WHERE
CALENDAR.CAL_TYPE='M'
AND (sysdate) BETWEEN CALENDAR.MONTH_BEG_DATE AND CALENDAR.MONTH_END_DATE
) ;
--DBMS_OUTPUT.PUT_LINE(varCurrMoDateBeg);
SELECT MONTH_END_DATE INTO varCurrMoDateEnd FROM
(
SELECT
CALENDAR.MONTH_END_DATE MONTH_END_DATE
FROM
CALENDAR
WHERE
CALENDAR.CAL_TYPE='M'
AND (sysdate) BETWEEN CALENDAR.MONTH_BEG_DATE AND CALENDAR.MONTH_END_DATE
);
--DBMS_OUTPUT.PUT_LINE(varCurrMoDateEnd);
END;
SELECT :varCurrMoDateBeg, :varCurrMoDateEnd from dual;
Online sources:
SELECT INTO Statement
https://docs.oracle.com/cd/B14117_01/appdev.101/b10807/13_elems045.htm
plsql - Declaring a variable and setting its value from a SELECT query in Oracle - Stack Overflow
Declaring a variable and setting its value from a SELECT query in Oracle
PL/SQL SELECT INTO Statement By Practice Examples
https://www.oracletutorial.com/plsql-tutorial/plsql-select-into/
Oracle Tutorials - Assign Query Results to Variables
http://dba.fyicenter.com/faq/oracle/PL-SQL-Assign-Query-Results-to-Variables.html
Using Toad, a small example
declare
v_var date;
v_bind date :=to_date('01.01.2020','DD.MM.YYYY');
v_stm varchar2(4000);
v_counter pls_integer;
begin
select sysdate into v_var from dual ;
dbms_output.put_line(v_var);
execute immediate ' select sysdate from dual ' into v_var ;
dbms_output.put_line(v_var);
-- with bind
v_stm := ' select count(*) from dba_objects where created > :1 ' ;
execute immediate v_stm into v_counter using v_bind;
dbms_output.put_line(v_counter);
end;
/
When I ran this code
As you can see, it is a very easy piece of code that shows how to use bind variables in PL/SQL.
You could create a function for each of the dates you want to use outside of your current PL/SQL block. Here is a rough example to demonstrate how that could be made to work.
CREATE OR REPLACE FUNCTION varCurrMoDateBeg
RETURN DATE
AS
dt_Work DATE;
BEGIN
-- Replace this with your query
SELECT SYSDATE INTO dt_Work FROM dual;
RETURN dt_Work;
END varCurrMoDateBeg;
/
SELECT varCurrMoDateBeg FROM dual;

Declaring cursor in a PL/SQL stored procedure

printf('local_time_greeting');
Having some trouble getting a stored procedure to run with SQL Developer. Below is an example patterned exactly like the first few lines, with variable names changed for security reasons.
CREATE OR REPLACE PROCEDURE redacted ( an_in_variable IN VARCHAR ) AS
these VARCHAR;
variables VARCHAR;
don_apostrophe_t INT;
matter INT;
BEGIN
DECLARE cursor_giving_me_trouble CURSOR FOR
SELECT something FROM db.table WHERE condition_1 = condition_2;
...
In the editor the SELECT word is red-wavy-lined, and when I try to run the code the output returns
PLS-00103: Encountered symbol "FOR" when expecting one of the following := . ( # % ; not null range default character
Any ideas?
You need to use IS rather than FOR, but you have the terms of the definition in the wrong order as well:
DECLARE
CURSOR cursor_giving_me_trouble IS
SELECT something FROM db.table WHERE condition_1 = condition_2;
db<>fiddle which still errors because of the illegal object names in your obfuscated code, but not from the syntax; and a more complete example.
It's also possible you're trying to use the construct:
FOR cursor_giving_me_trouble IN (
SELECT something FROM db.table WHERE condition_1 = condition_2
) LOOP
...
rather than a sub-block (a new declare, followed by begin/end) with references only to cursor within that. db<>fiddle.
To get you started:
create or replace procedure redacted
( an_in_variable in varchar2 )
as
these varchar2(123);
variables varchar2(456);
don_apostrophe_t integer;
matter integer;
cursor cursor_giving_me_trouble is
select 'Welcome to PL/SQL' as whatever from dual where 1=1;
begin
for r in cursor_giving_me_trouble loop
dbms_output.put_line(r.whatever);
end loop;
end;
However, you often don't need a separate cursor definition as there is this compact syntax:
create or replace procedure redacted
( an_in_variable in varchar2 )
as
these varchar2(123);
variables varchar2(456);
don_apostrophe_t integer;
matter integer;
begin
for r in (
select 'Welcome to PL/SQL' as whatever from dual where 1=1
)
loop
dbms_output.put_line(r.whatever);
end loop;
end;

Getting error when trying to return the ORACLE cursor output into a variable

I have declared a SELECT query into a cursor which takes 1 argument - the output of which is 1 row and 1 column containing an integer value. I am attempting to open this cursor to store the result into a variable and later print it.
But it is throwing an error: PLS-00306: wrong number or types of arguments in call to 'c1'
I am not sure what I am doing wrong, I have tried declaring return types/ arguments too, but nothing works. Please help.
Here's what I am working with:
DECLARE
dept_no int ;
cursor c1(Var1 date)
IS
SELECT dept_no
from Employees
where academic_period = 202050
and trunc(r_date) = to_date(:Var1, 'yyyy-mm-dd');
BEGIN
dbms_output.put_line('Department Number: ');
OPEN c1;
FETCH c1 INTO dept_no;
CLOSE c1;
END;
You need to open the cursor like this :
OPEN c1(value);
Here is one example how your code "should" look like:
declare
cursor c1(Var1 date)
IS
SELECT dept_no
from Employees
where academic_period = 202050
and trunc("date") = Var1; -- I have removed ":" from the variable call
-- I have also removed the format Check if you actually need it
v_dept_no int ;
BEGIN
dbms_output.put_line('Department Number: ');
OPEN c1(to_date('01-02-2020','dd-mm-yyyy')); --I have formatred the value I am sending
FETCH c1 INTO v_dept_no;
CLOSE c1;
dbms_output.put_line(v_dept_no); -- I have shown you the value reutrned just for show
END;
/
Here is a demo
Your cursor declaration requires a date input parameter:
cursor c1(Var1 date)
IS
 ...
But then you call it without a date:
OPEN c1;
Fix one, or the other!

Error in Oracle (PLS-00103: Encountered the symbol "="...) trying to select into a variable for use in a cursor

I'm creating a procedure. I'm selecting a max date from a table into a var, and then intending to use that var in sql for a cursor. It looks like:
l_max_update_date DATE;
--Param var
l_max_update_date := NULL;
SELECT max(pivlog.last_update_date) as maxdate into l_max_update_date
FROM piv_verification_log pivlog;
...and then...
--No data in log table? Create a max_update_date
IF l_max_update_date IS NULL
THEN
l_max_update_date := TO_TIMESTAMP('2014/SEP/1 00:00:00', 'YYYY/MON/DD HH24:MI:SS');
END IF;
Finally...
--Get affected employees (those who have certified since the max(last_update_date) listed in the log table)
CURSOR affected_employees_cursor
IS
SELECT [columns]
FROM [tables]
WHERE LAST_UPDATE_DATE > l_max_update_date;
But, whenever I compile, I get this error message:
[Error] PLS-00103 (47: 22): PLS-00103: Encountered the symbol "=" when expecting one of the following:
constant exception
table long double ref
char time timestamp
which points at this line:
l_max_update_date := NULL;
I appreciate your insight. I'm thinking it has to do with the order or location in the procedure where I'm defining the var and cursor(?).
Thank you.
You can't have executable code before the first BEGIN. It would help if you'd post all the code for your procedure, but given what can be seen above it looks to me like your procedure should be something like:
CREATE OR REPLACE PROCEDURE SOME_PROC AS
l_max_update_date DATE := NULL; -- not really needed - variables are
-- initialized to NULL if no other
-- initial value is given.
CURSOR affected_employees_cursor IS
SELECT [columns]
FROM [tables]
WHERE LAST_UPDATE_DATE > l_max_update_date;
rowAffected_employee affected_employees_cursor%ROWTYPE;
BEGIN
BEGIN
SELECT max(pivlog.last_update_date) as maxdate
into l_max_update_date
FROM piv_verification_log pivlog;
EXCEPTION
WHEN NO_DATA_FOUND THEN
l_max_update_date := NULL;
END;
--No data in log table? Create a max_update_date
IF l_max_update_date IS NULL THEN
l_max_update_date := TO_DATE('2014/SEP/1 00:00:00', 'YYYY/MON/DD HH24:MI:SS');
END IF;
OPEN affected_employees_cursor;
LOOP
FETCH affected_employees_cursor
INTO rowAffected_employee;
EXIT WHEN affected_employees_cursor%NOTFOUND;
-- do something useful with the data fetched from the cursor
END LOOP;
CLOSE affected_employees_cursor;
END SOME_PROC;
Share and enjoy.
Further to Bob's answer, the cursor will use whatever value l_max_update_date has at the point the cursor is opened, so it doesn't have to be set before the cursor is declared.
If you'd prefer that to be more obvious in your code then you could also pass the date to the cursor as a parameter:
CURSOR affected_employees_cursor (p_last_update_date DATE) IS
SELECT [columns]
FROM [tables]
WHERE LAST_UPDATE_DATE > p_max_update_date;
and then call it with:
OPEN affected_employees_cursor (l_max_update_date);
Or you could combine the lookup-up into the cursor definition, as long as you only open it once, and skip the separate look-up and check:
CREATE OR REPLACE PROCEDURE SOME_PROC AS
CURSOR affected_employees_cursor IS
SELECT [columns]
FROM [tables]
WHERE LAST_UPDATE_DATE > (
SELECT COALESCE(MAX(pivlog.last_update_date), DATE '2014-09-01')
FROM piv_verification_log pivlog
);
rowAffected_employee affected_employees_cursor%ROWTYPE;
BEGIN
OPEN affected_employees_cursor;
LOOP
FETCH affected_employees_cursor
INTO rowAffected_employee;
EXIT WHEN affected_employees_cursor%NOTFOUND;
-- do something useful with the data fetched from the cursor
END LOOP;
CLOSE affected_employees_cursor;
END SOME_PROC;
/
Or even simpler use an implicit cursor loop:
CREATE OR REPLACE PROCEDURE SOME_PROC AS
BEGIN
FOR rowAffected_employee In (
SELECT [columns]
FROM [tables]
WHERE LAST_UPDATE_DATE > (
SELECT COALESCE(MAX(pivlog.last_update_date), DATE '2014-09-01')
FROM piv_verification_log pivlog
)
)
LOOP
-- do something useful with the data fetched from the cursor
END LOOP;
END SOME_PROC;
/
Of course, depending on what you're doing with the data fetched form the cursor, this might be something that doesn't need PL/SQL at all and could be done in plain SQL.

Oracle: IN function within an IF block

I have a cursor c2, with one column 'note', containing numbers.
I want to check, whether the column contains 5 and change my local variable if so.
this:
CREATE OR REPLACE PROCEDURE proc
IS
result varchar(50);
cursor c2 is
SELECT note
FROM student;
BEGIN
IF c2.note IN(5) THEN
result := 'contains 5';
DBMS_OUTPUT.PUT_LINE(result);
END;
/
doesnt work.
please help!
In your code, you're declaring a cursor but you are never opening it and never fetching data from it. You'd need, presumably, some sort of loop to iterate through the rows that the cursor returned. You'll either need to explicitly or implicitly declare a record into which each particular row is fetched. One option to do that is something like
CREATE OR REPLACE PROCEDURE proc
IS
result varchar(50);
cursor c2 is
SELECT note
FROM student;
BEGIN
FOR rec IN c2
LOOP
IF rec.note IN(5) THEN
result := 'contains 5';
DBMS_OUTPUT.PUT_LINE(result);
END IF;
END LOOP;
END;
/
Note that you also have to have an END IF that corresponds to your IF statement. Naming a cursor c2 is also generally a bad idea-- your variables really ought to be named meaningfully.
You have too loop over the records/rows returned in the cursor; you can't refer to the cursor itself like that:
CREATE OR REPLACE PROCEDURE proc
IS
result varchar(50);
cursor c2 is
SELECT note
FROM student;
BEGIN
FOR r2 IN c2 LOOP
IF r2.note = 5 THEN -- IN would also work but doesn't add anything
result := 'contains 5';
END IF;
END LOOP;
DBMS_OUTPUT.PUT_LINE(result);
END;
/
But if you're just testing for the existence of any record with value 5 then you don't need a cursor:
CREATE OR REPLACE PROCEDURE proc
IS
result varchar(50);
BEGIN
SELECT max('contains 5')
INTO result
FROM student
WHERE note = 5;
DBMS_OUTPUT.PUT_LINE(result);
END;
/
If there are any rows with five you'll get the 'contains 5' string; if not you'll get null. The max() stops an exception being thrown if there are either zero or more than one matching records in the table.
You are missing an END IF and need to LOOP over the cursor. The procedure name is included in the final END.
But using IN should work. Like this:
CREATE OR REPLACE PROCEDURE proc
IS
result varchar(50);
cursor c2 is
SELECT note
FROM student;
BEGIN
FOR rec in c2
LOOP
IF rec.note IN (5) THEN
result := 'contains 5';
END IF;
END LOOP;
DBMS_OUTPUT.PUT_LINE(result);
END proc;
/