Rename mixed-case tables in a single query - sql

In my PostgreSQL 9.2 database there are many tables having name with mixed cases,For example
Tbl_Sales,Tbl_Purch,Tbl_logMnth
What I want to do is
alter table "Table1" rename to table1
but how to rename all mixed-case tables in my database in an easy way ?

this is the query to use
ALTER TABLE name
RENAME TO new_name

Use the following select to get the table(s) with mixed-cases in name
SELECT table_name ucase,lower(table_name) lcase
FROM information_schema.tables
where table_type = 'BASE TABLE' and
table_schema = 'public' and
table_name ~ E'^[[:upper:]][^[:upper:]]'
PostgreSQL string function lower and information_schema.tables
and use PL/PGSQL SQL - DO to rename all tables that have mixed-case
do
$$
declare
rw record;
begin
for rw in
SELECT 'ALTER TABLE "'||t.ucase||'" RENAME to '||t.lcase||';' execme from (
SELECT table_name ucase, lower(table_name) lcase
FROM information_schema.tables
where table_type = 'BASE TABLE' and
table_schema = 'public' and
table_name ~ E'^[[:upper:]][^[:upper:]]')t
loop
execute rw.execme ;
end loop;
end;
$$

Your best bet would probably be to generate a series of dynamic SQL statements, in, say, Python or similar by querying the pg_tables catalog.
You could then iterate over that list for the schemas in which you're interested (or all of them if you want to do that, so long as they're user-created -- you should avoid any of the pg_ ones, among others, as those are managed by Postgres itself) and check to see if the lowercase name is the same as the current name. If they are different, you can then generate the ALTER TABLE statement needed to rename the table, and then execute it, making sure to COMMIT your changes.
sqlfiddle with an example of this.
Note how the foo table I created is listed in there.
I'd recommend white-listing by schema, say, public and any others you want. In the fiddle, for example, you wouldn't want to touch anything in the pg_catalog nor information_schema schemas. You could also filter by tableowner -- you would probably want to avoid, for example, anything owned by the postgres user.
Also, note that when creating tables, casing doesn't matter. If a table foo already exists, and I then try to create Foo, the error ERROR: relation "foo" already exists will result.

Related

Oracle SQL only drop a column if a table exists

For Microsoft SQL Server I have following statement to only drop a column if the table exist.
IF EXISTS(SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TEST_TABLE')
ALTER TABLE TEST_TABLE DROP COLUMN LEGACY_VALUE
GO
I was wondering if there was a related IF-EXISTS mechanism is present in Oracle.
All the metadata about the columns in Oracle Database is accessible using one of the following views.
user_tab_cols; -- For all tables owned by the user
all_tab_cols ; -- For all tables accessible to the user
dba_tab_cols; -- For all tables in the Database.
So, if you are looking for a column that exists and want to drop it, your code may look something like this ( see below).
Since this appears to be a one time task, is the effort really worth it?
DECLARE
v_column_exists number := 0;
BEGIN
Select count(*) into v_column_exists
from user_tab_cols
where upper(column_name) = 'LEGACY_VALUE''
and upper(table_name) = 'TEST_TABLE';
--and owner = 'SCOTT --*might be required if you are using all/dba views
if (v_column_exists = 1) then
execute immediate 'alter table test_table drop column legacy_value';
end if;
end;
/

How to delete every table in a specific schema in postgres?

How do I delete all the tables I have in a specific schema? Only the tables in the schema should be deleted.
I already have all the table names that I fetched with the code below, but how do delete all those tables?
The following is some psycopg2 code, and below that is the SQL generated
writeCon.execute("SELECT table_name FROM information_schema.tables WHERE table_schema='mySchema'")
SELECT table_name FROM information_schema.tables WHERE table_schema='mySchema'
You can use an anonymous code block for that.
WARNING: This code is playing with DROP TABLE statements, and they are really mean if you make a mistake ;) The CASCADE option drops all depending objects as well. Use it with care!
DO $$
DECLARE
row record;
BEGIN
FOR row IN SELECT * FROM pg_tables WHERE schemaname = 'mySchema'
LOOP
EXECUTE 'DROP TABLE mySchema.' || quote_ident(row.tablename) || ' CASCADE';
END LOOP;
END;
$$;
In case you want to drop everything in your schema, including wrappers, sequences, etc., consider dropping the schema itself and creating it again:
DROP SCHEMA mySchema CASCADE;
CREATE SCHEMA mySchema;
For a single-line command, you can use psql and its \gexec functionality:
SELECT format('DROP TABLE %I.%I', table_schema, table_name)
FROM information_schema.tables
WHERE table_schema= 'mySchema';\gexec
That will run the query and execute each result string as SQL command.

Drop all tables in a Redshift schema - without dropping permissions

