SQL check if table exist and truncate - sql

I'm trying to code a statement that checks if a table exist and if it does to truncate/delete it. If it doesn't exist, to print the message 'This table does not exist!'
This is what I've come up so far but doesn't seem to work.
BEGIN
TRUNCATE TABLE PPA_P6_2018;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_OUTPUT.put_line('This table does not exist!');
ELSE
RAISE;
DBMS_OUTPUT.put_line('This table has been delted!');
END IF;
END;

Create a custom exception to catch when the table does not exist and then only catch that single exception (rather than catching all of them with OTHERS) and then use EXECUTE IMMEDIATE to truncate/drop the table:
DECLARE
table_name VARCHAR2(30) := 'PPA_P6_2018';
table_not_exists EXCEPTION;
PRAGMA EXCEPTION_INIT( table_not_exists, -942 );
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || table_name;
EXECUTE IMMEDIATE 'DROP TABLE ' || table_name;
DBMS_OUTPUT.put_line('This table has been deleted!');
EXCEPTION
WHEN table_not_exists THEN
DBMS_OUTPUT.put_line('This table does not exist!');
END;
/
db<>fiddle

TRUNCATE TABLE is DDL so cannot be run directly within PL/SQL. You need to use EXECUTE IMMEDIATE:
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE PPA_P6_2018';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_OUTPUT.put_line('This table does not exist!');
ELSE
RAISE;
DBMS_OUTPUT.put_line('This table has been delted!');
END IF;
END;
Note: You will never see the message 'This table has been delted!' since the RAISE before it throws you out of the block! And if you got an error, the table hasn't been deleted anyway!

DECLARE
v_count NUMBER;
v_table_name VARCHAR2 (100) := 'YOURTABLE';
v_sqlstr VARCHAR2 (1000);
BEGIN
SELECT COUNT ( * )
INTO v_count
FROM user_tables
WHERE table_name = v_table_name;
IF v_count > 0
THEN
v_sqlstr := 'DELETE FROM ' || v_table_name;
EXECUTE IMMEDIATE v_sqlstr;
DBMS_OUTPUT.put_line (
'TABLE ' || v_table_name || ' HAS BEEN DELETED!');
ELSE
DBMS_OUTPUT.put_line ('TABLE ' || v_table_name || ' DOES NOT EXIST!');
END IF;
END;

Related

Check if first column is populated but all other columns are null Teradata

Please what is the effective way for getting the rows where the first column (primary index) is populated but all other columns are null? The table has 25 columns and I want to avoid putting all column names in the WHERE clause.
Thanks.
One of many methods (this will give you a generated SQL to run, but you can amend the code just to get its results through insert select, for instance)
create table test_table_2000 ( charcol1 varchar(2000) );
replace procedure sp_find_blank_rows( in_database varchar(50), in_tablename varchar(50) )
begin
declare
l_sql varchar(2000);
declare
l_int integer;
set l_sql = 'select * from '||in_database||'.'||in_tablename||' where 1=1 ';
FOR fReq AS cReq CURSOR FOR
select * from Dbc.Columns where databaseName=in_database and TableName=in_tablename order by ColumnId
DO
IF l_int is null THEN
SET l_sql = l_sql || ' and ' || fReq.ColumnName || ' is not null ';
ELSE
SET l_sql = l_sql || ' and ' || fReq.ColumnName || ' is null ';
END IF;
set l_int = 1;
END FOR;
insert into test_table_2000 values ( l_sql );
end;
call sp_find_blank_rows('<your_database>','<your_table>');

Oracle databases loop tables

