Need to add to srting in postgresql select query result - sql

i have a bundle of tables in my database. I need to truncate all the tables but not some.
so by using table_schema i can get list of table names!
select ''as "truncate", table_name
from information_schema.tables
where table_schema = 'public'
Expected output.
truncate table table_name restart identity.
some one tell me is there any better way to do that.

Use format() with placeholders for the schema and table name to make sure the names are quoted properly:
To properly deal with the foreign keys used by the tables, it would also be better to add the cascade option to the truncate command:
select format('truncate table %I.%I restart identity cascade;', table_schema, table_name) as stmt
from information_schema.tables
where table_schema = 'public';
Another option would be to truncate all tables in a single statement:
select concat('truncate table ', string_agg(format('%I.%I', table_schema, table_name), ', '), ' restart identity;') as stmt
from information_schema.tables
where table_schema = 'public'

You can concat strings in Postgres using ||
select 'truncate table' || table_name::text || ' restart identity'
from information_schema.tables
where table_schema = 'public
Take a look at 9.4. String Functions and Operators

Related

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.

Sum all numeric columns in database and log results

I have a query which gives me all numeric columns in my Postgres database:
SELECT table_schema, table_name, column_name
FROM information_schema.columns
WHERE table_schema in (
'datawarehouse_x',
'datawarehouse_y',
'datawarehouse_z',
'datawarehouse_w'
)
and udt_name not in
('date','timestamp','bool','varchar')
and column_name not like '%_id'
This gives me, what I need:
table_schema table_name column_name
schema_1 table_x column_z
schema_2 table_y column_w
I checked it and it's fine.
What I do now want to do is, to query all these columns for each table as a select sum(column) and then insert this schema_name, table_name, query_result and the current date into a log table on a daily basis.
Writing the results into a target table shouldn't be a big deal, but how in the world can I run queries according to the results of this query?
Thanks in advance.
EDIT: What I will write afterwards would be a procedure, which takes these schema/table/column as input, then queries the table and writes into the log-table. I just do not know the part in-between. This is kind of what I would be doing then, but I don't know yet which types I should use for schema, table and column.
create or replace function sandbox.daily_routine_metrics(schema_name regnamespace, table_name regclass, column_name varchar)
returns void
language plpgsql
as $$
BEGIN
EXECUTE
'INSERT INTO LOGGING.DAILY_ROUTINE_SIZE
SELECT
'|| QUOTE_LITERAL(schema_name) ||' schema_name,' ||
QUOTE_LITERAL(table_name) ||' table_name, ' ||
QUOTE_LITERAL(column_name) ||' column_name, ' ||
'current_timestamp, sum(' || QUOTE_LITERAL(column_name) || ')
FROM ' || QUOTE_LITERAL(schema_name) ||'.'|| QUOTE_LITERAL(table_name);
END;
$$;
The feature you need is known as "dynamic SQL". It's an RDBMS-specific implementation; the documents for Postgres are here.
Whilst it's possible to achieve what you want in dynamic SQL, you might find it easier to use a scripting language like Python or Ruby to achieve this. Dynamic SQL is hard to code and debug - you find yourself concatenating lots of hardcoded strings with results from SQL queries, printing them to the console to see if they work, and realizing all sorts of edge cases blow up.

Renaming multiple columns in PostgreSQL

My table has a bunch of columns in the following format:
_settingA
_settingB
_settingB
And I want to rename them simply to add a prefix as follows:
_1_settingA
_1_settingB
_1_settingC
I have a lot more than three columns to rename in this way. If I had just three, I'd just do it manually one by one.
What is the quickest / most efficient way to achieve this?
There's no single command aproach. Obviously you could type multiple comands for RENAME by your self, but let me intoduce some improvement:) As I said in this answer
...for all such bulk-admin-operations you could use PostgreSQL system tables to generate queries for you instead of writing them by hand
In your case it would be:
SELECT
'ALTER TABLE ' || tab_name || ' RENAME COLUMN '
|| quote_ident(column_name) || ' TO '
|| quote_ident( '_1' || column_name) || ';'
FROM (
SELECT
quote_ident(table_schema) || '.' || quote_ident(table_name) as tab_name,
column_name
FROM information_schema.columns
WHERE
table_schema = 'schema_name'
AND table_name = 'table_name'
AND column_name LIKE '\_%'
) sub;
That'll give you set of strings which are SQL commands like:
ALTER TABLE schema_name.table_name RENAME COLUMN "_settingA" TO "_1_settingA";
ALTER TABLE schema_name.table_name RENAME COLUMN "_settingB" TO "_1_settingB";
...
There no need using table_schema in WHERE clause if your table is in public schema. Also remember using function quote_ident() -- read my original answer for more explanation.
Edit:
I've change my query so now it works for all columns with name begining with underscore _. Because underscore is special character in SQL pattern matching, we must escape it (using \) to acctually find it.
Something simple like this will work.
SELECT FORMAT(
'ALTER TABLE %I.%I.%I RENAME %I TO %I;',
table_catalog,
table_schema,
table_name,
column_name,
'_PREFIX_' + column_name
)
FROM information_schema.columns
WHERE table_name = 'foo';
%I will do quote_ident, which is substantially nicer. If you're in PSQL you can run it with \gexec
You can use the following function :
(I use this to add prefix on tables wiches have more than 50 columns)
First create the function :
CREATE OR REPLACE FUNCTION rename_cols( schema_name_ text,table_name_ text, prefix varchar(4))
RETURNS bool AS
$BODY$
DECLARE
rec_selection record;
BEGIN
FOR rec_selection IN (
SELECT column_name FROM information_schema.columns WHERE table_schema = schema_name_ AND table_name = table_name_) LOOP
EXECUTE 'ALTER TABLE '||schema_name_||'.'||table_name_||' RENAME COLUMN "'|| rec_selection.column_name ||'" TO "'||prefix|| rec_selection.column_name ||'" ;';
END LOOP;
RETURN True;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Then execute function :
SELECT rename_cols('public','test','d');
Hope it will be usefull,
You can't do that.
All the actions except RENAME and SET SCHEMA can be combined into a list of multiple alterations to apply in parallel.
most efficient way is using ActiveRecord.

