truncate script tables in schema does not work - sql

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...

Related

Get DDL of all tables under schema in one database in Snowflake

Can anyone tell me a query to DDL of all tables under schema in database.
I know how to get a DDL of a table.
select get_ddl('table', 'ods.users');
It gives us only one table DDL. But in my I have around 40 tables.
I want to get all tables DDL at a time instead of getting one by one. Is there any query available. If so please guide me.
Regards,
Kathija.
GET_DDL can script entire schema(with all objects inside):
select get_ddl('SCHEMA', 'ods');
select get_ddl('SCHEMA', 'ods', true); -- to get qualified names
With Snowflake Scripting block it is possible to list over tables/views/functions/... only:
DECLARE
CUR CURSOR FOR SELECT CONCAT_WS('.',TABLE_CATALOG,TABLE_SCHEMA,TABLE_NAME) AS name
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_SCHEMA ILIKE 'ODS';
BEGIN
CREATE OR REPLACE TEMPORARY TABLE temp_view_defs(view_name TEXT, definition TEXT);
FOR rec IN CUR DO
EXECUTE IMMEDIATE REPLACE('INSERT INTO temp_view_defs(view_name, definition)
SELECT ''<view_name>'', GET_DDL(''TABLE'', ''<view_name>'')'
,'<view_name>'
,rec.name);
END FOR;
LET rs RESULTSET := (SELECT * FROM temp_view_defs);
RETURN TABLE(rs);
END;
For sample:
CREATE SCHEMA ODS;
CREATE TABLE ODS.TAB1(i INT);
CREATE TABLE ODS.TAB2(id INT DEFAULT 0) COMMENT = 'Test';
Output:

An equivalence of ".schema sqlite_master" in Oracle

I'm trying to do the same exercise for both SQLite and Oracle. In SQLite, there is a table sqlite_master containing a description of all of the other tables, indexes, triggers, and views that are contained within the database. I can see the query to generate sqlite_master with .schema sqlite_master.
In Oracle, the data dictionary is presented to us in the form of a number of views (DBA, ALL or USER). Let's take the table USER_TABLES as an example. We can do query on USER_TABLES, for example
SELECT table_name
FROM USER_TABLES;
Is there anyway to get the query used to create the table USER_TABLES in Oracle? I tried
SELECT dbms_metadata.get_ddl('TABLE', 'USER_TABLES')
FROM dual;
but it does not work.
I am not sure what are you looking for but if you want the definition of any table in oracle you can use :
Describe TableName
Or if you want to have list of tables, views or columns you can use below queries:
For Tables :
select * from select * from all_tables
For Columns :
select * from all_tab_columns
For Views :
select * from select * from all_views
To get all the column information of a table:
select *
from all_tab_columns
where upper(table_name) = upper('Test')
order by column_id
Typically oracle stores table_name in uppercase so I used upper() or you can just type 'TEST'
You could use this one:
DECLARE
DDL CLOB;
BEGIN
FOR aTab IN (SELECT TABLE_NAME FROM USER_TABLES) LOOP
DDL := DBMS_METADATA.GET_DDL('TABLE', aTab.TABLE_NAME);
DBMS_OUTPUT.PUT_LINE(DDL);
END LOOP;
END;
You may customize the output with DBMS_METADATA.SET_TRANSFORM_PARAM() before you run the query.

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.

Rename mixed-case tables in a single query

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.