Errors in PL/SQL - oracle

I was trying to create a PL/SQL program to search for a value in entire database. Following is the code:
DECLARE
custom_query VARCHAR2(100);
user_input VARCHAR2(100);
i NUMBER (6);
TYPE temp_record
IS
varray(1000) OF VARCHAR2(100);
CURSOR t_rec IS
SELECT a.name AS t_name,
b.name AS c_name
FROM sys.TABLES a,
sys.COLUMNS b
WHERE a.object_id = b.object_id;
table_rec t_name%ROWTYPE;
BEGIN
IF NOT t_rec%isopen THEN
OPEN t_rec;
END IF;
FETCH t_rec
INTO table_rec;
WHILE t_rec%FOUND THEN
LOOP
custom_query := 'select'
|| table_rec.c_name
|| 'into temp_record from'
||table_rec.t_name ;
dbms_output.Put_line(custom_query);
EXECUTE IMMEDIATE custom_query;
FOR i IN 1 .. temp_record.count
LOOP
IF (Temp_record(i) = user_input) THEN
dbms_output.Put_line ('The value you are looking for is in '
|| table_rec.c_name
|| 'column of table'
|| table_rec.t_name);
END IF;
END LOOP;
END LOOP;
END;
Can anyone let me know what's wrong with this code?

Use ALL_TAB_COLUMNS to iterate all tables and columns in your dynamic query.

Related

PLS-00302: component 'M' must be declared in oracle 11g [duplicate]

This question already has answers here:
Accessing elements of Oracle PLSQL record type on runtime
(3 answers)
Closed 6 months ago.
I want to convert table type data into single variable with ',' separated
also I dont know what column used in table type. please let us know how to achieve it without passing column name, output must be string type.
DECLARE
TEST_TAB ADT.TEST_TABB2 := ADT.TEST_TABB2(adt.test_obj(2,
'dsd'),
adt.test_obj(3,
'agg'));
l_name clob := '';
CURSOR c IS
SELECT
ATTR_NAME
FROM
ALL_TYPE_ATTRS
WHERE
OWNER = 'ADT'
AND TYPE_NAME = (
SELECT
REFERENCED_NAME
FROM
DBA_DEPENDENCIES
WHERE
REFERENCED_OWNER = 'ADT'
AND NAME = 'TEST_TABB2'
AND REFERENCED_TYPE = 'TYPE');
t nvarchar2(500) := '';
BEGIN
FOR i IN TEST_TAB.FIRST .. TEST_TAB.LAST
LOOP
l_name := l_name || '(';
FOR cur IN c LOOP
t := cur.ATTR_NAME;
dbms_output.put_line(t);
l_name := l_name || ' ' || t ;
l_name := l_name || ', ' || TEST_TAB(i).t;
END LOOP;
l_name := l_name || ')' ;
END LOOP;
dbms_output.put_line(l_name);
END;
You could use dynamic SQL, concatenating in the attribute name, and passing the object as a bind variable:
...
BEGIN
FOR i IN TEST_TAB.FIRST .. TEST_TAB.last LOOP
FOR cur IN c LOOP
m := '.' || cur.ATTR_NAME;
execute immediate 'select :o' || m || ' from dual'
into t
using test_tab(i);
dbms_output.put_line(t);
END LOOP;
END LOOP;
END;
or
...
BEGIN
FOR i IN TEST_TAB.FIRST .. TEST_TAB.last LOOP
FOR cur IN c LOOP
execute immediate 'select :o.' || cur.ATTR_NAME || ' from dual'
into t
using test_tab(i);
dbms_output.put_line(t);
END LOOP;
END LOOP;
END;
which both produce output;
2
John
3
Devid
db<>fiddle
The first block above doesn't work in the unpatched version of 11gR2 available in db<>fiddle, but I'm not quite sure why, or whether it would work in a later, patched, version. The second block does work though.

Oracle PL equivalent of foreach-loop

