DBMS_OUTPUT.PUT_LINE returning error - oracle

I am attempting to write a basic PL/SQL For Loop and keep getting an error. My statement is:
begin
for tab_x in
(select unique table_name from all_tables
where owner like 'MSGCENTER_DBO%'
and table_name like 'MSG_DETAIL%')
loop
DBMS_OUTPUT.PUT_LINE(tab_x);
end loop;
end;
/
The error message is
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
ORA-06550: line 6, column 7:
PL/SQL: Statement ignored
I am probably missing something VERY obvious but have not been able to get this to work. I appreciate any help!

You want to access tab_x.table_name instead.
begin
for tab_x in
(select unique table_name from all_tables
where owner like 'MSGCENTER_DBO%'
and table_name like 'MSG_DETAIL%')
loop
DBMS_OUTPUT.PUT_LINE(tab_x.table_name );
end loop;
end;
/

Related

Raise an error if a subquery returns no result

In DB2 it is possible to raise an error if a subquery returns no results with the help of coalesce and the raise_error scalar function. But how can this be done in oracle?
I checked scalar functions so far, but there is no raise error function.
example for db2 (note: the subquery needs to be replaced by something meaningful...):
SELECT
COALESCE(
(SELECT 1 FROM SYSIBM.SYSDUMMY1 LIMIT 0),
RAISE_ERROR('70NUL', 'Value is missing'))
FROM
SYSIBM.SYSDUMMY1;
UPDATE 1:
The use case is about finding a matching value in another table during an export of millions of records. The idea is to raise an error if there is no matching value so it is detected early and not afterwards.
The way you describe it it sounds as if you need to mark a number of records based on whenever some values exist in a table. If PLSQL is an option you can just use the no_data_found exception:
invalid_data CONSTANT NUMBER := -70;
DECLARE
l_var NUMBER;
BEGIN
SELECT 1
INTO l_var
FROM dual
WHERE 1 <> 1;
EXCEPTION WHEN no_data_found THEN
/* do your updating or error handling */ RAISE_APPLICATION_ERROR(invalid_data ,'Value is missing');
END;
You can use RAISE_APPLICATION_ERROR feature of oracle to resolve your problem. You can declare a procedure and define when to raise the exception in that procedure. Simply call the procedure to execute your task and it will raise the error whenever your given condition staisfies.
For knowing in details, please see the trapping user defined exceptions section of oracle documentation with example.
In Oracle, you'd use similar query:
SQL> select coalesce((select dummy from dual where 1 = 2), 'Value is missing') result from dual;
RESULT
----------------
Value is missing
SQL> select coalesce((select dummy from dual where 1 = 1), 'Value is missing') result from dual;
RESULT
----------------
X
SQL>
I don't speak MS SQL Server so I can't comment it.
Alternative to #Gnqz solution is to write a user function wrapper around raise_application_error() in conjunction with coalesce.
CREATE OR REPLACE FUNCTION raise_error
RETURN NUMBER
IS
BEGIN
raise_application_error(-70, 'Mapping value is missing');
RETURN(0);
END;
select coalesce((select 5 AS result from dual fetch first 1 row only), raise_error()) AS result from dual;

Why i'm getting "PLS-00302: component 'TABLE_NAME' must be declared"?

I'm trying to create a fairly simple stored procedure in Oracle 12.2 DB:
create or replace procedure list_tables (
p_src_schema varchar2
)
as
l_src_schema varchar2(30) := upper(p_src_schema);
begin
for x in (select table_name name from all_tables where owner = l_src_schema
and not regexp_like(table_name, '(AAA|BKP_|LOG_|TMP_|TEST|XX).*')
order by table_name)
loop
dbms_output.put_line(x.table_name);
end loop;
end;
/
show errors
and i'm getting the following error:
LINE/COL ERROR
-------- -----------------------------------------------------------------
11/9 PL/SQL: Statement ignored
11/32 PLS-00302: component 'TABLE_NAME' must be declared
the error occurs in the following line: dbms_output.put_line(x.table_name);
Question: what do I do wrong? I must be overseeing something very obvious...
UPDATE: the alias name has been "added" after pressing <TAB> by the dBeaver autocompletion - and I didn't notice it.
;)
Because you used column alias:
select table_name name from
----
which means that you should have used
dbms_output.put_line(x.name);
instead.

Error while compiling cursor in plsql block