I have an oracle database and I am running the below query
select table_name
from db_test.test
where table_name like '%20170128'
This returns me a column with all the tables with the specific date at the end.
How can I take this list and query them?
You'd need dynamic SQL. If you're running a simple query against each table (I'm just doing a count(*) in this example), something like this would work
declare
l_cnt integer;
l_sql varchar2(1000);
begin
for t in (select table_name
from db_test.test
where table_name like '%20170128')
loop
l_sql := 'select count(*) from ' || t.table_name;
execute immediate l_sql
into l_cnt;
dbms_output.put_line( t.table_name || ' has ' || l_cnt || ' rows.' );
end loop;
end;

Reason for Sql command not ended properly error

When I execute the following code I get , sql command not ended properly.
I'm using this to find matching column for a string.
DECLARE
match_count INTEGER;
BEGIN
FOR t IN (SELECT table_name, column_name FROM all_tab_cols where owner=v_owner and data_type = v_data_type) LOOP
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM '||t.table_name||' WHERE lower('||t.column_name||') like :1'
INTO match_count
USING 'XRWJ01';
IF match_count > 0 THEN
dbms_output.put_line( t.table_name ||' '||t.column_name||' '||match_count );
END IF;
END LOOP;
END;
/
Debug your code... if you get an error print the statement erroring out. I made some minor changes to your pl/sql block. Replace v_owner and v_datatype with your values to run it.
set serveroutput on size 999999
clear screen
DECLARE
match_count INTEGER;
v_owner VARCHAR2(30);
v_data_type VARCHAR2(30);
v_stmt VARCHAR2(1024);
BEGIN
v_owner := 'SCOTT';
v_data_type := 'NUMBER';
FOR t IN (SELECT table_name, column_name FROM all_tab_cols where owner=v_owner and data_type = v_data_type) LOOP
v_stmt := 'SELECT COUNT(*) FROM "'||t.table_name||'" WHERE "'||t.column_name||'" like :1';
BEGIN
EXECUTE IMMEDIATE
v_stmt
INTO match_count
USING 'XRWJ01';
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line( 'Error in statement: '|| v_stmt );
dbms_output.put_line ( DBMS_UTILITY.FORMAT_ERROR_STACK() );
dbms_output.put_line ( DBMS_UTILITY.FORMAT_ERROR_BACKTRACE() );
END;
IF match_count > 0 THEN
dbms_output.put_line( t.table_name ||' '||t.column_name||' '||match_count );
END IF;
END LOOP;
END;
/
I ran the statement locally and it errored out because of LOWER('||t.column_name||'). You select the columns from a data dictionary - those are the column names. If you do a LOWER then you might have different values if the tables/columns are created with case. Solution is to not do LOWER and put double quotes around them.

Dynamic loop in PL/SQL

I am currently looping through values in PL/SQL with the following:
for c in (select * from example_table where name is not null) loop
-- logic
end loop;
I would like to replace the SQL statement with a dynamic one, for example:
l_sql := 'select * from example_table where || l_col || is not null';
for c in (l_sql) loop
-- logic
end loop;
Is this possible?
Best regards
That's not possible with an implicit cursor loop ( select inside for loop ). You may use the conventional OPEN .. FETCH .. LOOP through a REFCURSOR with a record variable of tablename%ROWTYPE
DECLARE
t_rec example_table%ROWTYPE;
l_sql VARCHAR2(1000);
v_cur SYS_REFCURSOR;
l_col varchar2(32) := 'MY_COLUMN';
BEGIN
l_sql := 'select * from example_table where '|| l_col || ' is not null';
OPEN v_cur FOR l_sql;
LOOP
FETCH v_cur INTO t_rec; --fetch a row
EXIT WHEN v_cur%NOTFOUND;
-- your logic using t_rec columns.
END LOOP;
CLOSE v_cur;
END;
/

How to delete all data in Oracle Database with SQL?

I had created a lot of tables and users while testing some SQL command and now I dont remember exactly all the tables and user's name.
But now I want to delete all of it for my big project.So is it possible to delete it in SQL command line ?
This PL/SQL block will be useful to delete all the data in oracle data base
BEGIN
FOR cur_rec IN (SELECT object_name, object_type
FROM user_objects
WHERE object_type IN
('TABLE',
'VIEW',
'PACKAGE',
'PROCEDURE',
'FUNCTION',
'SEQUENCE',
'SYNONYM',
'PACKAGE BODY'
))
LOOP
BEGIN
IF cur_rec.object_type = 'TABLE'
THEN
EXECUTE IMMEDIATE 'DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '" CASCADE CONSTRAINTS';
ELSE
EXECUTE IMMEDIATE 'DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '"';
END IF;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ( 'FAILED: DROP '
|| cur_rec.object_type
|| ' "'
|| cur_rec.object_name
|| '"'
);
END;
END LOOP;
END;
/
execute this command:
BEGIN
FOR table_ IN (SELECT * FROM dba_tables where owner like 'YOUR_SCHEMA') LOOP
execute immediate 'truncate table ' || table_.owner || '.' || table_.table_name ||' cascade';
END LOOP;
END;
/
BEGIN
FOR T in (SELECT table_name FROM user_tables) LOOP
EXECUTE IMMEDIATE 'ALTER TABLE '||T.table_name||' DISABLE ALL CONSTRAINTS';
--This will disable all the constraint
END LOOP;
FOR T in (SELECT table_name FROM user_tables) LOOP
EXECUTE IMMEDIATE 'TRUNCATE TABLE '||T.table_name;
END LOOP;
FOR T in (SELECT table_name FROM user_tables) LOOP
EXECUTE IMMEDIATE 'ALTER TABLE '||T.table_name||' ENABLE ALL CONSTRAINTS';
END LOOP;
END;
Alter table ... disable all constraints throws a ORA-01735: invalid ALTER TABLE option if there is no constraint defined for the table, which would cause the script to fail to truncate every table if there is at least one table without constraint. You might want to place the execute immediate within a begin -exception block
You have two ways:
you can use function delete instead truncate for this function you should not disable constraints, but it work more slowly because you can rollback this operation if you will go this way:
BEGIN
FOR table_ IN (SELECT * FROM dba_tables where owner like 'YOUR_SCHEMA') LOOP
execute immediate 'delete from table ' || table_.owner || '.' || table_.table_name;
END LOOP;
END;
use truncate it is more faster, but you must diable constraints on table:
begin
for disable_constraint_ in
(select * from dba_constraints where owner= 'YOUR_SCHEMA'
)
loop
execute immediate 'alter table ' || disable_constraint_.owner || '.' || disable_constraint_.table_name ||' disable constraint '|| disable_constraint_.constraint_name;
end loop;
for table_ in (select * from dba_tables where owner = 'YOUR_SCHEMA')
loop
execute immediate 'truncate table ' || table_.owner || '.' ||table_.table_name ||' cascade';
end loop;
for enable_constaint_ in (select * from dba_constraints where owner= 'YOUR_SCHEMA')
loop
execute immediate 'alter table ' || enable_constaint_.owner || '.' || enable_constaint_.table_name ||' enable constraint '|| enable_constaint_.constraint_name;
end loop;
end;