I know of show tables and show columns from table TABLE_NAME which gets me the primary key (Key is PRI). But how do I get the primary key of a view or more specific the keys of the underlying tables? In that case show columns from VIEW_NAME all the Key values are empty.
A new INFORMATION_SCHEMA table exists to map views to the underlying table(s). It's called VIEW_TABLE_USAGE.
mysql> create table mytable (id serial primary key);
Query OK, 0 rows affected (0.01 sec)
mysql> create view v as select * from mytable;
Query OK, 0 rows affected (0.00 sec)
mysql> select table_schema, table_name, column_name, ordinal_position
from information_schema.view_table_usage
join information_schema.key_column_usage using (table_schema, table_name)
where table_name='mytable' and constraint_name='PRIMARY';
+--------------+------------+-------------+------------------+
| TABLE_SCHEMA | TABLE_NAME | COLUMN_NAME | ORDINAL_POSITION |
+--------------+------------+-------------+------------------+
| test2 | mytable | id | 1 |
+--------------+------------+-------------+------------------+
This table is new in MySQL 8.0.13.
If you use an older version of MySQL (or any version of MariaDB), there is no such information_schema table, so you can't get this information by any query. You would need to come up with a way to parse the view definition, which is a complex task because it could have a wide variety of SELECT syntax.
mysql> select view_definition from information_schema.views where table_name='v';
+--------------------------------------------------------------+
| VIEW_DEFINITION |
+--------------------------------------------------------------+
| select `test2`.`mytable`.`id` AS `id` from `test2`.`mytable` |
+--------------------------------------------------------------+
I have got two servers both running a MySQL instance. The first one, server1, is running MySQL 5.0.22. The other one, server2, is running MySQL 5.1.58.
When I create a memory table on server1 and I add a row its size is instantly 8,190.0 KiB.
When I create a memory table on server2 and I add a row its size is still only some bytes, though.
Is this caused by the difference in MySQL version or (hopefully) is this due to some setting I can change?
EDIT:
I haven't found the reason for this behaviour yet, but I did found a workaround. So, for future references, this is what fixed it for me:
All my memory tables are made once and are read-only from thereon. When you specify to MySQL the maximum number of rows your table will have, its size will shrink. The following query will do that for you.
ALTER TABLE table_name MAX_ROWS = N
Factor of 2?
OK, the problem likely is caused by the UTF-8 vs latin1
:- http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html
You can check the database connection, database default character set for both servers.
here is the testing I have just done :-
mysql> create table test ( name varchar(10) ) engine
-> =memory;
Query OK, 0 rows affected (0.03 sec)
mysql> show create table test;
+-------+------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------+
| test | CREATE TABLE `test` (
`name` varchar(10) DEFAULT NULL
) ENGINE=MEMORY DEFAULT CHARSET=latin1 |
+-------+------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> insert into test values ( 1 );
mysql> set names utf8;
Query OK, 0 rows affected (0.01 sec)
mysql> create table test2 ( name varchar(10) ) engine =memory default charset = utf8;
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
mysql> insert into test2 values ( convert(1 using utf8) );
Query OK, 1 row affected (0.01 sec)
mysql> select table_name, avg_row_length from information_schema.tables where TABLE_NAME in( 'test2', 'test');
+------------+----------------+
| table_name | avg_row_length |
+------------+----------------+
| test | 12 |
| test2 | 32 |
+------------+----------------+
2 rows in set (0.01 sec)
How can I add prefix to all tables in mysql using query.
For example:
I need to add "dr_" in all tables which are available in mysql database.
Run all queries that you get from running this query:
SELECT Concat('ALTER TABLE `', TABLE_NAME, '` RENAME TO `dr_', TABLE_NAME, '`;') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '<name of your db>';
For this example, I will create a database called prefixdb with 4 tables:
mysql> drop database if exists prefixdb;
Query OK, 4 rows affected (0.01 sec)
mysql> create database prefixdb;
Query OK, 1 row affected (0.00 sec)
mysql> use prefixdb
Database changed
mysql> create table tab1 (num int) ENGINE=MyISAM;
Query OK, 0 rows affected (0.05 sec)
mysql> create table tab2 like tab1;
Query OK, 0 rows affected (0.05 sec)
mysql> create table tab3 like tab1;
Query OK, 0 rows affected (0.05 sec)
mysql> create table tab4 like tab1;
Query OK, 0 rows affected (0.04 sec)
mysql> show tables;
+--------------------+
| Tables_in_prefixdb |
+--------------------+
| tab1 |
| tab2 |
| tab3 |
| tab4 |
+--------------------+
4 rows in set (0.00 sec)
The query to generate it would be
select
concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';')
from
(select table_schema db,table_name tb
from information_schema.tables where
table_schema='prefixdb') A,
(SELECT 'dr_' prfx) B
;
Running it at the command line I get this:
mysql> select concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';') from (select table_schema db,table_name tb from information_schema.tables where table_schema='prefixdb') A,(SELECT 'dr_' prfx) B;
+----------------------------------------------------------------+
| concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';') |
+----------------------------------------------------------------+
| alter table prefixdb.tab1 rename prefixdb.dr_tab1; |
| alter table prefixdb.tab2 rename prefixdb.dr_tab2; |
| alter table prefixdb.tab3 rename prefixdb.dr_tab3; |
| alter table prefixdb.tab4 rename prefixdb.dr_tab4; |
+----------------------------------------------------------------+
4 rows in set (0.00 sec)
Pass the result back into mysql like this:
mysql -hhostip -uuser -pass -AN -e"select concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';') from (select table_schema db,table_name tb from information_schema.tables where table_schema='prefixdb') A,(SELECT 'dr_' prfx) B" | mysql -hhostip -uuser -ppass -AN
With regard to your question if you want to rename all tables, do not touch information_schema and mysql databases. Use this query instead:
select
concat('alter table ',db,'.',tb,' rename ',db,'.',prfx,tb,';')
from
(select table_schema db,table_name tb
from information_schema.tables where
table_schema not in ('information_schema','mysql')) A,
(SELECT 'dr_' prfx) B
;
Give it a Try !!!
In case anyone runs into this error:
#1044 - Access denied for user 'user_name'#'localhost' to database 'information_schema'
After executing the queries resulting from the answer posted by #abhay, use the following instead to eliminate the issue:
SELECT Concat('RENAME TABLE `', TABLE_NAME, '` TO `dr_', TABLE_NAME, '`;') FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '<database_name>'
To add to Rolando's excellent and comprehensive answer. If you run the RENAME queries generated by his SELECT CONCAT query (I used phpMyAdmin and just copied the output queries into the SQL box and hit Go) then you shouldn't have any problems with foreign key constraints. I've just done this on a test database in XAMPP and all tables renamed ok, and the constraints remained intact. This may seem obvious to SQL experts but perhaps not so much to us amateurs.
Add a prefix to all of your database tables.
Supposing that your database was called "my_database" and the prefix you want to add is "my_prefix", execute the following query:
SELECT Concat('ALTER TABLE ', TABLE_NAME, ' RENAME TO my_prefix_', TABLE_NAME, ';') FROM information_schema.tables WHERE table_schema = 'my_database'
Your result set will be a bunch of queries that you can copy and paste into your favorite MySQL editor (Sequel Pro, phpMyAdmin, whatever). Just paste those in and execute, and you're all done.
How can I see what collation a table has? I.E. I want to see:
+-----------------------------+
| table | collation |
|-----------------------------|
| t_name | latin_general_ci |
+-----------------------------+
SHOW TABLE STATUS shows information about a table, including the collation.
For example SHOW TABLE STATUS where name like 'TABLE_NAME'
The above answer is great, but it doesn't actually provide an example that saves the user from having to look up the syntax:
show table status like 'test';
Where test is the table name.
(Corrected as per comments below.)
Checking the collation of a specific table
You can query INFORMATION_SCHEMA.TABLES and get the collation for a specific table:
SELECT TABLE_SCHEMA
, TABLE_NAME
, TABLE_COLLATION
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 't_name';
that gives a much more readable output in contrast to SHOW TABLE STATUS that contains a lot of irrelevant information.
Checking the collation of columns
Note that collation can also be applied to columns (which might have a different collation than the table itself). To fetch the columns' collation for a particular table, you can query INFORMATION_SCHEMA.COLUMNS:
SELECT TABLE_SCHEMA
, TABLE_NAME
, COLUMN_NAME
, COLLATION_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 't_name';
For more details you can refer to the article How to Check and Change the Collation of MySQL Tables
Use this query:
SHOW CREATE TABLE tablename
You will get all information related to table.
Check collation of the whole database
If someone is looking here also for a way to check collation on the whole database:
use mydatabase; (where mydatabase is the name of the database you're going to check)
SELECT ##character_set_database, ##collation_database;
You should see the result like:
+--------------------------+----------------------+
| ##character_set_database | ##collation_database |
+--------------------------+----------------------+
| utf8mb4 | utf8mb4_unicode_ci |
+--------------------------+----------------------+
1 row in set (0.00 sec)
-edit2- 3hrs later and still have the same problem. I am using the noinstall archive package.
-edit- maybe someone can tell me a better way to check if a table exist?
I have a function in my lib to check if a table exist which i asked how to do in the past.
I deleted my database and created it again. My code didnt create the tables properly. After debugging i decided to write the below.
mysql> SELECT table_schema, table_name FROM information_schema.tables WHERE tabl
e_schema = 'mydb' AND table_name='ApprovePost';
+--------------+-------------+
| table_schema | table_name |
+--------------+-------------+
| mydb | ApprovePost |
+--------------+-------------+
1 row in set (0.00 sec)
Weird... mydb was dropped and created again (i wrote drop database mydb; and create database mydb;. It should be gone?). Lets find out what exists
mysql> SELECT table_schema, table_name FROM information_schema.tables WHERE tabl
e_schema = 'mydb';
Empty set (0.00 sec)
Not only do i not know why the first statement shows tables which is wrecking my code, i dont know why this is not showing any tables (in that database).
note: The databases should all be innodb. Also this is a fresh windows install and i may have configured something wrong.
Bonus weirdness.
mysql> drop database mydb;
ERROR 1008 (HY000): Can't drop database 'mydb'; database doesn't exist
mysql> SELECT table_schema, table_name FROM information_schema.tables WHERE tabl
e_schema = 'mydb';
Empty set (0.00 sec)
mysql> SELECT table_schema, table_name FROM information_schema.tables WHERE tabl
e_schema = 'mydb' AND table_name='ApprovePost';
+--------------+-------------+
| table_schema | table_name |
+--------------+-------------+
| mydb | ApprovePost |
+--------------+-------------+
1 row in set (0.00 sec)
Looks like you need to use the FLUSH TABLES command for the INFORMATION_SCHEMA.TABLES to reflect existing tables.
Reference:
TABLE CACHE
Hmmm...
Are results stable? May be some pending transaction..
What is shown by
show tables like '%'
Also it may be an issue with physical files.
Is folder for mydb exists?