I have a table as employee. I am new to oracle.I am creating the cursor but when I compile,I get error:
DECLARE
CURSOR c_data IS
SELECT distinct dept_id
FROM offc.employee;
tmp_event offc.employee.dept_id%type;
BEGIN
OPEN c_data;
LOOP
FETCH c_data INTO tmp_event;
EXIT WHEN c_data%NOTFOUND;
Dbms_Output.Put_Line(tmp_event.dept_id);
END LOOP;
CLOSE c_data;
END;
/
I got the error as follows:
Error at line 1 ORA-06550: line 15, column 40: PLS-00487: Invalid
reference to variable 'TMP_EVENT' ORA-06550: line 15, column 9:
PL/SQL: Statement ignored
I think there is problem in tmp_event declaration.How to handle this error?
You should use Dbms_Output.Put_Line(tmp_event);
where tmp_event is a variable which is already of type offc.employee.dept_id%type
This link would help for details.
Try Below Query
DECLARE
CURSOR c_data IS
SELECT distinct dept_id
FROM offc.employee;
tmp_event offc.employee.dept_id%type;
BEGIN
OPEN c_data;
LOOP
FETCH c_data INTO tmp_event;
EXIT WHEN c_data%NOTFOUND;
dbms_output.Put_line(tmp_event); --Dont Use Dept id
END LOOP;
CLOSE c_data;
END;
/
The following PL/SQL statement is equivalent to the original statement, but way shorter and thus less prone to programming errors.
DECLARE
CURSOR c_data IS
SELECT DISTINCT dept_id
FROM offc.employee;
BEGIN
FOR r_data IN c_data LOOP
Dbms_Output.Put_Line(r_data.dept_id);
END LOOP;
END;
/

PL/SQL FIRST LAST EXISTS - (cannot show table contents)

First, I have read the PL/SQL documentation repeatedly, no help. Second, I have googled for hours (usually being led here) and still cannot figure this out.
I have created an index table, which seems to have been successful - at least it did not throw any errors...
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name, job_id, salary FROM employees ORDER BY employee_id;
TYPE t_emp_rec IS TABLE OF cur_emps%ROWTYPE
INDEX BY BINARY_INTEGER;
v_emp_rec_tab t_emp_rec;
BEGIN
FOR emp_rec IN cur_emps LOOP
v_emp_rec_tab(emp_rec.employee_id) := emp_rec;
END LOOP;
However, when I try to show what is in my index table. I fail...
Documentation says do something like this...
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name, job_id, salary FROM employees ORDER BY employee_id;
TYPE t_emp_rec IS TABLE OF cur_emps%ROWTYPE
INDEX BY BINARY_INTEGER;
v_emp_rec_tab t_emp_rec;
BEGIN
FOR emp_rec IN cur_emps LOOP
v_emp_rec_tab(emp_rec.employee_id) := emp_rec;
END LOOP;
FOR i IN v_emp_rec_tab.FIRST..v_emp_rec_tab.LAST LOOP
IF v_emp_rec_tab.EXISTS(i)
THEN DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i));
END IF;
END LOOP;
END;
... which gives me this...
ORA-06550: line 13, column 12:
PLS-00306: wrong number or types of arguments in call to 'PUT_LINE'
ORA-06550: line 13, column 12:
PL/SQL: Statement ignored
In place of
THEN DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i));
. I have tried
emp_rec.last_name, v_emp_rec.last_name, cur_emps.last name
... it has been days now trying, can anyone help?
Thanks.
Daniel
You should iterate over an indexed table like this:
l_idx := v_emp_rec_tab.first;
while (l_idx is not null) loop
dbms_output.put_line( v_emp_rec_tab(l_idx).last_name );
l_idx := v_emp_rec_tab.next(l_idx);
end loop;
Otherwise you will get an exception when your table indexes are not consecutive.
See here
v_emp_rec_tab is of rowtype, and it's not possible to call as
DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i));
but you can call as :
DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i).last_name);
with only one column or you might concatenate like :
DBMS_OUTPUT.PUT_LINE(v_emp_rec_tab(i).last_name||' '||v_emp_rec_tab(i).employee_id);
for multiple columns.

PLSQL ignore compilation error which is not an error

I came accross interesting error where I am not sure about best way how to fix it. Given following block:
DECLARE
v_column_exists number := 0;
host_column_exists number := 0;
i number;
BEGIN
Select count(*) into v_column_exists from user_tab_cols where column_name = 'CONNECTIONDESCRIPTION' and table_name = 'NODES';
if (v_column_exists = 1) then
Select count(*) into host_column_exists from user_tab_cols where column_name = 'HOST' and table_name = 'NODES';
if (host_column_exists = 0) then
execute immediate 'alter table NODES add (Host varchar2(255))';
for item in (select connectiondescription, code from nodes) loop
... LOOP STUFF ...
end loop;
end if;
end if;
END;
I get following result:
PL/SQL: ORA-00904: "CONNECTIONDESCRIPTION": invalid identifier
ORA-06550: line 40, column 20: PL/SQL: SQL Statement ignored
ORA-06550: line 41, column 20: PLS-00364: loop index variable 'ITEM'
use is invalid
any ideas how to get rid of this error? Problem is occuring when column NODES.CONNECTIONDESCRIPTION is not present in database, however in such case for loop won't execute in runtime. I would need to disable these errors, but haven't found any way to do it. I have tried using ALTER SESSION SET PLSQL_WARNINGS='DISABLE:00904', but it had no effect.
Thanks
Correct approach was to use another dynamic query which bulk collects items to an array and then loop through this array.

Resources