I would be interested to drop all tables in a Redshift schema. Even though this solution works
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
is NOT good for me since that it drops SCHEMA permissions as well.
A solution like
DO $$ DECLARE
r RECORD;
BEGIN
-- if the schema you operate on is not "current", you will want to
-- replace current_schema() in query with 'schematodeletetablesfrom'
-- *and* update the generate 'DROP...' accordingly.
FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = current_schema()) LOOP
EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE';
END LOOP;
END $$;
as reported in this thread How can I drop all the tables in a PostgreSQL database?
would be ideal. Unfortunately it doesn't work on Redshift (apparently there is no support for for loops).
Is there any other solution to achieve it?
Run this SQL and copy+paste the result on your SQL client.
If you want to do it programmatically you need to built little bit code around it.
SELECT 'DROP TABLE IF EXISTS ' || tablename || ' CASCADE;'
FROM pg_tables
WHERE schemaname = '<your_schema>'
I solved it through a procedure that deletes all records. Using this technique to truncate fails but deleting it works fine for my intents and purposes.
create or replace procedure sp_truncate_dwh() as $$
DECLARE
tables RECORD;
BEGIN
FOR tables in SELECT tablename
FROM pg_tables
WHERE schemaname = 'dwh'
order by tablename
LOOP
EXECUTE 'delete from dwh.' || quote_ident(tables.tablename) ;
END LOOP;
RETURN;
END;
$$ LANGUAGE plpgsql;
--call sp_truncate_dwh()
In addition to demircioglu's answer, I had to add Commit after every drop statement to drop all tables in my schema. SELECT 'DROP TABLE IF EXISTS ' || tablename || ' CASCADE; COMMIT;' FROM pg_tables WHERE schemaname = '<your_schema>'
P.S.: I do not have required reputation to add this note as a comment and had to add as an answer.
Using Python and pyscopg2 locally on my PC I came up with this script to delete all tables in schema:
import psycopg2
schema = "schema_to_be_deleted"
try:
conn = psycopg2.connect("dbname='{}' port='{}' host='{}' user='{}' password='{}'".format("DB_NAME", "DB_PORT", "DB_HOST", "DB_USER", "DB_PWD"))
cursor = conn.cursor()
cursor.execute("SELECT tablename FROM pg_tables WHERE schemaname = '%s'" % schema)
rows = cursor.fetchall()
for row in rows:
cursor.execute("DROP TABLE {}.{}".format(schema, row[0]))
cursor.close()
conn.commit()
except psycopg2.DatabaseError as error:
logger.error(error)
finally:
if conn is not None:
conn.close()
Replace correctly values for DB_NAME, DB_PORT, DB_HOST, DB_USER and DB_PWD to connect to the Redshift DB
The following recipe differs from other answers in the regard that it generates one SQL statement for all tables we're going to delete.
SELECT
'DROP TABLE ' ||
LISTAGG("table", ', ') ||
';'
FROM
svv_table_info
WHERE
"table" LIKE 'staging_%';
Example result:
DROP TABLE staging_077815128468462e9de8ca6fec22f284, staging_abc, staging_123;
As in other answers, you will need to copy the generated SQL and execute it separately.
References
|| operator concatenates strings
LISTAGG function concatenates every table name into a string with a separator
The table svv_table_info is used because LISTAGG doesn't want to work with pg_tables for me. Complaint:
One or more of the used functions must be applied on at least one user created tables. Examples of user table only functions are LISTAGG, MEDIAN, PERCENTILE_CONT, etc
UPD. I just now noticed that SVV_TABLE_INFO page says:
The SVV_TABLE_INFO view doesn't return any information for empty tables.
...which means empty tables will not be in the list returned by this query. I usually delete transient tables to save disk space, so this does not bother me much; but in general this factor should be considered.

truncate script tables in schema does not work

I am looking for a solution. I am trying to truncate all the tables in my postgres database:
I am using a simple SQL script
SELECT 'TRUNCATE ' || table_name || ';'
FROM information_schema.tables WHERE table_schema='sda' AND table_type='BASE TABLE';
unfortunately it does not work because many relations do not exist.
please help. ( i am using postgresql 9.2)
prepare:
t=# create schema sda;
CREATE SCHEMA
t=# create table sda."BASE TABLE"();
CREATE TABLE
try:
t=# SELECT format('TRUNCATE %I;',table_name)
FROM information_schema.tables WHERE table_schema='sda' AND table_type = 'BASE TABLE';
format
------------------------
TRUNCATE "BASE TABLE";
(1 row)
t=# TRUNCATE "BASE TABLE";
TRUNCATE TABLE
so I assume you just did not treat table a identifier, like:
t=# TRUNCATE BASE TABLE;
ERROR: syntax error at or near "TABLE"
LINE 1: TRUNCATE BASE TABLE;
also - upper case with space in name often leads to human errors, better use standard no case names...

Clear a big number of tables with template names fast and easy

I have about 30 tables in Oracle. Names of the tables have some template format, for example:
DF_D_AUTO, DF_D_PERSON
and so on. So the first part of a table name is always
DF_D_
I would like to clear all these tables. Of course I can clear them manually one by one.
However I would like to know may be someone knows a good fast way using SQL to clear all such tables in one scope.
You can run a loop on all such tables
BEGIN
for table_names in (select table_name from dba_tables where table_name like 'DF\_D\_%' escape '\')
loop
EXECUTE immediate 'truncate table ' || table_names.table_name;
end loop;
END;
DBA_TABLES - reference
Difference between dba_tables, user_tables, all_tables - reference