Check if table exists in the database - PL SQL - oracle

I'm new in PL SQL, and I need to check if table exist on server and drop it.
Thanks in advance,
Goran

you can query the tablenames
select tname from tab where tname = 'TABLE_NAME_TO_SEARCH_FOR';

select tname from tab where tname = 'TABLE_NAME';

This is where the true power of the information schema comes in.
A simple query will point you in the right direction
SELECT
*
FROM
information_schema.tables
WHERE
table_name='salesorders';
This can then be used in plpg function
CREATE OR REPLACE FUNCTION table_exists(v_table text)
RETURNS boolean AS
$BODY$
DECLARE
v_count int;
v_sql text;
BEGIN
v_sql =
'SELECT ' ||
' count(1) ' ||
'FROM ' ||
' information_schema.tables ' ||
'WHERE ' ||
E' table_name=\'' || v_table || E'\'';
EXECUTE v_sql INTO v_count;
RETURN v_count>0;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE
COST 100;
Use the function
select * from table_exists('salesordesrs');
That should be enough to get you going.
OOPS
Seems I misread the original posters question. I've answered for PostgreSQL.
Peter.

The most efficient method is, don't. Just drop the table. If the table didn't exist already, it'll raise an exception.
Running a query just before dropping the table is just wasting time doing what Oracle will do automatically for you.
You can handle the exception however you want, e.g.:
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE "MYTABLE"';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_OUTPUT.put_line('the table did not exist!');
ELSE
RAISE;
END IF;
END;

I had some troubles with the solutions above, as my DB has a peculiar tree structure. This should give every table in your schema:
SELECT
table_name
FROM
all_tables
WHERE
table_name = '<your table here>'

Related

Oracle query logic to identify email addresses across the dwh schemas

