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

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.

Related

How to use a variable in a LIKE clause in PL/SQL

I am new to Oracle and learning; I am simply trying to run this T-SQL query
DECLARE #SearchObj varchar(100);
SET #SearchObj='%aldbrough%';
SELECT
obj_id,
name,
description
FROM
agnis.t_object
WHERE
lower(name) = ObjToSearch ;
I am using SQL Developer Oracle tool which also have a "Scratch Editor" to help with translation from T-SQL. When i run the tool it gave me this code
DECLARE
v_SearchObj VARCHAR2(100);
BEGIN
v_SearchObj := '%aldbrough%' ;
SELECT obj_id ,
NAME ,
DESCRIPTION
FROM agnis.t_object
WHERE LOWER(NAME) = ObjToSearch;
END;
but the same tool give me this error
Error report -
ORA-06550: line 10, column 26:
PL/SQL: ORA-00904: "OBJTOSEARCH": invalid identifier
ORA-06550: line 6, column 4:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
so what is the correct syntax to use a variable into a LIKE clause that returns multiple rows?
I hope I do not have to use cursors etc for such of a simple statement as suggested in this question
Well, yes - those "translators" don't always do what they are supposed to.
This is how your code should look like:
use like, not = in the where clause
in PL/SQL, you have to put the result of the select statement into something - for example, locally declared variables (as my example shows).
So:
DECLARE
v_SearchObj VARCHAR2 (100) := '%aldbrough%';
--
v_obj_id t_object.obj_id%TYPE;
v_name t_object.name%TYPE;
v_description t_object.description%TYPE;
BEGIN
SELECT obj_id, NAME, DESCRIPTION
INTO v_obj_id, v_name, v_description
FROM agnis.t_object
WHERE LOWER (NAME) LIKE v_searchobj;
END;
If such a code returns an error - too_many_rows (and yes, it does), then one option is to loop through rows and do something (such as display those values):
DECLARE
v_SearchObj VARCHAR2 (100) := '%aldbrough%';
BEGIN
FOR cur_r IN (SELECT obj_id, NAME, DESCRIPTION
FROM agnis.t_object
WHERE LOWER (NAME) LIKE v_searchobj)
LOOP
DBMS_OUTPUT.put_line (
'Name = ' || cur_r.name || ', description = ' || cur_r.description);
END LOOP;
END;
Since this is tagged SQL Developer, use a bind variable:
SELECT obj_id,
name,
description
FROM agnis.t_object
WHERE lower(name) = :ObjToSearch;
and SQL developer will pop up a dialog box where you can set the value of the ObjToSearch variable.
If you want to specify the bind variable in code then:
VARIABLE objtosearch VARCHAR2(50)
BEGIN
:objtosearch := '%aldbrough%';
END;
/
SELECT obj_id,
name,
description
FROM agnis.t_object
WHERE lower(name) = :ObjToSearch;
And run the statements as a script using F5 rather than as individual statements.

Store Procedure hit SQL Statement Ignored

