PL/SQL EXECUTE IMMEDIATE, table name not valid - plsql

I have to create a new table for each entry in a separate table(Studenti in my case) dynamically. I am just starting to learn about Dynamic Sql. I use the fallowing procedure:
CREATE or REPLACE PROCEDURE carnet_student IS
CREATE_TABLE_QUERY VARCHAR2(250);
CURSOR table_name is SELECT NR_MATRICOL FROM STUDENTI;
nume CHAR(4);
BEGIN
OPEN table_name;
LOOP
FETCH table_name INTO nume;
EXIT when table_name%NOTFOUND;
CREATE_TABLE_QUERY:='Create TABLE '||nume||'(
column1 varchar2(50),
column2 varchar2(50),
column3 number(2),
column4 DATE
)';
EXECUTE IMMEDIATE CREATE_TABLE_QUERY;
END LOOP;
CLOSE table_name;
END;
/
BEGIN
carnet_student;
END;
I receive the error ORA-00903: invalid table name. Any ideas how to solve this?

Related

Find a column and a value from a schema scan all the table in oracle

I am trying to find a column (ABC) and it's value 1234 from a schema , basically i need to to check if ABC and a value from this column 1234 is present in any other table that is mapped to ABC , i tried to do a search the most efficient way but it is taking lot of time and not retrieving the desired result
i have tried
https://lalitkumarb.wordpress.com/2015/01/06/sql-to-search-for-a-value-in-all-columns-of-all-atbles-in-an-entire-schema/
but the query is not results at all it is running running...
You may write the output to a file if you get buffer overflow on set Serveroutput otherwise this should do.Output will have all tables that has 'ABC' column and respective count shows count of record with ABC column value as 1234.
SET SERVEROUTPUT ON 100000
DECLARE
lv_count number(10):=0;
l_str varchar2 (1000);
BEGIN
FOR V1 IN
(select distinct table_name
from dba_tab_columns
where column_name = 'ABC')
LOOP
BEGIN
lv_query := ' select count(*) from '||v1.table_name||' where ABC =1234';
EXECUTE IMMEDIATE lv_query INTO lv_count;
dbms_output.put_line(v1.table_name||' --> '||lv_count);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('OTHERS EXCEPTION '||v1.table_name||' ERRCODE '||SQLERRM||' '||SUBSTR(SQLCODE,1,200));
END;
END LOOP;
END;
To find all tables having column_name ABC, simple query as below should do.
select table_name
from dba_tab_columns
where column_name = UPPER('ABC');
PS: Metadata tables(dba_Tab_columns) stores column_name in upper case, to avoid any issues with case ,converting the case to upper for the literal.
Second query in PL/SQL block,
SET SERVEROUTPUT ON 100000
DECLARE
lv_count number(10):=0;
l_str varchar2 (1000);
lv_col_name varchar2(255) :='ABC';
BEGIN
FOR V1 IN
(select distinct table_name
from dba_tab_columns
where column_name = lv_col_name)
LOOP
dbms_output.put_line(lv_col_name||' '||v1.table_name);
END LOOP;
END;

PLSQL_trigger cannot be complied

I need to create a trigger that when the last employee of the dept is deleted from emp table, the dept is deleted from the dept table.
emp(empno, ename, deptno)
dept(deptno, dname)
First, I created a procedure that deletes the dept from dept table given a deptno.
CREATE OR REPLACE PROCEDURE del_dept
(v_dno in number)
is
begin
delete from DEPT where deptno = v_dno;
end;
Then I created a trigger that deletes the dept when the last emp in that dept is deleted. I tried to test the trigger by deleting one of the three emps in deptno10, but I got error mesg from command that trigger is invalid and failed re-validation.
create or replace trigger del_dept
after delete on EMP
for each row
DECLARE
emp_count Number;
g_dno Number;
begin
SELECT COUNT(:old.ename) INTO emp_count FROM emp group by deptno;
FOR i IN 1.. emp_count LOOP
IF i = emp_count THEN
del_dept(g_dno);
end if;
END LOOP;
End;
Error trigger is invalid and failed re-validation specifies that yor trigger was created with compilation error hence you were not able to test it. This is not a good idea to write a trigger in your case. I can see few issues in you code. So lets first resolve these issues.
When you write the code below, your trigger would be compiled and would be a valid one. So you will not get the error trigger is invalid and failed re-validation
CREATE OR REPLACE TRIGGER del_dept
AFTER DELETE
ON EMP
FOR EACH ROW
DECLARE
EMP_CNT NUMBER;
BEGIN
SELECT COUNT (1)
INTO emp_cnt
FROM emp
WHERE deptno = :old.deptno;
IF emp_cnt = 0
THEN
---del_dept is your procedure to delete records from dept table
del_dept (:old.deptno);
END IF;
END;
But when you would try to execute it you will further get the error:
ORA-04091: table EMP is mutating, trigger/function may not see it
ORA-06512: at "DEL_DEPT", line 4 ORA-04088: error during execution of
trigger 'DEL_DEPT'
The reason for getting this error is you are trying to select from the table from which you are deleting records and thats not allowed in oracle.
The best way for your case is to write a procedure which would delete the records once the last employee data is deleted from your dept table . See below:
CREATE OR REPLACE PROCEDURE del_dept (dept_no NUMBER)
IS
EMP_CNT NUMBER;
BEGIN
SELECT COUNT (1)
INTO emp_cnt
FROM emp
WHERE deptno = dept_no;
IF emp_cnt = 0
THEN
del_dept (dept_no);
END IF;
END;