I was performing an activity to identify eMail addresses based on certain pattern (#xyz.de). I initially tried checking the DBA_TAB_COLS [data dictionary] view but this just finds email column names and I manually need to check the big list of tables. Instead of doing that, is there is a more effective way to just fetch the the pattern value #xyz.de ?
Database - oracle 11g
Query used
SET SERVEROUTPUT ON 100000
DECLARE
lv_count number(10):=0;
l_str varchar2 (1000);
lv_col_name varchar2(255) :='EMAIL';
BEGIN
FOR V1 IN
(select distinct table_name
from dba_tab_columns
where column_name = lv_col_name
order by table_name)
LOOP
dbms_output.put_line(lv_col_name||' '||v1.table_name);
END LOOP;
END;
Please note that
I don't exactly know the table or column names.
The value #xyz.de can be in any schema and any table and any column. This has to be identified but in an effective way.
Any suggestions?
i have used the above block query to fetch the email column along with the table name , but how can i achieve by searching certain value #xyz.de using the dynamic sql ?
I don't know what you want to do with the values that you are trying to extract, so the below code just prints them. Refer to PL/SQL Dynamic SQL from the Oracle documentation.
declare
type EMAILS is ref cursor;
L_CURSOR EMAILS;
cursor EMAIL_COLS is
select OWNER
,TABLE_NAME
,COLUMN_NAME
from DBA_TAB_COLS
where COLUMN_NAME like '%EMAIL%'
and OWNER <> 'SYS';
L_SQL varchar2(200);
L_EMAIL varchar2(500);
begin
for REC in EMAIL_COLS
loop
L_SQL := 'select ' || REC.COLUMN_NAME || ' from ' || REC.OWNER || '.' || REC.TABLE_NAME || ' where ' || REC.COLUMN_NAME || ' like ''%xyz.de''';
open L_CURSOR for L_SQL;
loop
fetch L_CURSOR into L_EMAIL;
exit when L_CURSOR%notfound;
DBMS_OUTPUT.PUT_LINE(L_EMAIL);
end loop;
end loop;
end;

When does user_tab_columns get updated?

In another question I tried to create a hist table, which keeps a log from the given table. With the answers in that question, I tried to create something new.
Since it is not possible to create a system trigger on tables or views, I created a DDL trigger like this:
create or replace trigger ident_hist_trig after alter on schema
declare
v_table varchar2(30);
begin
select upper(ora_dict_obj_name) into v_table from dual;
if (v_table = 'Z_IDENT') then
prc_create_hist_tabel('z_ident_hist', 'z_ident');
elsif (v_table = 'D_IDENT') then
prc_create_hist_tabel('d_ident_hist', 'd_ident');
elsif (v_table = 'X_IDENT') then
prc_create_hist_tabel('x_ident_hist', 'x_ident');
else
null;
end if;
end;
/
The procedure prc_create_hist_tabel looks like this:
create or replace procedure prc_create_hist_tabel(p_naam_hist_tabel in varchar2, p_naam_tabel in varchar2) is
cursor c is
select 'alter table ' || p_naam_hist_tabel || ' add ' || column_name || ' ' || data_type || case when data_type = 'DATE' then null else '(' || data_length || ')' end lijn
from user_tab_columns
where TABLE_NAME = upper(p_naam_tabel)
and column_name not in (select column_name from user_tab_columns where table_name = upper(p_naam_hist_tabel));
v_dummy number(1);
cursor trig is
select column_name || ',' kolom, ':old.' || column_name || ',' old
from user_tab_columns
where table_name = upper(p_naam_tabel);
v_trigger_sql varchar2(32767);
begin
begin
select 1 into v_dummy
from user_tab_columns
where TABLE_NAME = upper(p_naam_hist_tabel)
group by 1;
exception when no_data_found then
execute immediate 'create table ' || p_naam_hist_tabel || ' (wijziger varchar2(60) default user, wijzigdatum date default sysdate, constraint pk_' || p_naam_hist_tabel || ' primary key (wijziger, wijzigdatum))';
end;
dbms_output.put_line('BBB');
for i in c
loop
begin
dbms_output.put_line(i.lijn);
execute immediate i.lijn;
exception when others then
dbms_output.put_line(i.lijn);
end;
end loop;
v_trigger_sql := 'create or replace trigger ' || p_naam_tabel || '_hist_trig after update on ' || p_naam_tabel || ' for each row begin insert into ' || p_naam_hist_tabel || ' (';
for v_lijn in trig
loop
v_trigger_sql := v_trigger_sql || v_lijn.kolom;
end loop;
v_trigger_sql := substr(v_trigger_sql, 1, length(v_trigger_sql) - 1);
v_trigger_sql := v_trigger_sql || ') values (';
for v_lijn in trig
loop
v_trigger_sql := v_trigger_sql || v_lijn.old;
end loop;
v_trigger_sql := substr(v_trigger_sql, 1, length(v_trigger_sql) - 1);
v_trigger_sql := v_trigger_sql || '); end;';
execute immediate v_trigger_sql;
end;
/
In short what that function does, is maintain the history table. If it doesn't exist, it will create one, and if it exists, it will add the new columns to it. The procedure also creates a new trigger which will write the old values into the history table after update.
But when I alter one of the tables x_ident, z_ident or d_ident, the cursor c will return nothing (I can check that with the print when I loop through it). Although when execute the select after I altered my table, then I do get results.
The results I get from altering the table d_ident are these:
BBB
d_ident: Table altered.
But I guess it should be the other way around, I think that the procedure prc_create_hist_tabel is executed before the alter table actually goes off, and I guess I should get something like this:
d_ident: Table altered.
BBB
Any help would be apreciated. I tried to create a trigger on insert on user_tab_columns, but that gave me ORA-25001: cannot create this trigger type on views.
I tried with a sleep command as well, but that didn't work either.
This won't work. Even if you were able to get the column that is being added to the table in your trigger, if you tried to actually do DDL in a trigger, you'd get an error that DDL isn't allowed in a trigger.
I'd expect that the right way to approach this would be to make the call to prc_create_hist_tabel as part of your promotion scripts. Reasonable systems don't add columns to tables willy-nilly. The DDL is part of a promotion that exists in source control and gets deployed after testing. If your promotion scripts failed to modify the history table, you'd find out during testing that you missed a step and the change would never go to production. Having changes happen automatically means that they're not in change control which makes it more difficult to do a build from change control.
If you are determined to do this automatically, your trigger would need to submit a job, realistically using dbms_job not the newer dbms_scheduler, that calls the procedure. That job would run after the transaction the DDL trigger is a part of committed. At that point, the column would be visible in dba_tab_columns. And your job is free to do DDL.

Find a Value in Table Using SQL Developer

I inherited a large database and nobody seems to know which table/column a particular data set is coming from. I've spent a lot of time going through table by table in Oracle's SQL Developer, but I can't find it. Is there a way in SQLDeveloper to search the entire table for a single value. Something like:
select table_name from all_tab_columns where column_value='desired value';
The db has around 1K+ tables each with lots of columns so manually combing through this isn't working.
You can use the following script to search for a value in all columns of your schema. The execution time for the script will depend on the number of tables in your schema and the number of rows in each of your table.
Replace 'abc' with the value which you intend to search. Also, right now the script will search all VARCHAR2 columns. You can also insert the table names and counts into a table instead of doing a DBMS_OUTPUT.PUT_LINE.
DECLARE
CURSOR cur_tables
IS
SELECT table_name,
column_name
FROM user_tab_columns
WHERE data_type = 'VARCHAR2';
v_sql VARCHAR2(4000);
v_value VARCHAR2(50);
v_count NUMBER;
BEGIN
v_value := 'abc';
FOR c_tables IN cur_tables LOOP
v_sql := 'SELECT count(1) FROM ' || c_tables.table_name || ' WHERE ' || c_tables.column_name || ' = :val' ;
EXECUTE IMMEDIATE v_sql INTO v_count USING v_value;
IF v_count > 0 THEN
DBMS_OUTPUT.PUT_LINE('Table Name ' || c_tables.table_name || ' Column Name ' || c_tables.column_name || ' Row Count ' || v_count);
END IF;
END LOOP;
END;

Drop Schema in Oracle: SQL Error: No more data to read from socket

I'm trying to drop a schema in oracle 11g on our dev environment and I get back SQL Error: No more data to read from socket. There is no load on the schema as it's just a dev db. It's a small db without anything crazy going on. I see this error all the time. Restarting the instance sometimes resolves the problem. I can't seem to find any information that would point to a solution. Thanks!
I understand that this message often arises due to a bug. Also, when it appears an entry in your alert log and/or a trace file will contain more detail on what the error might actually be. To find your trace file for the session run:
select U_DUMP.value
|| '/'
|| DB_NAME.value
|| '_ora_'
|| V$PROCESS.SPID
|| nvl2(V$PROCESS.TRACEID, '_' || V$PROCESS.TRACEID, null)
|| '.trc'
"Trace File"
from V$PARAMETER U_DUMP
cross join V$PARAMETER DB_NAME
cross join V$PROCESS
join V$SESSION
on V$PROCESS.ADDR = V$SESSION.PADDR
where U_DUMP.NAME = 'user_dump_dest'
and DB_NAME.NAME = 'db_name'
and v$session.audsid=sys_context('userenv','sessionid');
A dba at my company gave me this one. It's
CREATE OR REPLACE PROCEDURE "SYS"."DROP_SCHEMA_FAST" (pSchema IN
VARCHAR2)
IS
cnt NUMBER(5) := 0;
sql1 varchar2(4000);
x PLS_INTEGER;
--disable constraints:
cursor cur1 is select 'alter table ' || OWNER ||'.'||table_name||' disable constraint '||constraint_name sql2
from all_constraints where owner=pSchema and status='ENABLED'
and table_name not like 'BIN$%' and constraint_name not like 'SYS_%' and constraint_name not like '%PK%';
cursor cur2 is select 'alter table ' || OWNER ||'.'||table_name||' disable constraint '||constraint_name sql2
from all_constraints where owner=pSchema and status='ENABLED'
and table_name not like 'BIN$%' and constraint_name not like 'SYS_%';
--truncate all tables:
cursor cur3 is select 'truncate table ' || OWNER ||'.'||table_name sql2 from all_tables where owner=pSchema
and table_name not like 'BIN$%';
BEGIN
SELECT COUNT(*) INTO cnt FROM dba_users WHERE UPPER(username) = UPPER(pSchema);
IF (cnt <= 0) THEN
RETURN;
END IF;
sql1 := 'ALTER USER ' || UPPER(pSchema) || ' ACCOUNT LOCK';
EXECUTE IMMEDIATE sql1;
--disable constraints:
FOR ao_rec IN cur1 LOOP
EXECUTE IMMEDIATE ao_rec.sql2;
END LOOP;
FOR ao_rec IN cur2 LOOP
EXECUTE IMMEDIATE ao_rec.sql2;
END LOOP;
--truncate all tables:
FOR ao_rec IN cur3 LOOP
EXECUTE IMMEDIATE ao_rec.sql2;
END LOOP;
--drop schema:
sql1 := 'DROP USER ' || UPPER(pSchema) || ' CASCADE';
EXECUTE IMMEDIATE sql1;
exception when others then null;
END;
Also had this problem, got fixed by setting "PLScope identifiers:" to "None" in Tools->Preferences ->Database->PL/SQL Compiler

Oracle - determining whether a table exists

How do you determine in oracle whether a table exists?
On a script file, I wanted to delete a table only if it exists.
Thanks!
http://www.dba-oracle.com/bk_check_table_exists.htm
There are various solutions given here. The simplest ones:
SQL> desc mytable
Or just try to drop and catch the exception:
begin
execute immediate 'drop table TABLE1';
exception when others then null;
end;
Oracle has an all_tables table, you could query that to see.
Maybe something like this:
declare
v_tab_count number := 0;
begin
select count(*)
into v_tab_count
from all_tables
where table_name = 'MY_TABLE';
if v_tab_count > 0 then
execute immediate 'drop table my_table';
else
dbms_output.put_line('The table isn''t there! maybe you deleted it already?');
end if;
exception
when others then
dbms_output.put_line( sqlerrm);
end if;
/
I know I commented earlier on someone else's post that I didn't like using execute immediate for this, but I'd forgotten that it's the only way to perform a drop table from PL/SQL.
You can query USER_TABLES for TABLE_NAME = 'YOUR_TABLE_NAME' :-)

Resources