Oracle variable from select statement is empty value - sql

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;

Related

How can I declare constant in PL SQL without writing procedure in "begin"?

I would like to do something like that:
DECLARE MY_DATE CONSTANT DATE := DATE'2022-07-01';
BEGIN null; end;
SELECT MY_DATE FROM dual
or
DECLARE MY_DATE CONSTANT DATE := DATE'2022-07-01';
BEGIN null; end;
SELECT CASE WHEN sysdate > MY_DATE THEN 1 ELSE 0 END FROM dual
But I am getting error. How can I fix it?
NEW:
From the comment I see you're declaring a constant within a package and your aim is to use it in an SQL statement outside of package.
You need a function to return that constant.
NOTE: I wouldn't recommend to store constants in a package and use it in SQL. I'd prefer to store them in a special table because of overhead you'll get when adding or removing constants. And performance issues are to be expected as well because of context switching while using PLSQL constants in SQL statements.
However, answering your question, here's the example for a package having multiple constants:
CREATE OR REPLACE PACKAGE MYCONSTANTS
IS
MY_DATE CONSTANT DATE := DATE'2022-07-01';
MY_CHAR CONSTANT VARCHAR2(10) := 'ABCD';
function get_my_date return date;
function get_my_char return varchar2;
END;
/
create or replace PACKAGE body MYCONSTANTS IS
function get_my_date return date
is
begin
return my_date;
end;
function get_my_char return varchar2
is
begin
return MY_CHAR;
end;
END;
/
And the you can say:
select MYCONSTANTS.get_my_date from dual;
select MYCONSTANTS.get_my_char from dual;
OLD:
As far as I can see you don't need PL/SQL but just SQL.
The PLSQL is what you would have between "begin" and "end". But in your example, you have just null there.
So, all you need is "define"
def my_date = date '2022-07-01';
begin
null;
end;
/ -- you need this to start execution of an pl/sql block
select &my_date from dual; -- be aware you need to use an "&" before var name
If you're on a recent version you can declare a local function in a CTE:
WITH
FUNCTION MY_DATE RETURN DATE IS
BEGIN
RETURN DATE '2022-07-01';
END;
SELECT MY_DATE FROM dual
Or you can use a normal CTE:
WITH cte (MY_DATE) AS (
SELECT DATE '2022-07-01' FROM DUAL
)
SELECT MY_DATE FROM cte
db<>fiddle

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;

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

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;

SQL Use a Variable as tablename

i would like to set the Tablename as Variable
Why: i go from a oracle db to a mysql db via db link and in the mysql db i have some table-names which includes the date- example: data_20121126
here's my statement :
DECLARE
tbname VARCHAR2 (200);
BEGIN
SELECT ab.teste
INTO tbname
FROM (SELECT '"data_'
|| REPLACE (TO_CHAR (SYSDATE - 1, 'yyyy.mm.dd'),
'.',
'')
|| '"#myDB'
AS teste
FROM DUAL) ab;
SELECT * FROM tbname;
END;
could anybody help me please?
thanks in advance
It's not possible with static SQL (and I doubt that creating a new table for every day in your MySQL database is a sensible design approach).
If you really need to do this, you can
use dynamic SQL (EXECUTE IMMEDIATE / OPEN CURSOR FOR ...)
create a synonym once per day, pointing to the current table, and use that synonym in your query
You can't do this without resorting to dynamic SQL:
DECLARE
tbname VARCHAR2 (200) := '"data_'
|| TO_CHAR (SYSDATE - 1, 'yyyymmdd')
|| '"#myDB';
vMyVariable varchar2(10);
BEGIN
execute immediate "SELECT MyColumn
FROM " || tbname into vMyVariable ;
END;
Of course, this version assumes you'll be returning a single column from a single field into a variable. In all likelihood, you'll really want to return a ref cursor to your calling application.

ORACLE PL/SQL: Dynamic SQL Select using a Collection

Is it possible to create a dynamic SQL statement that pulls from an existing collection?
l_collection := pack.get_items(
i_code => get_items_list.i_code ,
i_name => get_items_list.i_name );
Now, let's say I want to select a COUNT from that collection using dynamic SQL. Is that possible? Furthermore, I want to do a sub select from that collection as well.
If the collection type is declared at the schema level, it can be used in SQL statements, including dynamic ones. You need to explicitly cast it to the proper collection type, or the SQL engine has no idea what type it is.
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM TABLE(CAST(:collection AS collection_type))'
INTO l_count
USING l_collection
;
I'm not sure if there's some other reason you want to use dynamic SQL, or if you're just assuming that it's necessary in this case. It shouldn't be necessary if all you want to do is select the count. This inline SQL should work fine:
SELECT COUNT(*) INTO l_count FROM TABLE(CAST(l_collection AS collection_type));
Of course, if that's all you want you don't need SQL at all, just l_count := l_collection.COUNT.
Edit -- adding fully worked out example
CREATE OR REPLACE TYPE testtype AS OBJECT( x NUMBER, y NUMBER);
/
CREATE OR REPLACE TYPE testtypetab AS TABLE OF testtype;
/
DECLARE
t testtypetab := testtypetab();
l_count integer;
BEGIN
-- Populate the collection with some data
SELECT testtype(LEVEL, LEVEL) BULK COLLECT INTO t FROM dual CONNECT BY LEVEL<21;
-- Show that we can query it using inline SQL
SELECT count(*) INTO l_count FROM TABLE(CAST(t AS testtypetab));
dbms_output.put_line( l_count );
-- Clear the collection
t.DELETE;
-- Show that we can query it using dynamic SQL
EXECUTE IMMEDIATE 'select count(*) from table(cast(:collection as testtypetab))'
into l_count using t;
dbms_output.put_line( l_count );
END;
/