oracle plsql procedure dynamic count of the tables in cursor loop

I want to update all the tables having ABC column.Need to skip the tables which doesn't have data.I am having problem in checking the count of the table in a cursor loop.
PLSQL code
create or replace procedure testp is
CURSOR c_testp
IS
SELECT table_name,
column_name
FROM all_tab_columns
WHERE column_name IN('ABC')
ORDER BY table_name;
c int;
BEGIN
FOR table_rec IN c_testp
LOOP
BEGIN
SELECT COUNT(*)
INTO c
FROM table_rec.table_name;
IF(c>0) THEN
query := 'update '||table_rec.table_name||' set '||table_rec.column_name ||'= xyz';
EXECUTE IMMEDIATE query;
COMMIT;
END IF;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('data not found');
WHEN OTHERS THEN
dbms_output.put_line('others');
END;
END LOOP;
END;
In your code, use this:
EXECUTE IMMEDIATE 'SELECT count(*) FROM ' || table_rec.table_name INTO c;
instead of this:
SELECT COUNT(*)
INTO c
FROM table_rec.table_name;
However, as mentioned in comments - there is actually no need to perform that condition check, as no update will be performed when table is empty.

How can drop table if table exists in oracle?

I am trying to create database by my java application using my generated schema file. In schema I have included drop query also. But I want to do some improvements for DROP QUERY. So I want to check the existence of db objects before running drop query and drop only when if it exists.
I googled for it and found some oracle link, Some link suggest following syntax and some mentioned that ORACLE does not support such syntax.
SYNTAX A:
IF EXISTS DROP TABLE TABLE_NAME
SYNTAX B:
DROP [TEMPORARY] TABLE [IF EXISTS]
tbl_name [, tbl_name] ...
[RESTRICT | CASCADE]
I also tried following queries:-
IF EXISTS (SELECT * FROM dba_objects WHERE OBJECT_NAME = 'BBB' )
DROP TABLE [BBB]
but it was giving error:-
Error starting at line 2 in command:
DROP TABLE [BBB]
Go
Error report:
SQL Error: ORA-00903: invalid table name
00903. 00000 - "invalid table name"
*Cause:
*Action:
Error starting at line 1 in command:
IF EXISTS (SELECT * FROM dba_objects WHERE OBJECT_NAME = 'BBB' ) DROP TABLE [BBB]
Error report:
Unknown Command
I refered following links:-
https://community.oracle.com/thread/2421779?tstart=0
Please suggest me if there any other queries to drop table with condition if table exists.
Drop table with no check. If any error exists you'll never know when something went wrong.
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE my_table';
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
Or you can search in Oracle dictionary.
DECLARE
l_cnt NUMBER;
BEGIN
SELECT count(*)
INTO l_cnt
FROM user_tables
WHERE table_name = 'MY_TABLE';
IF l_cnt = 1 THEN
EXECUTE IMMEDIATE 'DROP TABLE my_table';
END IF;
END;
If you run following code you do not have to check if table exists and in case of errors (table is locked with now wait or any other you will know about it)
begin
for c1 in (select owner,table_name from dba_tables where table_name='MY_TABLE') loop
execute immediate 'drop table '||c1.owner||'.'||c1.table_name||'';
end loop;
end;
Try this : It will drop table 'table_name' if it is present .
declare
a varchar2(700) ;
begin
execute immediate ' SELECT CASE WHEN tab = 1
THEN ''DROP TABLE TABLE_NAME''
ELSE ''select 1 from dual''
END
FROM ( SELECT sum(case when table_name = ''TABLE_NAME'' then 1 else 0 end ) as tab FROM user_tables)' into a;
EXECUTE IMMEDIATE a;
end;

In pl/sql how can I execute a select statement stored in CLOB type of field?

In Oracle DB, I have a large select staetment with lots of joins and cases that is stored in a CLOB field in one of my tables.
How can i execute this statement from the CLOB?
Look into the EXECUTE IMMEDIATE syntax.
Example table:
CREATE TABLE test(id number, largedata clob);
INSERT INTO test VALUES (1, 'select name from v$database');
commit;
select * from test;
DECLARE
l_sql clob;
l_result VARCHAR2(50);
BEGIN
SELECT LARGEDATA INTO l_sql FROM TEST;
EXECUTE IMMEDIATE l_sql INTO l_result;
dbms_output.put_line(l_result);
END;
/
Output is the DB name.

Resources