Generate script SQL to insert comment on tables and columns - sql

I have an Oracle 12 database with a schema with 50+ tables and 500+ columns without comments/documentation. I need to generate documentation for the whole schema and I've to comment all tables and columns. Is there an easy way to generate an SQL script pre-compiled with all statements, for example:
comment on table EMPLOYE IS '';
comment on column EMPLOYE.EMPLOYE_ID IS '';
Or, I'm unlucky and I need to create every single entry myself?

You could use the table from the Oracle data dictionary and build a simple script. E.g., for comments on the table...
select 'comment on table ' || table_anme || ' is ' || ''
from dba_tables
where owner='schema_name'
and use the proper table (i.e., DBA_TAB_COLS) for columns too.

Related

Redshift: Executing a dynamic query from a string

I would like to execute a dynamic SQL query stored in a string field on Amazon Redshift.
My background is mostly T-SQL relational databases. I used to build SQL statements dynamically, store them into variables and them execute them. I know Redshift can prepare and execute statements, but I wonder if it is possible to execute a query stored in a string field.
I have a piece of code that dynamically builds the code below with stats on several tables using pg_* system tables. Every column/table name is dynamically calculated. Here's an example of the query output:
SELECT h_article_id AS key, 'transport_parameters_weight_in_grams' AS col_name, COUNT(DISTINCT transport_parameters_weight_in_grams) AS count_value FROM dv.s_products GROUP BY h_article_id UNION ALL
SELECT h_article_id AS key, 'transport_parameters_width_in_mm' AS col_name, COUNT(DISTINCT transport_parameters_width_in_mm) AS count_value FROM dv.s_products GROUP BY h_article_id UNION ALL
SELECT h_article_id AS key, 'label_owner_info_communication_address' AS col_name, COUNT(DISTINCT label_owner_info_communication_address) AS count_value FROM dv.s_products GROUP BY h_article_id
I would like to input this dynamic piece of code within another query, so I can make some statistics, like so:
SELECT col_name, AVG(count_value*1.00) AS avg_count
FROM (
'QUERY ABOVE'
) A
GROUP BY col_name;
This would ouput something like:
col_name avg_count
transport_parameters_weight_in_grams 1.00
transport_parameters_width_in_mm 1.00
label_owner_info_communication_address 0.60
The natural way for me to do this would be to store everything as a string in a variable and execute it. But I'm afraid Redshift does not support this.
Is there an alternative way to really build dynamic SQL code?
This is possible now that we have added support for Stored Procedures. "Overview of Stored Procedures in Amazon Redshift"
For example, this stored procedure counts the rows in a table and inserts the table name and row count into another table. Both table names are provided as input.
CREATE PROCEDURE get_tbl_count(IN source_tbl VARCHAR, IN count_tbl VARCHAR) AS $$
BEGIN
EXECUTE 'INSERT INTO ' || quote_ident(count_tbl)
|| ' SELECT ''' || source_tbl ||''', COUNT(*) FROM '
|| quote_ident(source_tbl) || ';'
RETURN;
END;
$$ LANGUAGE plpgsql;
In your example the query to executed could be passed in as a string.
No. There is not a straightforward way to run dynamic built SQL code in Redshift.
You can't define SQL variables, or create stored procedures, as you would have in MS SQL Server.
You can create Python Functions in Redshift, but you would be coding in Python vs. SQL.
You can use the "PREPARE" and "EXECUTE" statements to run "pre-defined" SQL queries, but you would have to create the statements outside of the database, before passing them to the execute command. By creating the statement outside of the database, in a way defeats the purpose.... You can create any statement in your "favorite" programming language.
As I said, this SQL based, in-database dynamic SQL does not exist.
Basically, you need to run this logic in your application or using something such as AWS Data Pipeline.
I am using Postgre on Redshift, and I ran into this issue and found a solution.
I was trying to create a dynamic query, putting in my own date.
date = dt.date(2018, 10, 30)
query = ''' select * from table where date >= ''' + str(my_date) + ''' order by date '''
But, the query entirely ignores the condition when typing it this way.
However, if you use the percent sign (%), you can insert the date correctly.
The correct way to write the above statement is:
query = ''' select * from table where date >= ''' + ''' '%s' ''' % my_date + ''' order by date '''
So, maybe this is helpful, or maybe it is not. I hope it helps at least one person in my situation!
Best wishes.

Getting creation-SQL of a table in HP Vertica using a query

I am using HP Vertica db engine. There are some tables created in the database. I have a requirement wherein I need to get the create-table script of a table given the table name by querying over a system-table or a stored-proc or otherwise. Any help in reaching this need is highly appreciated. Thanks.
The easiest way to get the table definition for a table is by using EXPORT_TABLES(). This function allows multiple objects for the scope.
You can script the export statement and execute it inside a script, such as:
SELECT 'SELECT EXPORT_TABLES('''', ''' || table_schema || '.' || table_name || ''');' FROM v_catalog.tables;
Alternatively, you can roll up to the schema level using:
SELECT EXPORT_TABLES('', 'schema');
The difference being that EXPORT_TABLES will not produce definition for any projections associated with the table. If you need the projection with the table definition, use EXPORT_OBJECTS.

Programmatically create a new table from anothers (Postgres)

I have 32 tables with the exactly the same schema (i.e. same columns names, etc.) in a PostgreSQL 9.1 data base, and I want to create a new table from them (so I can unify the queries).
I know that I can use a INSERT SELECT technique, table by table, but I was wondering if its a better way of do that. Maybe a for loop?
Thanks in advance
Maybe something like this should work, if your tables really have the same column names and types:
SELECT 'INSERT INTO myschema.mynewtable SELECT * FROM ' || table_schema || '.' || table_name || ';'
FROM information_schema.tables
WHERE table_schema='myschema' AND table_name LIKE 'old%';
This will output the INSERT statements you can then execute to insert the data from the old tables. It would be possible to automatically execute them using a PL/SQL procedure. But if you need to do that just once, I think it's easier to execute them manually.

SQL/JDBC : select query on variable tablenames

I'm using Oracle DB and I would like to write a SQL query that I could then call with JDBC. I'm not very familiar with SQL so if someone can help me, that could be great ! Here is the problem. I have a table MY_TABLE wich contains a list of another tables, and I would like to keep only the nonempty tables and those that their names start by a particular string.
The query I wrote is the following :
select TABLE_NAME
from MY_TABLE
where TABLE_NAME like '%myString%'
and (select count(*) from TABLE_NAME where rownum=1)<>0
order by TABLE_NAME;`
The problem comes from the second SELECT, but I don't know how can I do to use the TABLE_NAME value.
Does someone have an idea ?
Thanks.
[Added from comments]
Actually, I need to test the V$ views contained in the ALL_CATALOG table. But if I can find another table where all these views are contained too and with a NUM_ROWS column too, it would be perfect !
Standard versions of SQL do not allow you to replace 'structural elements' of the query, such as table name or column name, with variable values or place-holders.
There are a few ways to approach this.
Generate a separate SQL statement for each table name listed in MY_TABLE, and execute each in turn. Brute force, but effective.
Interrogate the system catalog directly.
Investigate whether there are JDBC metadata operations that allow you to find out about the number of rows in a table without being tied to the system catalog of the specific DBMS you are using.
Can you use oracle view USER_TABLES? then query will be much easier
select TABLE_NAME
from USER_TABLES
where TABLE_NAME like '%myString%'
and Num_ROWS > 0
order by TABLE_NAME;`

Copy many tables in MySQL

I want to copy many tables with similar names but different prefixes. I want the tables with the wp_ prefix to go into their corresponding tables with the shop_ prefix.
In other words, I want to do something like this:
insert into shop_wpsc_*
select * from wp_wpsc_*
How would you do this?
SQL doesn't allow wildcarding table names - the only way to do this is to loop through a list of tables (via the ANSI INFORMATION_SCHEMA/INFORMATION_SCHEMAS) while using dynamic SQL.
Dynamic SQL is different for every database vendor...
Update
MySQL? Why didn't you say so in the first place...
MySQL's dynamic SQL is called "Prepared Statements" - this is my fav link for it besides the documentation. There're numerous questions on SO about operations on all the tables in a MySQL database - just need to tweak the WHERE clause to get the table names you want.
You'll want to do this from within a MySQL stored procedure...
You can do this by combining multiple statements into a single prepared statement -- try doing this:
SELECT #sql_text := GROUP_CONCAT(
CONCAT('insert into shop_wpsc_',
SUBSTRING(table_name, 9),
' select * from ', table_name, ';'), ' ')
FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema = 'example'
AND table_name LIKE 'wp_wpsc_%';
PREPARE stmt FROM #sql_text;
EXECUTE stmt;
Expanding on OMG Ponies' answer a bit, you can use the data dictionary and write a SQL to write the SQL's. For example, in Oracle, you could do something like this:
SELECT 'insert into shop_wpsc_' || SUBSTR(table_name,9) || ' select * from ' || table_name || ';'
FROM all_tables
WHERE table_name LIKE 'WP_SPSC%'
This will generate a series of SQL statements you can run as a single script. Like OMG Ponies' pointed out though, the syntax will vary depending on what DB vendor you are using (e.g. all_tables is Oracle specific).
First I would select all tables from the catalog views (the name of those may depend on your dmbs, though if they are ansi compatible they should support INFORMATION_SCHEMA) that start with wp_wpsc_.
(For instance for DB2:
SELECT NAME FROM TABLES WHERE NAME LIKE 'wp_wpsc_%'
)
Then iterate through that result set, and create a dynamic statement in the form you have given to read from the current table and insert into the corresponding new one.