Reputation: 839
When I run this PL/SQL block:
SQL> set serveroutput on
SQL> declare
2 v_max_sal NUMBER(20)
3 begin
4 select max(sal) INTO :v_max_sal
5 from emp e, dept d
6 where e.deptno=d.deptno
7 and d.dname='SALES';
8 END;
9 /
it throws to me the next error: SP2-0552: Bind variable "V_MAX_SAL" not declared.
What am I missing or doing wrong?
Upvotes: 3
Views: 84739
Reputation: 635
Lose the :
in front of v_max_sal
on your select ... into
statement:
SQL> set serveroutput on
SQL> declare
2 v_max_sal NUMBER(20)
3 begin
4 select max(sal) INTO v_max_sal
5 from emp e, dept d
6 where e.deptno=d.deptno
7 and d.dname='SALES';
8 END;
9 /
Upvotes: 1
Reputation: 21073
Note also, that a typical usage of bind variables covers the literal string in the WHERE predicate, so you may additionally replace the department name with it (to be able use the same query for all departments).
VARIABLE v_max_sal NUMBER;
VARIABLE v_dname VARCHAR2(14);
begin
:v_dname := 'SALES';
select max(sal) INTO :v_max_sal
from scott.emp e, scott.dept d
where e.deptno=d.deptno
and d.dname = :v_dname;
END;
/
print v_max_sal;
You may also simple remove the colon before the variable and it will work too:
SQL> set serveroutput on
SQL> declare
2 v_max_sal NUMBER(20);
3 begin
4 select max(sal) INTO v_max_sal
5 from scott.emp e, scott.dept d
6 where e.deptno=d.deptno
7 and d.dname='SALES';
8 dbms_output.put_line(v_max_sal);
9 END;
10 /
2850
Note that this variant and the solution proposed by @Alex lead to an identical query in the database:
SELECT MAX(SAL) FROM SCOTT.EMP E, SCOTT.DEPT D WHERE E.DEPTNO=D.DEPTNO AND D.DNAME='SALES'
So in the database no bind variable is used.
The extended option in the begin of this answer leads to a query with a BV in the WHERE clause:
SELECT MAX(SAL) FROM SCOTT.EMP E, SCOTT.DEPT D WHERE E.DEPTNO=D.DEPTNO AND D.DNAME = :B1
Upvotes: 3
Reputation: 191275
If you definitely want a bind variable then you need to declare it outside the block:
variable v_max_sal number;
begin
select max(sal)
into :v_max_sal
from dept d
join emp e
on e.deptno=d.deptno
where d.dname='SALES';
end;
/
print v_max_sal
Notice the SQL*Plus client variable
and print
commands, and that there is no longer a declare
section in the block, as you don't now have or need a local PL/SQL variable. A local variable can act as a bind variable when it's used in a query - the parser sees it like that, and you'll see a placeholder in the query's plan - but it's not quite the same thing, as you usually want the bind variable to be referencable outside the Pl/SQL code.
I've also used modern join syntax, though that isn't relevant to the problem.
Upvotes: 4