How to set Oracle bind variables when using SQLPlus? - oracle

How do I set Oracle bind variables when using SQLPlus?
Example:
SELECT orders.order_no FROM orders WHERE orders.order_date BETWEEN :v1 AND :v2
How do I set the dates of :v1 and :v2?

Notice the following:
VARIABLE is a SQLPlus command. You don't end it with a semicolon (;).
In the VARIABLE command, you do not precede the variable name with
colon (:).
Bind variable can't be of data type "date" - they are some sort of
character value.
For that reason, IN YOUR CODE you must use to_date() with the
proper format model, or some other mechanism, to convert string to
date. That is currently missing in your code. NEVER compare dates to
strings!
Brief demo below.
SQL> variable v1 varchar2(20)
SQL> exec :v1 := '2015/12/22';
PL/SQL procedure successfully completed.
SQL> select 1 as result from dual where to_date(:v1, 'yyyy/mm/dd') < sysdate;
RESULT
----------
1

In common
you may use define and use variable with &
define x = 12 ;
select &x from dual;
Or varable
variable x refcursor;
begin
open :x for select * from dual connect by level < 11;
end;
/
print x

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;

Why parameter with default value is null?

I just want to ask a simple question, I have a procedure in my package: procedure(p_x in default sysdate). However, when i try to use this p_x to do query in my procdure, i got nothing from my table. My assumption is p_x does not get value from sysdate and it is null. Why does this happen? How can I fix it?
Thanks in advance.
In Package:
Procedure M_m(p_x in default sysdate)
In Package Body:
Procedure M_m(p_x in default sysdate) as
cursor cur is select manager_id, manager_name,manger_department
from employ_table where trunc(EmploymentDate)=trunc(p_x);
r_cur cur%rowtype;
Begin
for r_cur in cur
loop
DBMS_OUTPUT.PUT_LINE(employ_table.manager_id || employ_table.manager_name
|| employ_table.manager_department);
end loop;
end;
I guess Wernfried is right, it depends on how exactly you call it. Just add a DBMS_OUTPUT.PUT_LINE(p_x) immediately before the FOR to verify the value of the variable:
CREATE TABLE employ_table AS SELECT * FROM scott.emp;
UPDATE employ_table SET hiredate=SYSDATE WHERE ename='SCOTT';
CREATE OR REPLACE PACKAGE P IS
PROCEDURE M_m(p_x IN DATE DEFAULT sysdate);
END;
/
CREATE OR REPLACE PACKAGE BODY p IS
PROCEDURE M_m(p_x IN DATE DEFAULT sysdate) IS
CURSOR cur IS
SELECT * FROM employ_table WHERE TRUNC(hiredate)=TRUNC(p_x);
BEGIN
DBMS_OUTPUT.PUT_LINE('p_x='||p_x);
FOR r_cur IN cur LOOP
DBMS_OUTPUT.PUT_LINE(r_cur.mgr);
END LOOP;
END M_m;
END P;
/
EXEC P.m_m(DATE '1980-12-17');
p_x=1980-12-17 00:00:00
7902
EXEC P.m_m();
p_x=2018-05-26 17:50:11
7566
EXEC P.m_m(NULL);
p_x=
Currently (as of 18c) the default or := clause in a PLSQL parameter specification behaves like a pre-12c default clause in a table column definition. That is, the default value is only applied when the corresponding column is not specified at all.
If you define a table column as
somedate date default sysdate
then it will only be assigned the default value if the insert statement does not mention column somedate at all. If the insert sets somedate to null then it will be null, regardless of any default. The same behaviour is true of PL/SQL parameters. An explicit null value passed in overrides any default that you set for a parameter.
You will need to define a local constant along the lines of
k_x constant date := coalesce(p_x,sysdate);
and then have the rest of the procedure refer to that instead of the parameter.
In 12c we have default on null for table columns, but in my opinion PL/SQL lags behind, as it has no equivalent syntax for parameter defaults. If you pass null to a PL/SQL parameter, it respects that null and not any default that you specified, as it has no on null syntax option.
If you would like Oracle to extend PL/SQL parameter defaults along the same lines as table columns then consider voting for my suggestion here:
https://community.oracle.com/ideas/18189

PLSQL Passing Variables to External .SQL Scripts

I have 2 scripts, Script1.sql & Script2.sql. Script1.sql retrieves some data from a table in the database which I want to then pass to Script2.sql to use.
Script1.sql is as below:
SET SERVEROUTPUT ON;
DECLARE
FundRecord Test_Table%ROWTYPE;
CURSOR Fund_Cursor IS SELECT Code, YOURNAME FROM Test_Table;
BEGIN
OPEN Fund_Cursor;
LOOP
FETCH Fund_Cursor INTO FundRecord;
EXIT WHEN Fund_Cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Script1: ' || FundRecord.Code);
END LOOP;
CLOSE Fund_Cursor;
END;
/
#C:\Temp\Script2.sql FundRecord.Code;
And Script2.sql is as below:
BEGIN
DBMS_OUTPUT.PUT_LINE('Script 2:' || ' ' || '&1');
END;
/
The output from Script1.sql and Script2.sql is as follows:
Script1: ABDCE
Script2: FundRecord.Code
Why is the output of Script2 FundRecord.Code and not 'ABCDE' as I would expect?
How do I pass this in to ensure that Script2 is getting 'ABCDE' as the parameter?
Thanks
The record FundRrecord only exists within the PL/SQL block. You need to declare a separate variable that you can use outside the block:
set autoprint on serverout on
var somevalue varchar2(20)
col somevalue new_value somevalue
begin
for r in (
select dummy from dual
)
loop
dbms_output.put_line('Script 1: ' || r.dummy);
:somevalue := r.dummy;
end loop;
end;
/
#C:\Temp\Script2.sql &somevalue
The column ... new_value ... syntax is provided in SQL*Plus for page headers and footers in reports, but it is also very useful in scripts as it sets a define variable from the (last) result of a query. set autoprint on tells SQL*Plus to print the values of any bind variables (the ones with a leading :) after each PL/SQL block, and helpfully it does this by generating a query, allowing us to set up a column ... new_value and capture the result in a substitution variable.
Edit: regarding SQL Developer compatibility, I'll try some things out when I get a chance, but you might try adding something along the lines of
select :somevalue as somevalue from dual;
after the PL/SQL block, in case the column ... new_value construction works the same as in SQL*Plus but autoprint does not.
You can try as
#Script2.sql param1
and in Script2 SQL file, refer the parameter as
&1
Update 1
Here is my test case which works fine.
SELECT SYSDATE FROM &1;
This SQL statement is saved as Test.sql and it is invoked from SQLPLUS as
#D:\Test.sql dual
where dual is the parameter which been passed to Test.sql file
Result is displayed in the below screenshot

Declare bind variables in SQL*Plus

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;

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.

Resources