I have MySQL database about 5GB size and about 200 tables in it. All tables have prefix which I'd like to remove and I found some ideas for that.
The problem is that this database has referential integrity checking by using CONSTRAINT...FOREIGN KEY.
How to remove prefix from tables, including change in constraints, without manual modification or removing constraints?
Unfortunately you have to drop and recreate the foreign keys according to the mysql documentation on rename table:
Foreign keys that point to the renamed table are not automatically
updated. In such cases, you must drop and re-create the foreign keys
in order for them to function properly.
Use the tables in information_schema (mostly TABLES and COLUMNS) to construct the code you need. Perhaps 3 scripts would be wise:
SELECT CONCAT('ALTER TABLE ', table_name, ' DROP FOREIGN KEY ' ... ) FROM ...
SELECT CONCAT('RENAME TABLE ', ...
SELECT CONCAT('ALTER TABLE ', table_name, ' ADD FOREIGN KEY ' ... ) FROM ...
Then manually copy and paste the 3 scripts into the mysql commandline tool.
As for removing the prefix, look at the string functions MID, LOCATE, SUBSTRING_INDEX, etc., to see what would be useful.
Related
Suddenly I've a strange problem with Mysql:
In the navigator I see the "company" table (even after refresh), but if I do SELECT * FROM company; says that the table does not exist.
With the command SHOW TABLES FROM smartex_develop; the table "company" is present, but if I use the command SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'smartex_develop'; the table is missing. It's very strange also considering that there are a lot of table with a foreign key of that table.
Someone know how to resolve it?
[SELECT * FROM company] 1
[SHOW TABLES FROM smartex_develop] 2
[SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'smartex_develop'] 3
We had a similar problem - a table suddenly went missing. In the logs we had:
Load table <name-of-missing-table> failed, the table has missing foreign key indexes. Turn off 'foreign_key_checks' and try again.
InnoDB: Foreign Key referenced table <name-of-missing-table> not found for foreign table <some-other-table>
This happened upon mysqld startup, so the root cause might have been much older than that. In our case, the root cause was charset conversions. We converted a few tables, and ended up with foreign keys where the column in one table and the column in the referenced table had different character sets.
How we solved:
Disable foreign key checks
Restart mysql -- the missing table will now reappear
Convert all the columns that reference each other to have the same character set. You can use this query: select table_name,column_name,CHARACTER_SET_NAME from INFORMATION_SCHEMA.COLUMNS where table_schema = 'myschema' and data_type='varchar';
Re-enable foreign key checks
Restart mysql -- all should be fine now
I need a query that could drop primary key only if it exists.
ALTER TABLE tablename DROP PRIMARY KEY;
This will return error if it does not exists, but my requirement is to run a query in different databases.
In MariaDB 10.2.16 i was able to solve this problem with:
ALTER TABLE tablename DROP INDEX IF EXISTS `PRIMARY`;
This should work with any table since the primary keys in MySQL are always called PRIMARY as stated in MySQL doc:
The name of a PRIMARY KEY is always PRIMARY, which thus cannot be
used as the name for any other kind of index.
I would recommend using this:
SELECT CONCAT('ALTER TABLE ', TABLE_SCHEMA, '.',TABLE_NAME,
' DROP PRIMARY KEY; ANALYZE TABLE ', TABLE_SCHEMA, '.',TABLE_NAME, ';')
FROM information_schema.COLUMNS
WHERE CONCAT(TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME) IN
(SELECT CONCAT(TABLE_SCHEMA,TABLE_NAME,COLUMN_NAME)
FROM INFORMATION_SCHEMA.STATISTICS
WHERE INDEX_NAME = 'PRIMARY' -- *Required* to get only the primary keys from the statistics table.
-- *Optional*
AND TABLE_SCHEMA = 'clients_database');
Run this to generate your required SQL.
Copy your results, then run them as working queries.
ANALYZE TABLE is optional as well as the WHERE clause.
You can remove ANALYZE TABLE ', TABLE_SCHEMA, '.',TABLE_NAME, ';' if desired from the query below.
I exploit the information_schema when researching and utilizing standardization techniques.
Just about everything you would ever need or want to know about your tables and columns lives in some System table in either (if applicable)
Database / Table_schema:
information_schema
performance_schema
mysql
Note: From doc's
Internal schemas, such as "performance_schema", "information"schema", "sys", and "mysql", are hidden by default. Toggle the Show Metadata and Internal Schemas preference to list them in the object browser. Schemas beginning with a "." are also controlled by this setting.
NOTE: Here's something similar that has been created.
Hope this helps!
Cheers,
Jay
I think the easy option might be this:
first go to :
'YourDatabase'>tables>your table name>keys>copy the constraints like 'PK__TableName__0001'
then run this:
Query:alter Table 'TableName' drop constraint PK__TableName__0001
I'm trying to use fulltext and match against multiple tables but without Join because they are not related.
I've tried something like:
SELECT mg_users.username, mg_users.email, mg_uzgajivac.imeuzgajivaca ...
FROM mg_users,mg_uzgajivac,mg_buy_it_now,mg_golu ...
WHERE MATCH(mg_users.username) AGAINST ('rasa')
OR MATCH(mg_users.email) AGAINST ('rasa')
OR MATCH(mg_uzgajivac.imeuzgajivaca) AGAINST ('rasa')
OR MATCH(mg_uzgajivac.mjesto) AGAINST ('rasa') ...
But it returns nothing, I'm not sure what I'm doing wrong.
I think your issue is that the indexes are not up to date. You need to rebuild your indexes for MATCH ... AGAINST to work correctly.
If you are using MyISAM tables then repair the tables will rebuild you the indexes
REPAIR TABLE table_name;
But if you are using Innodb tables "and you should." You can execute a fake ALTER command which will force the indexes to be rebuild. It will not change anything but it will force the table to rebuild.
ALTER TABLE table_name ENGINE=innodb;
This may be off-topic but it is something to think about. You can use a multiple column fulltext index to make your query a bit faster
ALTER TABLE mg_users ADD FULLTEXT INDEX (user_name, email);
ALTER TABLE mg_uzgajivac ADD FULLTEXT INDEX (imeuzgajivaca, mjesto);
Then your query will look like this
SELECT mg_users.username, mg_users.email, mg_uzgajivac.imeuzgajivaca ...
FROM mg_users,mg_uzgajivac,mg_buy_it_now,mg_golu ...
WHERE MATCH(mg_users.username, mg_users.email) AGAINST ('rasa')
OR MATCH(mg_uzgajivac.imeuzgajivaca, mg_uzgajivac.mjesto) AGAINST ('rasa')
...
Some SQL servers allow for a generic statement such as ORDER BY PRIMARY KEY. I don't believe this works for MySQL, is there any such workaround that would allow for automated selects across multiple tables or does it require a lookup query to determine the primary key?
The workaround I have been working on involves calling a SHOW COLUMNS FROM before running the query. Is there a more efficient way of doing this? Can MySQL determine the primary key of a table during the select process?
Update: There is no official way of doing this in MySQL or SQL in general as Gordon pointed out. SAP has custom functionality for it. There are workarounds, such as working with SHOW COLUMNS FROM table or the information_schema as John pointed out.
MySQL generally pulls data out by insertion order which would be by primary key, but that aside you technically can do the same thing if you pull out the primary key column name and put it in an order by
SELECT whatever FROM table
ORDER BY
( SELECT `COLUMN_NAME`
FROM `information_schema`.`COLUMNS`
WHERE (`TABLE_SCHEMA` = 'dbName')
AND (`TABLE_NAME` = 'tableName')
AND (`COLUMN_KEY` = 'PRI')
);
For composite keys you can use this
SELECT whatever FROM table
ORDER BY
( SELECT GROUP_CONCAT(`COLUMN_NAME` SEPARATOR ', ')
FROM `information_schema`.`COLUMNS`
WHERE (`TABLE_SCHEMA` = 'dbName')
AND (`TABLE_NAME` = 'tableName')
AND (`COLUMN_KEY` = 'PRI')
);
Permission for information schema access from the DOCS
Each MySQL user has the right to access these tables, but
can see only the rows in the tables that correspond to objects for
which the user has the proper access privileges. In some cases (for
example, the ROUTINE_DEFINITION column in the
INFORMATION_SCHEMA.ROUTINES table), users who have insufficient
privileges see NULL. These restrictions do not apply for InnoDB
tables; you can see them with only the PROCESS privilege.
The same privileges apply to selecting information from
INFORMATION_SCHEMA and viewing the same information through SHOW
statements. In either case, you must have some privilege on an object
to see information about it.
SETUP:
CREATE TABLE some_stuff (
firstID INT,
secondID INT,
username varchar(55),
PRIMARY KEY (firstID, secondID)
) ;
QUERY:
SELECT GROUP_CONCAT(`COLUMN_NAME` SEPARATOR ', ')
FROM `information_schema`.`COLUMNS`
WHERE (`TABLE_SCHEMA` = 'dbName')
AND (`TABLE_NAME` = 'some_stuff')
AND (`COLUMN_KEY` = 'PRI');
OUTPUT:
+--------------------------------------------+
| GROUP_CONCAT(`COLUMN_NAME` SEPARATOR ', ') |
+--------------------------------------------+
| firstID, secondID |
+--------------------------------------------+
SAP does, indeed do this (http://help.sap.com/saphelp_nw04s/helpdata/en/fc/eb3a53358411d1829f0000e829fbfe/content.htm). SQL Server is also based on Sybase, and I don't think Sybase supported this functionality. There are many limitations on the syntax.
On a query on one table with a primary key, no explicit order by, and no where conditions, MySQL will generally return the results in primary key order. You cannot depend on this functionality, but it might be good enough for your system.
The big issue would be the use of indexes for the where clause. If there are no indexes on the table, you don't have to worry about it. If there are, you could possibly emulate the behavior with a materialized view:
select t.*
from (select t.*
from table t
) t
where <where clause here>;
Another option is to force the database engine to use the primary key index. You can do this by using a force index hint. The issue is that you need to know the name of the index.
There are different ways to create constraint in mariadb. We can either create them when creating the tables or after that. For example, the json_valid function could be defined in 3 different ways:
1) CREATE TABLE t2 (
j JSON
CHECK (JSON_VALID(j))
);
2) after table creation: "Alter table t2 add check(json_valid(j))"
3) "alter table t2 add constraint something check(json_valid(j))"
Which one is preferable and why?
Thank you in advance.
Assuming there are no INSERTs before the ALTER, they are all equivalent.
Doing everything in the CREATE TABLE is probably a tiny bit faster.