Declare bind variables in SQL*Plus - oracle

I am using SQL*Plus. When I am using the below query, it is giving error
Error report:
ORA-06550: line 4, column 1:
PLS-00428: an INTO clause is expected in this SELECT statement
Query
declare
id varchar2(80) :='test123';
begin
select test_quote,test_id from order_link where id = 'test123';
end;

Not sure why you're using a PL/SQL block for that. You aren't using the id you declare, and it would be better to give it a name different to the column name to avoid confusion.
You can declare a bind variable in SQL*Plus though, and select into that:
var l_test_quote varchar2(80); -- or whatever type/size you need
var l_test_id varchar2(80);
declare
l_id varchar2(80) :='test123';
begin
select test_quote, test_id
into :l_test_quote, :l_test_id
from order_link
where id = l_id;
end;
/
print l_test_quote
print l_test_id
Note the : before the references to the variables defined outside the block, indicating they are bind variables. l_id is declared inside the block so it does not have a preceding :.
In this case you could also define l_id outside the block, and avoid PL/SQL while still using a bind variable for that:
var l_id varchar2(80);
exec :l_id := 'test123';
select test_quote, test_id
from order_link
where id = :l_id;
Because the main query isn't PL/SQL any more (although the exec is; that's just a shorthand for a one-line anonymous block), you don't need to select ... into so you don't need to declare those variables.

try this:
declare
id varchar2(80) :='test123';
v_test_quote order_link.test_quote%type;
v_test_id order_link.test_id%type;
begin
select test_quote,test_id
into v_test_qoute, v_test_id
from order_link
where id = 'test123';
end;

Related

Reusing a variable in an Oracle SQL query

Very simple question, but one I can't seem to find an answer to.
I have a variable calculated at the start of an Oracle SQL script (in TOAD, if that makes a difference), and I hoped to reuse it later in an UPDATE statement.
Variable is declared and then set here:
DECLARE
v_months number;
v_check number;
BEGIN
v_check := '1'
SELECT (total_due/monthly_amount) INTO v_months FROM TABLE1 WHERE ...
and will return a numeric value of, say, 20.
and I want to use that figure here:
IF(v_check = 1)
update TABLE2 set paid = 'YES' where sequence between v_months and 48;
This doesn't seem to be possible as the variable is flagged up as an invalid identifier, but is there a way round this?
DECLARE the variable at the start of the PL/SQL block and then just re-use it in the same PL/SQL block and it works:
DECLARE
v_months PLS_INTEGER;
BEGIN
SELECT (total_due/monthly_amount) INTO v_months FROM TABLE1;
update TABLE2 set paid = 'YES' where sequence between v_months and 48;
END;
/
If you are trying to re-use it between different PL/SQL blocks then it will not work using a PL/SQL variable.
db<>fiddle here
If you want to use a variable in multiple statements then you can use bind variables:
VARIABLE v_months NUMBER
BEGIN
SELECT (total_due/monthly_amount) INTO :v_months FROM TABLE1;
END;
/
update TABLE2 set paid = 'YES' where sequence between :v_months and 48;

Oracle Where with variable

I have problem with my plsql code. It's just part of my whole job.
declare
id number(2):=1; (here is function which returns any value)
check VARCHAR2(100);
begin
select COUNT(*) into check from T_SDSN_LOG Where ANY_ID=id AND CHECK LIKE
'NAME';
dbms_output.put_line(check);
end;
In this case, my select returns 0 althought it should be 2.
If I change the part
Where ANY_ID=id to
Where ANY_ID=2 it works perfectly. Any advices? I need id to be variable as a return value from function.
This uses a locally defined function so it isn't available in the SQL but can be referenced in the PL/SQL.
DECLARE
lnum_id NUMBER := return_id;
lnum_check VARCHAR2(100);
FUNCTION return_id
RETURN NUMBER
IS
BEGIN
RETURN 123456;
END;
BEGIN
lnum_id := return_id;
SELECT COUNT(*)
INTO lnum_check
FROM my_table
WHERE table_id = lnum_id;
DBMS_OUTPUT.put_line(lnum_check);
END;
You will presumably want this functionality in a package in which case you can declare the function in the package header, write the code for the function in the body and then reference it in the SQL itself. So if I declare a function (FNC_RETURN_ID) in a package called PKG_DATA_CHECKS that returns a NUMBER I can do the following;
DECLARE
lnum_id NUMBER;
lnum_check VARCHAR2(100);
BEGIN
SELECT COUNT(*)
INTO lnum_check
FROM my_table
WHERE table_id = (SELECT pkg_data_checks.fnc_return_id FROM dual);
DBMS_OUTPUT.put_line(lnum_check);
END;