I need to loop over about 10 strings, which are all known to me in advance -- I don't need to SELECT them from anywhere.
I attempted:
BEGIN
FOR tab IN ('one', 'two', 'three')
LOOP
EXECUTE IMMEDIATE 'DROP TABLE ' || tab;
END LOOP;
END;
But that does not work (LOOP is unexpected)...
Is there a way to do this?
declare
type t_strings is table of varchar2(100);
strings t_strings:=t_strings('one','two','three');
begin
for i in 1..strings.count loop
dbms_output.put_line(strings(i));
end loop;
end;
/
Results:
one
two
three
Or you can use your own short-cut functions:
http://orasql.org/2017/10/02/plsql-functions-iterate-and-keys-for-associative-arrays/
Btw, Oracle 21 has some new features for FOR-LOOP:
1.1.1 PL/SQL Extended Iterators
FOR LOOP Iteration Enhancements in Oracle Database 21c
So it can be rewritten as:
declare
type t_strings is table of varchar2(100);
begin
for str in values of t_strings('one','two','three') loop
dbms_output.put_line(str);
end loop;
end;
/
"almost real" foreach loop:
declare
type tabList is table of varchar2(32);
tabs tabList := tabList ('one', 'two', 'three');
curr varchar2(32) := tabs.first;
begin
<<foreach>> loop exit foreach when curr is null;
execute immediate 'create table '||tabs(curr)||' (col char(1))';
execute immediate 'drop table '||tabs(curr)||' purge';
curr := tabs.next (curr);
end loop;
end;
/
PL/SQL procedure successfully completed.
begin
for tab_rec in ( select 'abc' val from dual
union
select '123' val from dual )
loop
EXECUTE IMMEDIATE 'DROP TABLE ' || tab_rec.val;
end loop;
end;

Where clause in Dynamic sql