Get Columns Names of Table

How I can Get for a specific Table its columns Names ?
I tried this :
SELECT column_name
FROM USER_TAB_COLUMNS
WHERE table_name = 'x' ;
But it doesn't work.
Try this :
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TABLENAME'
Hope this helps.
EDIT :
The Oracle equivalent for information_schema.COLUMNS is USER_TAB_COLS for tables owned by the current user, ALL_TAB_COLS or DBA_TAB_COLS for tables owned by all users.
Tablespace is not equivalent to a schema, neither do you have to provide the tablespace name.
Providing the schema/username would be of use if you want to query ALL_TAB_COLS or DBA_TAB_COLS for columns OF tables owned by a specific user. in your case, I'd imagine the query would look something like:
String sqlStr= "
SELECT column_name
FROM all_tab_cols
WHERE table_name = 'users'
AND owner = ' || +_db+ || '
AND column_name NOT IN ( 'password', 'version', 'id' )
"
Note that with this approach, you risk SQL injection.
Source : Oracle query to fetch column names
String comparisons in Oracle are case sensitive by default, and table and column names are upper case by default, so you need to make sure that the capitalization of the table name you are searching for matches the the way it's stored in the database, so unless your table was named with mixed case or all lower case try making sure your string is all upper case.
SELECT column_name from USER_TAB_COLUMNS
WHERE table_name = 'X'; -- not 'x'
Additionally, if you don't own the table, then you need to use either ALL_TAB_COLUMNS or DBA_TAB_COLUMNS instead of USER_TAB_COLUMNS since USER_TAB_COLUMNS only lists details for tables owned by your current schema.
You can just describe the table:
desc x;
Try to queryUSER_TAB_COLUMNS view
SELECT column_name
FROM USER_TAB_COLUMNS
WHERE table_name = 'TABLE_NAME'

How to extract table definitions using SQL or Toad

Can somebody tell me how to extract my table definitions using SQL? I want to extract the datatypes of all my tables and other information from my Oracle schema. I have about 100 tables.
I need the complete documentation of my Oracle Schema. My schema name IS "cco".
Can I do this by SQL?
I am using Toad for Data analyst 3.3. Please let me know if this tool helps.
You can try this -
select * from all_tab_cols
where owner = 'CCO';
To get the DDL for all tables of the current user, you can use this:
select dbms_metadata.get_ddl('TABLE', table_name)
from user_tables;
You will need to adjust your SQL client to be able to properly display the content of a CLOB column.
More details (e.g. about how to get the DDL for other objects) can be found in the manual: http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_metada.htm
you can use the table:USER_TAB_COLUMNS
Find below query example
select
table_name,
column_name,
data_type,
data_length,
data_precision,
nullable
from USER_TAB_COLUMNS
where table_name = '<table_name>';
This is only an example you can also do a select * to get more information.
you can also use the table: all_tab_columns
For a better display you can use:
select table_name,column_name, data_type||
case
when data_precision is not null and nvl(data_scale,0)>0 then '('||data_precision||','||data_scale||')'
when data_precision is not null and nvl(data_scale,0)=0 then '('||data_precision||')'
when data_precision is null and data_scale is not null then '(*,'||data_scale||')'
when char_length>0 then '('||char_length|| case char_used
when 'B' then ' Byte'
when 'C' then ' Char'
else null
end||')'
end||decode(nullable, 'N', ' NOT NULL') as data_type
from user_tab_columns
where table_name = '<TABLE_NAME>';