PostgreSQL query for table column comments? - mysql

I have migrated a MySQL database to PostgreSQL & replaced the querySHOW FULL COLUMNS FROM schema_name.table_name; with a Postgres equivalent,
SELECT * FROM information_schema.columns WHERE table_schema = 'schema_name' and table_name = 'table_name'; which returns the columns along with their properties however the 'Comment' property that was returned in the MySQL query is not returned in the PostgreSQL query.
Is there a way to query for the comments associated with each column_name?

How about this:
select col_description((table_schema||'.'||table_name)::regclass::oid, ordinal_position) as column_comment
, * from information_schema.columns
WHERE table_schema = 'schema_name'
and table_name = 'table_name';

You know this is shown under \dt+ you can reverse engineer what psql does with -E
-E --echo-hidden Echo the actual queries generated by \d and other backslash commands. You can use this to study psql's internal operations. This is equivalent to setting the variable ECHO_HIDDEN to on.
psql -d test -E -c'\dt+ foo'
********* QUERY **********
SELECT n.nspname as "Schema",
c.relname as "Name",
CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as "Type",
pg_catalog.pg_get_userbyid(c.relowner) as "Owner",
pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as "Size",
pg_catalog.obj_description(c.oid, 'pg_class') as "Description"
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r','s','')
AND n.nspname !~ '^pg_toast'
AND c.relname ~ '^(foo)$'
AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY 1,2;
**************************
You can see here all the information that psql shows. As they say, teach the man to fish... ?

Related

SQL: Binding an undef (NULL) to the placeholder will not select rows which have a NULL value