What is the simplest way to define a local variable in Oracle?

In the SQL Server, I can define local variables like this.
declare #id number := 1000
select * from tbl_A where id = #id;
select * from tbl_B where id = #id;
It is very convenient.
I tried to do same thing in PL/SQL but it doesn't work.
DECLARE id number;
select 1000 into id from dual;
Do you know how to do something similar? The simplest method is my objective.
If you want to define a local variable in PL/SQL, you need a complete PL/SQL block
DECLARE
id NUMBER;
BEGIN
SELECT 1000
INTO id
FROM dual;
END;
or just
DECLARE
id NUMBER := 1000;
BEGIN
<<do something that uses the local variable>>
END;
If you want to declare a variable in SQL*Plus
SQL> variable id number
SQL> begin
select 1000 into :id from dual;
end;
/
SQL> print id
ID
----------
1000
SQL> SELECT * FROM tbl_a WHERE id = :id
An alternative to DECLARE Block is to use a WITH Clause:
WITH my_params AS (
SELECT 123 AS min_id FROM DUAL
)
SELECT *
FROM some_table
WHERE id > (SELECT min_id FROM my_params)
It is more portable as many vendors support the WITH clause and you can change seamless from parameter to dynamic value. For example:
WITH my_params AS (
SELECT min(id) AS min_id FROM some_id_table
)
SELECT *
FROM some_table
WHERE id > (SELECT min_id FROM my_params)
Solution for Oracle SQL
DEF x = foo
SELECT '&x' FROM dual;
The result will be : foo
NB: The variable will keep the value even after execution. To clear variable run UNDEFINE x.
General syntax to declare variable in PL/SQL is
var_nm datatype [NOT NULL := var_value ];
var_nn is the name of the variable.
datatype is a valid PL/SQL datatype.
NOT NULL is an optional specification on the variable which this variable cannot be assigned null value.
var_value or DEFAULT value is also an optional specification, where you can initialize a variable with some specific value.
Each variable declaration is a separate statement and must be terminated by a semicolon.
We can assign value to variables in one of the following two ways -
direct assignment (Eg. var_nm:= var_value;)
Using select from (Eg. SELECT col_nm INTO var_nm FROM tbl_nm [WHERE clause];)
In you case as Justin Cave has already mentioned it can be
DECLARE
id number;
BEGIN
SELECT 1000 into id from dual;
dbms_output.put_line('id : '|| id );
END;
/
OR
DECLARE
id number := 1000;
BEGIN
dbms_output.put_line('id : '|| id );
END;
/
NOTE: '/' i.e Back slash after END keyword indicates to execute the above PL/SQL Block.
(Just stumbled across this thread.) Beginning with SQL*Plus 12.2, you can declare and assign a value at the same time:
SQL> var id number = 1000
SQL> select * from tbl_A where id = :id;
Oracle calls it input binding.
If you must do it in PL/SQL, the answer was given by others.

Output results of Oracle stored proc from SQL Developer

