In order to retrieve information about columns, e.g: their name, ordinal position, datatype, etc, I use the following query
SELECT *
FROM information_schema.`COLUMNS`
WHERE TABLE_SCHEMA = 'myDbName'
AND TABLE_NAME = 'myTable'
This returns all the information I need except information about which columns are PK and FK, especially FKs. I noticed that one of the columns returned by that query is COLUMN_KEY. For PKs, this column suffices because it has a value of PRI, but for FKs, this column either has a MUL or nothing. Is there a way to retrieve information about columns that includes key information reliably?
I don't need to know details about the PK or FK, I just want to get information about the columns AND to know if they are PK or FK.
This should give you an overview of columns, keys and FK constraints. I've arranged the keys to distinguish between those that reference another table and those that don't, which is somewhat against the natural order of the underlying views. You can add or remove columns to suit your requirement but you will get to a level of detail where you might as well just run show create table table_name.
N.B., this should work in mysql > 5.7.6 , if you are using an earlier version then you'll need to remove generation_expression from the SELECT.
SELECT c.`ordinal_position` AS '#',
c.`column_name` AS 'Name',
c.`column_type` AS 'Type',
c.`is_nullable` AS 'Allow NULL',
IFNULL(c.`column_default`,'') AS 'Default',
CONCAT(c.`extra`, ' ',c.`generation_expression`) AS 'Extra',
IFNULL((SELECT GROUP_CONCAT(CONCAT(IF(s.`non_unique` = 0 ,'*',''),s.`index_name`, '(', s.`seq_in_index`,')'))
FROM `information_schema`.`statistics` s
WHERE s.`table_schema` = c.`table_schema`
AND s.`table_name` = c.`table_name`
AND s.`column_name` = c.`column_name`
),'') as 'Key name(pos) *=unique',
IFNULL((SELECT GROUP_CONCAT(
CONCAT(k.`constraint_name`, ': ', k.`referenced_table_name`,' (', k.`referenced_column_name`,')'))
FROM `information_schema`.`key_column_usage` k
WHERE k.`table_schema` = c.`table_schema`
AND k.`table_name` = c.`table_name`
AND k.`column_name` = c.`column_name`
AND k.`referenced_table_name` IS NOT NULL
),'') AS 'FK name: table(column)'
FROM `information_schema`.`columns` c
WHERE c.`table_schema` = 'dbname'
AND c.`table_name` = 'table_name'
ORDER BY c.ordinal_position;
Assuming you're using INNODB for your tables, you can find out if a key is foreign key or primary key using the below script
SELECT * FROM information_schema.TABLE_CONSTRAINTS
WHERE information_schema.TABLE_CONSTRAINTS.CONSTRAINT_TYPE IN ('FOREIGN KEY', 'PRIMARY KEY')
AND information_schema.TABLE_CONSTRAINTS.TABLE_SCHEMA = 'myschema'
AND information_schema.TABLE_CONSTRAINTS.TABLE_NAME = 'mytable';
Related
I have here an SQL query that I got from this source. What it does is it finds all the primary keys and their references in the database.
select
concat(table_name, '.', column_name) as 'foreign key',
concat(referenced_table_name, '.', referenced_column_name) as 'references'
from
information_schema.key_column_usage
where
referenced_table_name is not null
and table_schema = 'my_database'
I modified it a little to become this
select
table_name as fk_table_name, column_name as 'foreign key',
referenced_table_name as ref_table_name, referenced_column_name as 'references'
from
information_schema.key_column_usage
inner join
information_schema.referenced_table_name
where
referenced_table_name is not null
and column_name = 'customer_number'
and referenced_table_name = 'accepted_orders'
Now it doesn't work. The error it returns is ' #1109 - Unknown table 'referenced_table_name' in information_schema'. My goal is instead of just displaying what the referenced column name is, it gives me all the values of that column instead.
So instead of telling me that the foreign key customer_number in accepted_orders references the primary key customer_number in customer_records, I want to get all the values of customer_number in customer_records instead.
I thought of using an inner join on the result of the query but apparently it won't let me. How do I do this? Do I have to use separate SQL statements?
You seem to be, as the error message says, using referenced_table_name in a context where the query parser wants a table name, not a column name. You wrote:
inner join
information_schema.referenced_table_name
That doesn't make any sense because you're trying to join to a column, not a table.
Try omitting the two lines above from your query.
How to find all the relations between all MySQL tables? If for example, I want to know the relation of tables in a database of having around 100 tables.
Is there anyway to know this?
The better way, programmatically speaking, is gathering data from INFORMATION_SCHEMA.KEY_COLUMN_USAGE table as follows:
SELECT
`TABLE_SCHEMA`, -- Foreign key schema
`TABLE_NAME`, -- Foreign key table
`COLUMN_NAME`, -- Foreign key column
`REFERENCED_TABLE_SCHEMA`, -- Origin key schema
`REFERENCED_TABLE_NAME`, -- Origin key table
`REFERENCED_COLUMN_NAME` -- Origin key column
FROM
`INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE` -- Will fail if user don't have privilege
WHERE
`TABLE_SCHEMA` = SCHEMA() -- Detect current schema in USE
AND `REFERENCED_TABLE_NAME` IS NOT NULL; -- Only tables with foreign keys
There are more columns info like ORDINAL_POSITION that could be useful depending your purpose.
More info: http://dev.mysql.com/doc/refman/5.1/en/key-column-usage-table.html
Try this:
select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS;
Try
SELECT
`TABLE_NAME`,
`COLUMN_NAME`,
`REFERENCED_TABLE_NAME`,
`REFERENCED_COLUMN_NAME`
FROM `information_schema`.`KEY_COLUMN_USAGE`
WHERE `CONSTRAINT_SCHEMA` = 'YOUR_DATABASE_NAME' AND
`REFERENCED_TABLE_SCHEMA` IS NOT NULL AND
`REFERENCED_TABLE_NAME` IS NOT NULL AND
`REFERENCED_COLUMN_NAME` IS NOT NULL
do not forget to replace YOUR_DATABASE_NAME with your database name!
A quick method of visualizing relationships in MySQL is reverse engineering the database with MySQL Workbench.
This can be done using the reverse engineering too, which will result in an entity-relationship diagram much like the following (though you may have to organize it yourself, once it is generated):
SELECT
count(1) totalrelationships ,
c.table_name tablename,
CONCAT(' ',GROUP_CONCAT(c.column_name ORDER BY ordinal_position SEPARATOR ', ')) columnname,
CONCAT(' ',GROUP_CONCAT(c.column_type ORDER BY ordinal_position SEPARATOR ', ')) columntype
FROM
information_schema.columns c RIGHT JOIN
(SELECT column_name , column_type FROM information_schema.columns WHERE
-- column_key in ('PRI','MUL') AND -- uncomment this line if you want to see relations only with indexes
table_schema = DATABASE() AND table_name = 'YourTableName') AS p
USING (column_name,column_type)
WHERE
c.table_schema = DATABASE()
-- AND c.table_name != 'YourTableName'
GROUP BY tablename
-- HAVING (locate(' YourColumnName',columnname) > 0) -- uncomment this line to search for specific column
ORDER BY totalrelationships desc, columnname
;
1) Go into your database:
use DATABASE;
2) Show all the tables:
show tables;
3) Look at each column of the table to gather what it does and what it's made of:
describe TABLENAME;
4) Describe is nice since you can figure out exactly what your table columns do, but if you would like an even closer look at the data itself:
select * from TABLENAME
If you have big tables, then each row usually has an id, in which case I like to do this to just get a few lines of data and not have the terminal overwhelmed:
select * from TABLENAME where id<5 - You can put any condition here you like.
This method give you more information than just doing select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS;, and it also provides you with more bite-sized information each time.
EDIT
As the comments suggested, the above WHERE id < 5 was a bad choice as a conditional placeholder. It is not a good idea to limit by ID number, especially since the id is usually not trustworthy to be sequential. Add LIMIT 5 at the end of the query instead.
Based on xudre's answer, you can execute the following to see all the relations of a schema:
SELECT
`TABLE_SCHEMA`, -- Foreign key schema
`TABLE_NAME`, -- Foreign key table
`COLUMN_NAME`, -- Foreign key column
`REFERENCED_TABLE_SCHEMA`, -- Origin key schema
`REFERENCED_TABLE_NAME`, -- Origin key table
`REFERENCED_COLUMN_NAME` -- Origin key column
FROM `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE`
WHERE `TABLE_SCHEMA` = 'YourSchema'
AND `REFERENCED_TABLE_NAME` IS NOT NULL -- Only tables with foreign keys
What I want in most cases is to know all FKs that point to a specific table. In this case I run:
SELECT
`TABLE_SCHEMA`, -- Foreign key schema
`TABLE_NAME`, -- Foreign key table
`COLUMN_NAME` -- Foreign key column
FROM `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE`
WHERE `TABLE_SCHEMA` = 'YourSchema'
AND `REFERENCED_TABLE_NAME` = 'YourTableName'
One option is : You can do reverse engineering to understand it in diagrammatic way.
When you install MySQL, you will get MySQLWorkbench. You need to open it and choose the database you want to reverse engineer. Click on Reverse Engineer option somewhere you find under the tools or Database menu. It will ask you to choose the tables. Either you select the tables you want to understand or choose the entire DB. It will generate a diagram with relationships.
you can use:
SHOW CREATE TABLE table_name;
I need to include the table name in a SELECT statement, together with some columns and the unique identifier of the table.
I don't know if there is possible to take the table name from a select within that table or some kind of unique identifier.
How can I achieve this?
I thank you for your responses but I fixed this in this way (it was too easy actually)
select 'table1' as tableName, col1, col2 from anyTable;
You will need to query the system catalog of the database to find the primary key and all unique constraints of the table, then choose one that best suites your needs. You can expect to find 0, 1, or more such constraints.
For an Oracle database you'd use something like
select
c.constraint_name,
col.column_name
from
dba_constrants c,
dba_cons_columns col
where
c.table_name = 'YOURTABLE'
and c.constraint_type in ('P', 'U')
and c.constraint_name = col.constraint_name
order by
c.constraint_name,
col.position
For MySQL you would query INFORMATION_SCHEMA.TABLE_CONSTRAINTS and INFORMATION_SCHEMA.KEY_COLUMN_USAGE views in a similar manner.
this will give you all the table names from your database, you can tweak it as you see fit
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'
What I need to do is retrieve the maximum primary key of all tables in my database at once? That is, my result will be like if I executed the below 2 queries:
SHOW TABLES FROM DATABASE_NAME
SELECT MAX(PRIMARY_KEY) AS maxId FROM TABLE
That is
(first column = TableName , second column = MAX(PK) Of that table)
Pardon if I am doing something wrong. I just do not want to write 80 queries because my database has 80 tables.
If (and only if) your primary keys are AUTO INCREMENT variables you can do this:
SELECT TABLE_NAME, AUTO_INCREMENT
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'mydb'
Please pay attention to the situation below when choosing the method of retrieving that info and what you are going to do with it:
AUTO_INCREMENT value is stored in memory, so after a server restart, AUTO_INCREMENT value is reset to:
SELECT MAX(ai_col) FROM table_name FOR UPDATE;
This can break things if the database has missing FKs and, for example, you delete some rows that refer to other tables. You would end up by reusing the same id.
Refer to: https://dev.mysql.com/doc/refman/5.7/en/innodb-auto-increment-handling.html#innodb-auto-increment-initialization
SELECT table_schema, table_name, column_name, data_type, extra
FROM `columns`
WHERE table_schema = 'mydb'
AND extra LIKE '%auto_increment%'
Optionally JOIN this with Alnitak's Answer.
I mean not mean by manually reading the output of show create table..., but by select ... so that the primary key name is output directly as the result?
The following query should give you the PKs - just plug in your table_schema and table_name at the bottom of the query.
SELECT k.`COLUMN_NAME`
FROM `information_schema`.`TABLE_CONSTRAINTS` t
JOIN `information_schema`.`KEY_COLUMN_USAGE` k
USING (`CONSTRAINT_NAME`, `TABLE_SCHEMA`, `TABLE_NAME`)
WHERE t.`CONSTRAINT_TYPE` = 'PRIMARY KEY'
AND t.`TABLE_SCHEMA` = 'dbName'
AND t.`TABLE_NAME` = 'tableName';
show index from CC_CSR_USER where Key_name = 'PRIMARY';
CC_CSR_USER is a table name. Have a look on the column_name field on the result, you will get that PRIMARY KEY column of the table.