I'm using perl 5.20 and MySQL 5.7, but I think the question is about SQL in general:
perldoc DBI says:
Binding an undef (NULL) to the placeholder will not select rows which have a NULL age! At least for database engines that conform to the SQL standard. Refer to the SQL manual for your database engine or any SQL book for the reasons for this. To explicitly select NULLs you have to say "WHERE age IS NULL".
I don't even know what to google for... My question is: What are the reasons behind = ? not matching a binding to NULL/undef? (Beyond "that is how it is defined and documented".)
I've discovered that MySQL has an operator <=> that allows comparisons with NULL and so:
my $sth = $dbh->prepare('select count(*) from table where field <=> ?');
$sth->execute(345);
$sth->execute(undef);
both work as expected. Unfortunately, the doc says:
The <=> operator is equivalent to the standard SQL IS NOT DISTINCT FROM operator.
And MySQL doesn't support the IS NOT DISTINCT FROM operator :-(. So there seems to be no portable way to do this. Except for the very hackish:
my $sth = $dbh->prepare('
select count(*) from table
where field = ? OR ( ? IS NULL AND field IS NULL )
');
$sth->execute(345, 345);
$sth->execute(undef, undef);
or the even more hackish snippet from perldoc DBI
$sql_clause = defined $age? "age = ?" : "age IS NULL";
$sth = $dbh->prepare(qq{
SELECT fullname FROM people WHERE $sql_clause
});
$sth->execute(defined $age ? $age : ());
Is there a portable way to do WHERE FIELD = ? and have it do what I mean also with NULLs/undefs? What did I miss?
EDIT: I also came up with this workaround, which especially works great if field is a numeric type such as an INT, so we're sure the string "NULL" is not a possible non-NULL value.
my $sth = $dbh->prepare('
select count(*) from table
where COALESCE(field, "NULL") = COALESCE(?,"NULL")
');
$sth->execute(345);
$sth->execute(undef);
But performance goes out the window, as I don't think any indexes can be used....
I understand that this is not exactly what you asked for but if you use DBIx::Class, the ORM will do that lifting for you.
my $res = $schema->resultset('table')->search({ field => [345, undef] });
print $res->count;
It will be translated to this SELECT COUNT( * ) FROM table me WHERE ( ( field = ? OR field IS NULL ) ): '345'

How to list tables used in a view with mysql

I need a list of tables being used in a view in mysql.
For example, if I have a view like:
SELECT * FROM table1
JOIN table2
ON table1.id = table2.id
I want to get: table1,table2
Unfortunately, I don't believe that's possible directly. Instead, you need to query and parse the actual view definition:
SELECT VIEW_DEFINITION
FROM INFORMATION_SCHEMA.VIEWS
WHERE
TABLE_NAME = ?;
.
mysql> CREATE VIEW vw_test AS
-> SELECT * FROM table1 JOIN table2 ON table1.id = table2.id;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS
-> WHERE TABLE_NAME = 'vw_test';
+------------------------------------------------------------------+
| VIEW_DEFINITION |
+------------------------------------------------------------------+
| select * from table1 join table2 on table1.id = table2.id; |
+------------------------------------------------------------------+
1 row in set (0.00 sec)
then you could use any of the following tools to parse the table names:
Terence Parr's ANTLR parser generator (Java, but can generate parsers in any one of a number of target languages) has several SQL grammars available, including a couple for PL/SQL, one for a SQL Server SELECT statement, one for mySQL, and one for ISO SQL - (http://www.antlr.org/grammar/list).
I took this from SO answer here: SQL parser library for Java - Retrieve the list of table names present in a SQL statement
Data Tools Project - SQL Development Tools (http://www.eclipse.org/datatools/project_sqldevtools/).
Here's the documentation for the SQL Query Parser (http://www.eclipse.org/datatools/project_sqldevtools/sqltools_doc/SQL%20Query%20Parser%20User%20documentation.htm).
Here's a blog with descriptions of how to "Get columns and tables in SQL script (Java version)" http://www.dpriver.com/blog/list-of-demos-illustrate-how-to-use-general-sql-parser/get-columns-and-tables-in-sql-script/
Or write yourself a custom mySQL proc based on the following (found here - http://www.sqlparser.com/fetch-table-column-name-example-extact-all-table-field-name.php):
SELECT c_mandant, hist_datum, parkey1, parkey2, funktionscode, ma_parkey, me_parkey
, CASE WHEN EXISTS (SELECT 1
FROM CDS_H_GRUPPE GRP1
WHERE GRP1.c_mandant = c_mandant
AND GRP1.hist_datum = ADD_MONTHS(LAST_DAY(TRUNC(SYSDATE)), -1)
AND GRP1.funktionscode = 'H'
AND GRP1.parkey1 = ma_parkey)
THEN 1
ELSE NULL
END MA_ME
, CASE WHEN EXISTS (SELECT 1
FROM CDS_H_GRUPPE GRP2
WHERE GRP2.c_mandant = c_mandant
AND GRP2.hist_datum = ADD_MONTHS(LAST_DAY(TRUNC(SYSDATE)), -1)
AND GRP2.funktionscode = 'U'
AND GRP2.parkey1 = me_parkey)
THEN 1
ELSE NULL
END ME_MA
, ROW_NUMBER() OVER (PARTITION BY c_mandant, ma_parkey, me_parkey ORDER BY c_mandant, ma_parkey, me_parkey) ANZ_MA
FROM (SELECT c_mandant, hist_datum, parkey1, parkey2, funktionscode
, CASE WHEN funktionscode = 'U'
THEN parkey1
ELSE parkey2
END MA_PARKEY
, CASE WHEN funktionscode = 'U'
THEN NULL
ELSE parkey1
END ME_PARKEY
FROM
CDS_H_GRUPPE
WHERE
funktionscode IN ('U', 'H')
AND hist_datum = ADD_MONTHS(LAST_DAY(TRUNC(SYSDATE)), -1)
)
this is what you want... this can get table used in Views and table which joined together.. but it can get one join... if want more add few more hint..
hope this would solve your question...
select
case
when view_definition regexp '.*from +.*'
then substring_index(substring_index(view_definition, 'from ', -1), ' ', 1)
end as 'primary table',
case
when view_definition regexp '.*join +.*'
then substring_index(substring_index(view_definition, 'join ', -1), ' ', 1)
end as 'joined table'
from information_schema.views where table_name="YOUR VIEW NAME" and table_schema="shotbot_production";
No that is not possible. You have to look for the definition of the view and get that done by yourself manually.

mysql case sensitive query for fieldnames

I would like the query to select only if there is a column named firstName. If the column is firstname then the query should not return anything.
SELECT firstName as currentName from tableNew WHERE id = $Id
I tried the code below but does not work
SELECT binary firstName as currentName from tableNew WHERE id = $Id
Can you please help?
On Unix, table names are case sensitive. On Windows, they are not.
Column, index, and stored routine names are not case sensitive on any
platform, nor are column aliases.
If you have access to INFORMATION_SCHEMA do this:
SELECT firstName as currentName from tableNew WHERE id = $Id AND (SELECT COUNT(TABLE_NAME)
FROM information_schema.COLUMNS
WHERE
TABLE_SCHEMA = 'mydbname'
AND TABLE_NAME = 'tableNew'
AND BINARY COLUMN_NAME = 'firstName') > 0;

How get the columnames from select query in MySQL?

Is it possible to get the column names using a query in MySQL? For example, I have a SELECT query:
SELECT name AS 'name', surname AS 'col1', last_name AS 'col2' FROM tb_people;
So, I want to get "Only with one SQL query" like:
Columns or alias of my query
--------
name
col1
col2
I try something similar to:
SHOW COLUMNS (SELECT name AS 'name', surname AS 'col1', last_name AS 'col2' FROM tb_people)
And with
DESCRIBE (SELECT name AS 'name', surname AS 'col1', last_name AS 'col2' FROM tb_people)
But these return SQL errors.
Why don't you do this in your application? MySql API in most languages provide functions to fetch all sorts of field information including name from the results returned by MySql. For example in PHP you can use mysql_fetch_field() on the results returned by mysql_query() to fetch field information.
This is how it is done in PHP, there must be equivalent functions in the language you are using:
$res = mysql_query( "SELECT name AS 'name', surname AS 'col1', last_name AS 'col2' FROM tb_people" );
for( $i = 0; $i < mysql_num_fields( $res ); ++$i ) {
$fieldInfo = mysql_fetch_field( $res, $i );
echo $fieldInfo[ 'name' ].'<br />';
}
results:
name
col1
col2
Hey I have used this successfully in the past, but I don't know if it compatible with all versions:
SELECT name FROM syscolumns
WHERE id = (SELECT id FROM sysobjects
WHERE name= 'MyTableName')
ORDER by colorder
If you installed MySQL server 5, you may get around this problem easily:
use information_schema
SELECT * FROM information_schema.`COLUMNS` C limit 5
WHERE table_name = 'your_table_name'
Cheers!

How to show all the tables from multiple databases

How to select all the tables from multiple databases in mySql..
I am doing the following steps but not able to achive the goal.
<?php
$a = "SHOW DATABASES";
$da = $wpdb->get_results($a);
foreach($da as $k){
echo '<pre>';
print_r ($k->Database);//prints all the available databases
echo '</pre>';
$nq = "USE $k->Database";//trying to select the individual database
$newda = $wpdb->get_results($nq);
$alld = "SELECT * FROM $k->Database";
$td = $wpdb->get_results($alld);
var_dump($td);//returns empty array
}
?>
Please Help me
Use the INFORMATION_SCHEMA:
select table_schema, table_name from information_schema.tables;
Even better:
Show all tables in all databases (except internal mysql databases) in one SQL statement.
SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema NOT IN ( 'information_schema', 'performance_schema', 'mysql' )
You cannot do
SELECT * FROM database
but you can do
USE DATEBASE;
SHOW TABLES;
or even better:
SHOW TABLES IN database
I would go for this this:
mysql -e "select table_schema, table_name from information_schema.tables;" | \
grep -Pv '^(sys|performance_schema|TABLE_SCHEMA|mysql|information_schema)' | \
perl -pe 's/\s+/./' | \
sort -u
mysql -e'select table_schema, table_name from information_schema.tables;'
This depends on you having a file ~/.my.cnf in place with the following contents:
[client]
user=ADMINUSER ## set user, usually 'root'
password=PASSWORD ## set password