I'm trying to call an Oracle stored proc using SQL Developer. The proc outputs results using a sys_refcursor. I right click in the proc window which brings up the Run PL/SQL window. When I choose the proc I want it creates all the input params etc for me. Below is the code I'm using to try and loop through the sys_refcursor and output the results, but I'm getting an error on the 'v_rec v_Return%rowtype;' line :
ORA-06550: line 6 column 9:
PLS-00320: the declaration of the type of this expression is incomplete or malformed.
ORA-06550: line 6 column 9:
PL/SQL: Item ignored
vendor code 6550
I found the looping code on a couple of other websites and it seems to be the way to do it but it's not working for me no matter what I try. Another question - on the DBMS_OUTPUT.PUT_LINE('name = ' || v_rec.ADM) am I referencing the v_rec correctly i.e. is v_rec."column_name" the correct way??
I'm not that used to Oracle and have never used SQL plus. Any suggestions appreciated.
DECLARE
P_CAE_SEC_ID_N NUMBER;
P_PAGE_INDEX NUMBER;
P_PAGE_SIZE NUMBER;
v_Return sys_refcursor;
v_rec v_Return%rowtype;
BEGIN
P_CAE_SEC_ID_N := NULL;
P_PAGE_INDEX := 0;
P_PAGE_SIZE := 25;
CAE_FOF_SECURITY_PKG.GET_LIST_FOF_SECURITY(
P_CAE_SEC_ID_N => P_CAE_SEC_ID_N,
P_PAGE_INDEX => P_PAGE_INDEX,
P_PAGE_SIZE => P_PAGE_SIZE,
P_FOF_SEC_REFCUR => v_Return
);
-- Modify the code to output the variable
-- DBMS_OUTPUT.PUT_LINE('P_FOF_SEC_REFCUR = ');
loop
fetch v_Return into v_rec;
exit when v_Return%notfound;
DBMS_OUTPUT.PUT_LINE('name = ' || v_rec.ADM);
end loop;
END;
Your problem is here:
v_Return sys_refcursor;
v_rec v_Return%rowtype;
v_Return is a cursor variable and has no specific structure (list of columns), so v_Return%rowtype is not a valid record structure to declare v_rec. It is even possible for different calls to the procedure to return cursors with different structures.
You know what you are expecting the structure of the returned cursor to be (but Oracle doesn't) so you need to explicitly define the appropriate record structure e.g.
type t_row is record (empno number, ename varchar2(30));
v_rec t_row;
You need a strongly typed ref cursor to be able to define it as a %ROWTYPE.
Example here
#Tony Andrews thanks for this it gave me a better idea where I was going wrong. Still having problems though - here's a shortened version of my proc. It's a bit complex in that it's selecting all fields from a subquery and 2 other values:
open p_fof_sec_refcur for
SELECT *
FROM(
SELECT securities.*, rownum rnum, v_total_count
FROM
(
SELECT
CFS.CAE_SEC_ID,
CFS.FM_SEC_CODE,
...
FROM
CAEDBO.CAE_FOF_SECURITY CFS
INNER JOIN caedbo.CAE_DATA_SET_ELEMENT CDSE_STAT
ON (CDSE_STAT.DATA_SET_ELEMENT_ID = CFS.APPR_STATUS)
...
WHERE APPR_STATUS = NVL(p_appr_status, APPR_STATUS)
...
)securities
)
WHERE rnum between v_pgStart and v_pgEnd;
I explicitly defined the output structure as below to match the return fields from the proc but I'm still getting an error:
v_Return sys_refcursor;
type t_row is record (CAE_SEC_ID NUMBER,FM_SEC_CODE VARCHAR2(7),...rnum number, v_total_count number);
v_rec t_row;
The error I get is
ORA-06504: PL/SQL: Return types of Result Set variables or query do not match
ORA-06512: at line 45
I'm just wondering is the "rownum rnum, v_total_count" part tripping me up. I'm pretty sure I have all the other fields in the output structure correct as I copied them directly from the proc.

How to initialize a varray table of {TABLE}%ROWTYPE?

I have a varray defined like:
declare
TYPE tnr_l IS VARRAY(30) of lve%ROWTYPE;
I want this varray to be initialized with a fetch from the database:
select * into tnr_l from lve where type = 'TNR' order by value;
But this fails with:
.ORA-06550: line 6, column 23:
PLS-00321: expression 'TNR_L' is inappropriate as the left hand side of an
assignment statement
How can I make this work?
You need to declare a variable of the type tnr_l, and then you need to use bulk collect in the select like this example:
declare
type t_dept is varray(100) of dept%rowtype;
l_dept t_dept;
begin
select * bulk collect into l_dept from dept;
for i in 1..l_dept.count loop
dbms_output.put_line(l_dept(i).dname);
end loop;
end;

Resources