I am trying to get all the tables where bank_id is 01.
I have written the following block
DECLARE
cursor cBankId is
select owner||'.'||table_name from all_tab_columns where column_name = 'BANK_ID';
v_table all_tab_columns.table_name%TYPE;
vcount varchar2(50);
BEGIN
open cBankId;
loop
fetch cBankId into v_table;
exit when cBankId%notfound;
execute immediate 'select count(*) from ' || v_table into vcount || ' where bank_id = 01';
IF vcount > 0 THEN
DBMS_OUTPUT.PUT_LINE (v_table);
END IF;
end loop;
close cBankId;
END;
I want to know how to put where clause in the execute immediate statement .
I am getting the error
ORA-06550: line 15, column 67:
PLS-00103: Encountered the symbol "|" when expecting one of the following:
. ( , % ; return returning using
You only need to change the order you're writing the parts of your query.
When using dynamic SQL, you need something like this:
SQL> declare
2 v_table varchar2(30);
3 vCount number;
4 begin
5 v_table := 'dual';
6 execute immediate 'select count(*) from ' || v_table || ' where 1=1' into vcount;
7 --
8 dbms_output.put_line('vCount: ' || vCount);
9 end;
10
11 /
vCount: 1
PL/SQL procedure successfully completed.
That is: execute immediate 'select ... from ... where ...' INTO ...;
You can't dynamically use a variable for the table name, instead use:
DECLARE
cursor cBankId is
select owner||'.'||table_name from all_tab_columns where column_name = 'BANK_ID';
v_table all_tab_columns.table_name%TYPE;
vcount varchar2(50);
v_sql varchar2(1000);
BEGIN
open cBankId;
loop
fetch cBankId into v_table;
exit when cBankId%notfound;
v_sql := 'select count(*) from ' || v_table || ' into vcount where bank_id = 01';
execute immediate v_sql;
IF vcount > 0 THEN
DBMS_OUTPUT.PUT_LINE (v_table);
END IF;
end loop;
close cBankId;
END;

Write a database function that should display {1} if object exists {0} if object does not exist in the database

Help me finish this function, please. If you could proof read and correct my mistake I could really appreciate it.
a. The function takes two INPUT parameters {object_name, object_type} and return an INT.
Object Names and Object Types are related as follows.
b. {object_name} can be any database object like TABLES, SEQUENCES, SYNONYMS, VIEWS.
c. {object_type} can be {T, SEQ, SYN, V}. Each object type corresponds to its object names.
T=>TABLES, SYN=>SYNONYMS, SEQ=>SEQUENCES, V=>VIEWS.
For example if I pass the object_name as ‘EMPLOYEES’, object_type as ‘T’ then it should check if this object in the database and then return either {1} or {0}.
create or replace function OBJECT_CHECK (object_name varchar,
object_type varchar,
)
return int
AS
BEGIN
DECLARE
v_Number NUMBER;
V_NUMBER1 NUMBER;
v_str VARCHAR2(100);
OBJECTS_NAME VARCHAR2(100):='&object';
v_tab VARCHAR2(100);
BEGIN
SELECT COUNT(* ) --for tables checking
INTO v_Number
FROM User_Tables
WHERE Table_Name = UPPER(OBJECTS_NAME);
v_str :='TABLE_NAME';
IF V_NUMBER =0 THEN -- for synonyms checking
SELECT COUNT(* )
INTO v_Number
FROM user_synonyms
WHERE synonym_Name = UPPER(OBJECTS_NAME);
v_str :='SYNONYM';
END IF;
--dbms_output.put_line(v_number);
v_str:='INDEX';
END IF;
IF V_NUMBER = 0 THEN -- for COLUMN checking
BEGIN
FOR i IN
(SELECT table_name FROM all_tab_cols WHERE column_name =UPPER(OBJECTS_NAME)
)
LOOP
dbms_output.put_line(UPPER(OBJECTS_NAME)|| ' Coulmn available in ' ||
i.table_name || ' table ');
END LOOP;
v_str:='colum';
END;
END IF;
IF V_NUMBER = 0 THEN
SELECT count(*)
into v_number FROM all_tab_cols WHERE column_name =UPPER(OBJECTS_NAME);
end if;
IF v_Number >= 1 AND v_str='TABLE_NAME' THEN
dbms_Output.Put_Line(UPPER(OBJECTS_NAME) ||'-----> TABLE IS AVAILABLE IN THE
SCHEMA ' );
ELSE
dbms_Output.Put_Line(UPPER(OBJECTS_NAME) ||'-----> NO SUCH TABLE AVAILABLE IN
THE SCHEMA ' );
END IF;
IF v_Number >= 1 AND v_str='SYNONYM' THEN
dbms_Output.Put_Line(UPPER(OBJECTS_NAME) ||'-----> SYNONYM IS AVAILABLE IN THE
SCHEMA ' );
ELSE
dbms_Output.Put_Line(UPPER(OBJECTS_NAME) ||'-----> NO SUCH SYNONYM AVAILABLE
IN THE SCHEMA ' );
END IF;
IF v_Number >= 1 AND v_str='INDEX' THEN
dbms_Output.Put_Line(UPPER(OBJECTS_NAME) ||'-----> INDEX IS AVAILABLE IN THE
SCHEMA ' );
ELSE
dbms_Output.Put_Line(UPPER(OBJECTS_NAME) ||'-----> NO SUCH INDEX AVAILABLE IN
THE SCHEMA ' );
END IF;
IF v_Number = 0 or V_STR <>'colum' THEN
dbms_Output.Put_Line(UPPER(OBJECTS_NAME) ||'-----> NO SUCH COLUMN AVAILABLE IN
THE SCHEMA ' );
END IF;
END;
END;
Not sure if this is the problem you're referring to, but you've got some syntax errors. You should have received error messages pointing you to these. However...
You have a comma here...remove it
create or replace function OBJECT_CHECK (object_name varchar,
object_type varchar, <--HERE
)
return int
And you have an extra end here as well
END;
END;

need to modify the below oracle query

I have the below script , i want to modify it such a way lets say if it is executed first time then it will create the column but lets say if it is executed second time then it will show fail message which is not correct it should show the message that column is created and also if there comes any exception lets say column i s not created due to some technical exception then it should show fail message , please advise how to achieve this
SELECT COUNT(*) INTO L_COL_EXISTS FROM USER_TAB_COLS WHERE COLUMN_NAME = 'TOR' and TABLE_NAME='AVOICE';
IF L_COL_EXISTS = 1
THEN
outcome := 'Success';
ELSE
outcome := 'Fail';
END IF;
DBMS_OUTPUT.PUT_LINE(outcome);
folks please advise
I suppose it can help you
CREATE OR REPLACE PROCEDURE add_column
(
v_table_name IN VARCHAR2,
v_column_name IN VARCHAR2,
v_column_type IN VARCHAR2
)
IS
v_column_exists pls_integer;
v_ddl_str varchar2(1024);
BEGIN
BEGIN
SELECT count(*)
INTO v_column_exists
FROM user_tab_columns
WHERE table_name = upper(v_table_name)
and column_name = upper(v_column_name);
EXCEPTION
WHEN OTHERS THEN
RAISE;
END;
if v_column_exists = 0 then
v_ddl_str := 'alter table ' || v_table_name || ' add ( ' || v_column_name || ' ' || v_column_type || ')';
BEGIN
EXECUTE IMMEDIATE alter_str;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line ('something wrong');
RAISE;
END;
ELSE
dbms_output.put_line ('Column exists');
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END add_column;
/

Resources