create or replace PROCEDURE GEN_STATEMENT_SP(indexNM IN VARCHAR2, tableNM IN VARCHAR2) AS
BEGIN
DECLARE
uniqueSTMT VARCHAR2(30);
nonUniqueSTMT VARCHAR2(30);
charOn VARCHAR2(5);
tempfld VARCHAR2(500) ;
CURSOR chkTyp IS(SELECT ES_UNIQUENESS from sys.dba_ind_columns where INDEX_NAME = indexNM and TABLE_NAME = tableNM);
CURSOR tblColumn IS(SELECT INDEX_NAME,listagg(COLUMN_NAME, ',') WITHIN GROUP (ORDER BY COLUMN_POSITION) COLUMN_NAME FROM sys.dba_ind_columns where INDEX_NAME = indexNM and TABLE_NAME = tableNM GROUP BY INDEX_NAME);
BEGIN
uniqueSTMT := 'CREATE UNIQUE INDEX';
nonUniqueSTMT := 'CREATE INDEX';
charOn := 'on';
if chkTyp.ES_UNIQUENESS = 'UNIQUE' then
tempfield := uniqueSTMT || indexNM || charOn || tableNM || '(' || tblColumn.COLUMN_NAME || ')' ;
DBMS_OUTPUT.put_line(tempfld);
end if;
END;
END;
/
Error list:
LINE/COL ERROR
-------- ------------------------------------------------------------------
9/17 PL/SQL: SQL Statement ignored
9/48 PL/SQL: ORA-00942: table or view does not exist
10/20 PL/SQL: SQL Statement ignored
10/126 PL/SQL: ORA-00942: table or view does not exist
18/1 PL/SQL: Statement ignored
18/11 PLS-00225: subprogram or cursor 'CHKTYP' reference is out of scope
Hi all, when i try to create a sample store procedure above. I hit SQL Statement ignored.
Need some help on this, Thanks alot.
You don't have access to DBA_ views (owned by SYS). Do you really need those? Switch to USER_IND_COLUMNS instead. Once you make that code work, expand it further (if necessary).
As of CHKTYP being improperly used: you declared a cursor, but never did anything with it (opened, fetched, ..., closed). On the other hand, why do you use cursors? Those are SELECT statements that return a single value (unless I'm wrong), so they might have been ordinary SELECTs (but yes, you might have to handle possible NO-DATA-FOUND exception).
Furthermore, there's no column ES_UNIQUENESS in USER_IND_COLUMNS view; what is is supposed to do? It exists in USER_INDEXES, but is called UNIQUENESS, without the ES_ prefix.
Shortly, you need to rewrite that code. Take it step by step, test frequently. Once you're sure that the first step was successful, go to the next.

Invalid table name error, when execute alter stored procedure in oracle

-- Disable constaint, good
CREATE OR REPLACE PROCEDURE cpl_disable_constraint(table_name IN varchar2, constraint_name IN varchar2)
AS
BEGIN
execute immediate 'ALTER TABLE :1 DISABLE CONSTRAINT :2' using table_name, constraint_name;
END;
/
-- Bug
declare
table_name varchar2(100) := 'ADV_TEST_COURSE_CREDIT';
column_name varchar2(100) := 'SEQUENCE_NUMBER';
begin
cpl_disable_constraint(table_name, column_name);
end;
/
I'm getting these errors:
ORA-00903: invalid table name
ORA-06512: at "SISD_OWNER.CPL_DISABLE_CONSTRAINT", line 5
ORA-06512: at line 5
00000 - "invalid table name"
Any idea?
As a_horse_with_no_name mentioned, you can't pass an identifier to execute immediate as a parameter. You have to put it in the SQL statement.
execute immediate 'ALTER TABLE ' || table_name || ' DISABLE CONSTRAINT :1' using constraint_name;
Note that this will open you up to SQL Injection if you don't carefully validate the table_name variable. I usually do something like this before calling execute immediate, to make sure the table_name variable is the valid and correct table name for the constraint, and not some malicious string like null; DROP TABLE ADV_TEST_COURSE_CREDIT;:
select c.table_name into table_name from user_constraints c where c.constraint_name = constraint_name;
(By the way, this is part of why people often choose a prefix for local PL/SQL variable names, like "v_table_name", to keep them separate from column names. You can see it's a little confusing in the query above.)
Also I'd like to point out that in your function definition, you're calling the second parameter "constraint_name", but in the anonymous block you're calling it "column_name".

PLS-00201 - identifier must be declared

I executed a PL/SQL script that created the following table
TABLE_NAME VARCHAR2(30) := 'B2BOWNER.SSC_Page_Map';
I made an insert function for this table using arguments
CREATE OR REPLACE FUNCTION F_SSC_Page_Map_Insert(
p_page_id IN B2BOWNER.SSC_Page_Map.Page_ID_NBR%TYPE,
p_page_type IN B2BOWNER.SSC_Page_Map.Page_Type%TYPE,
p_page_dcpn IN B2BOWNER.SSC_Page_Map.Page_Dcpn%TYPE)
I was notified I had to declare B2BOWNER.SSC_Page_Map prior to it appearing as an argument to my function. Why am I getting this error?
EDIT: Actual error
Warning: compiled but with compilation errors
Errors for FUNCTION F_SSC_PAGE_MAP_INSERT
LINE/COL ERROR
-------- -----------------------------------------------------------------
2/48 PLS-00201: identifier 'SSC_PAGE_MAP.PAGE_ID_NBR' must be declared
0/0 PL/SQL: Compilation unit analysis terminated
EDIT: Complete PL/SQL Function
RETURN INTEGER
IS
TABLE_DOES_NOT_EXIST exception;
PRAGMA EXCEPTION_INIT(TABLE_DOES_NOT_EXIST, -942); -- ORA-00942
BEGIN
INSERT INTO
B2BOWNER.SSC_Page_Map VALUES(
p_page_id,
p_page_type,
p_page_dcpn);
RETURN 0;
EXCEPTION
WHEN TABLE_DOES_NOT_EXIST THEN
RETURN -1;
WHEN DUP_VAL_ON_INDEX THEN
RETURN -2;
WHEN INVALID_NUMBER THEN
RETURN -3;
WHEN OTHERS THEN
RETURN -4;
END;
SHOW ERRORS PROCEDURE F_SSC_Page_Map_Insert;
GRANT EXECUTE ON F_SSC_Page_Map_Insert TO B2B_USER_DBROLE;
RETURN INTEGER
EDIT: I change the arguments and received a new error related to the insert command
CREATE OR REPLACE FUNCTION F_SSC_Page_Map_Insert(
p_page_id IN INTEGER,
p_page_type IN VARCHAR2,
p_page_dcpn IN VARCHAR2)
RETURN INTEGER
IS
TABLE_DOES_NOT_EXIST exception;
PRAGMA EXCEPTION_INIT(TABLE_DOES_NOT_EXIST, -942); -- ORA-00942
BEGIN
INSERT INTO
B2BOWNER.SSC_Page_Map VALUES(
p_page_id,
p_page_type,
p_page_dcpn);
The error
Errors for FUNCTION F_SSC_PAGE_MAP_INSERT
LINE/COL ERROR
-------- -----------------------------------------------------------------
17/18 PL/SQL: ORA-00942: table or view does not exist
16/5 PL/SQL: SQL Statement ignored
The tables has been verified within the correct schema and with the correct attribute names and types
EDIT: I executed the following command to check if I have access
DECLARE
count_this INTEGER;
BEGIN
select count(*) into count_this
from all_tables
where owner = 'B2BOWNER'
and table_name = 'SSC_PAGE_MAP';
DBMS_OUTPUT.PUT_LINE(count_this);
END;
The output I received is
1
PL/SQL procedure successfully completed.
I have access to the table.
EDIT:
So I finally conducted an insert into the table via the schema using PL/SQL and it worked fine. It appears I simply do not have authority to create functions but that is an assumption.
EDIT:
Actual table DDL statement
v_create := 'CREATE TABLE ' || TABLE_NAME || ' (
PAGE_ID_NBR NUMERIC(10) NOT NULL Check(Page_ID_NBR > 0),
PAGE_TYPE VARCHAR2(50) NOT NULL,
PAGE_DCPN VARCHAR2(100) NOT NULL,
PRIMARY KEY(Page_ID_NBR, Page_Type))';
EXECUTE IMMEDIATE v_create;
COMMIT WORK;
COMMIT COMMENT 'Create Table';
When creating the TABLE under B2BOWNER, be sure to prefix the PL/SQL function with the Schema name; i.e. B2BOWNER.F_SSC_Page_Map_Insert.
I did not realize this until the DBAs pointed it out. I could have created the table under my root USER/SCHEMA and the PL/SQL function would have worked fine.
The procedure name should be in caps while creating procedure in database.
You may use small letters for your procedure name while calling from Java class like:
String getDBUSERByUserIdSql = "{call getDBUSERByUserId(?,?,?,?)}";
In database the name of procedure should be:
GETDBUSERBYUSERID -- (all letters in caps only)
This serves as one of the solutions for this problem.
you should give permission on your db
grant execute on (packageName or tableName) to user;

Variable in UPDATE oracle in procedure : invalid identifier

I don't understand why service is complaining with
Fehler(36,11): PL/SQL: ORA-00904: "FOUND_VP": invalid identifier
Variable is declared in the first begin...
Is it not possible to use variable directly in queries ?
when trying store following procedure :
create or replace PROCEDURE fpwl_update_vp(
my_zn IN NUMBER, my_verwaltung IN VARCHAR2 , my_variante IN NUMBER, my_vp IN NUMBER
) IS
BEGIN
DECLARE
search_VP IFT_INFO_LAUF.VP%TYPE;
found_VP IFT_INFO_LAUF.VP%TYPE;
INFOversion number := 25;
BEGIN -- search SYFA_VP
SELECT SYFA_VP
INTO found_VP
FROM FPWL_VP_MAPPING
WHERE INFO_VP=search_VP ;
exception
when no_data_found then
dbms_output.put_line ('Kein SYFA VP : Importiere aus SYFA');
--found_VP:=:=cus_info25.pa_info_data.fn_insert_syfa_vp(my_vp,25);
WHEN OTHERS THEN
ROLLBACK;
RETURN;
END; -- SYFA VP
-- Update VP
UPDATE IFT_INFO_LAUF
SET vp = found_VP
WHERE id_kopf IN
(SELECT id_kopf
FROM ift_info_kopf
WHERE fahrtnummer= my_zn
AND verwaltung= my_verwaltung
AND variante = my_variante
)
;
--COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END ;
Your problem is that found_VP is going out of scope.
Move the contents of the "DECLARE" block to just after the "IS":
create or replace PROCEDURE fpwl_update_vp(
my_zn IN NUMBER, my_verwaltung IN VARCHAR2 , my_variante IN NUMBER, my_vp IN NUMBER
) IS
search_VP IFT_INFO_LAUF.VP%TYPE;
found_VP IFT_INFO_LAUF.VP%TYPE;
INFOversion number := 25;
BEGIN
BEGIN -- search SYFA_VP
etc
Make sure that
FPWL_VP_MAPPING.SYFA_VP
is the same type with
IFT_INFO_LAUF.VP
and make sure that
SELECT SYFA_VP INTO found_VP FROM FPWL_VP_MAPPING WHERE INFO_VP=search_VP ;
does not return multiple rows.
But I doubt that is the case with the error that you have given.
Since the error message refers to line 36 and the reference to found_VP in your code sample is on line 18, you've omitted the part of the code that actually has the problem.
It looks like you have a scope problem; you're declaring found_VP in an inner block (one level of DECLARE/BEGIN/END) and referring to it outside that block, either in the parent block or another one at the same level. The issue isn't where you're selecting into found_VP, it's (I think) that you're referring to it again later on, beyond the code you've posted, and therefore outside the block the variable is declared in.
To demonstrate, I'll declare l_name in an inner block, as you seem to have done:
create or replace procedure p42 is
begin
declare
l_name all_tables.table_name%TYPE;
begin
select table_name
into l_name -- this reference is OK
from all_tables
where table_name = 'EMPLOYEES';
end;
select table_name
into l_name -- this reference errors
from all_tables
where table_name = 'JOBS';
end;
/
Warning: Procedure created with compilation errors.
show errors
Errors for PROCEDURE P42:
LINE/COL ERROR
-------- -----------------------------------------------------------------
12/2 PL/SQL: SQL Statement ignored
13/7 PLS-00201: identifier 'L_NAME' must be declared
14/2 PL/SQL: ORA-00904: : invalid identifier
Notice that the error is reported against line 13, which is in the outer block; it doesn't complain about it in the inner block because it is in-scope there.
So, you need to declare the variable at the appropriate level. As Colin 't Hart says that is probably right at the top, between the IS and the first BEGIN, as that is the procedure-level DECLARE section (it doesn't need an explicit DECLARE keyword).

Resources