ALTER TABLE LIKE - mysql

Is it possible to use the LIKE statement on ALTER TABLE similar to CREATE TABLE in MySQL?
Eg. 'CREATE TABLE db.tbl1 LIKE db.tbl2'
This clones a database table's structure. I want to alter an existing table with the same columns but to pick up the primary keys of another table.
I was thinking of something like 'ALTER TABLE db.tbl1 LIKE db.tbl2' but this throws back an error.
Any ideas?
Thanks

I required a similar thing and settled to use the following procedure:
ALTER TABLE tbl1 RENAME tbl1_old;
CREATE TABLE tbl1 LIKE tbl2;
INSERT INTO tbl1 SELECT * FROM tbl1_old;
DROP TABLE tbl1_old;
Altough this is not a single statement it should do the job. Only problem could be different index settings (UNIQUE, etc.) which cause errors when doing the "INSERT INTO" of the original table contents.

Everything ALTER TABLE can do is explained here.
As you can see importing indexes from another table is not mentioned. You could probably do that with some clever information_schema querying, but I don't think it would be worth the cost.

It seems you can't.

Related

MySQL table "crashed" after column type update

My MySQL table "crashed" after updating column types. I changed VARCHAR to INT and added some new columns too.
After that, when I'd like to view the table entries, every software just keeps loading and crashing... I can't even make any queries to the table. All I can do is look at the list of columns of the table. (I've tried with PhpMyAdmin, HeidiSQL and MySQL Workbench). Changes are made with HeidiSQL.
What should I do? This is the first time this happens and I've been using HeidiSQL for a long time.
You have changed VARCHAR to INT in the table schema. At first sight we are correct, just change alter the column and mysql server do as without showing any error But when you alter the table, mysql server have to do lot of work. first store the records temporary and recreate the schema and insert the record. If your table have many records then it is tough to alter. So either truncate table and alter the schema and reinsert or create other table and rename it latter.
In my opinion the solution is create table as you want schema.
Insert the record in new table from table.
eg- insert into new_table (col1, col2) select col1, col2 from old_table;
drop the old table
drop table old_table
rename the new table with old table
rename new_table to old_table

When to CREATE TABLE AS SELECT versus CREATE TABLE LIKE?

I can "copy" a table using:
CREATE TABLE copy LIKE original_table
and
CREATE TABLE copy as select * from original_table
In the latter case only the data are copied but not e.g primary keys etc.
So I was wondering when would I prefer using a select as?
These do different things. CREATE TABLE LIKE creates an empty table with the same structure as the original table.
CREATE TABLE AS SELECT inserts the data into the new table. The resulting table is not empty. In addition, CREATE TABLE AS SELECT is often used with more complicated queries, to generate temporary tables. There is no "original" table in this case. The results of the query are just captured as a table.
EDIT:
The "standard" way to do backup is to use . . . . backup at the database level. This backs up all objects in the database. Backing up multiple tables is important, for instance, to maintain relational integrity among the objects.
If you just want a real copy of a table, first do a create table like and then insert into. However, this can pose a challenge with auto_increment fields. You will probably want to drop the auto_increment property on the column so you can populate such columns.
The second form is often used when the new table is not an exact copy of the old table, but contains only selected columns or columns that result from a join.
"Create Table as Select..." are most likely used when you have complex select
e.g:
create table t2 as select * from t1 where x1=7 and y1 <>2 from t1;
Now, apparently you should use Create Like if you don't need such complex selects. You can change the PI in this syntax also.

how to delete duplicate records in mysql table

I'm having an issue with finding and deleting duplicate records, I have a table with IDs called CallDetailRecordID which I need to scan and delete records, the reason there are duplicates is that I'm exporting data to special arching engine works with MySQL and it doesn't support indexing.
I tried using "Select DISTINCT" but it dosn't work, is there is another way? I'm hoping I can create a store procedure and have it run weekly to perform clean up.
your help is highly appreciated.
Thank you
CREATE TABLE tmp_table LIKE table
INSERT INTO tmp_table (SELECT * FROM table GROUP BY CallDetailRecordID)
RENAME table TO old_table
RENAME tmp_table to table
Drop the old table if you want, add a LOCK TABLES statement at the beginning to avoid lost inserts.

mysql: alter tablename only if table exists

I tried writing query using exists, but no success so far. Searching hasn't helped so far.
If you attempt to alter a table that does not exist, the query will fail with an error: Table 'database.table' doesn't exist
MySQL does support ALTER IGNORE TABLE, but that only turns errors into warnings if you're attempting to create a unique index while there are values in the table that violate that index.
If you would like to make sure that you do not produce any database queries, I would suggest ensuring the table's existence using SHOW TABLES LIKE 'tablename' before running your ALTER TABLE query.

Quickest way to delete enormous MySQL table

I have an enormous MySQL (InnoDB) database with millions of rows in the sessions table that were created by an unrelated, malfunctioning crawler running on the same server as ours. Unfortunately, I have to fix the mess now.
If I try to truncate table sessions; it seems to take an inordinately long time (upwards of 30 minutes). I don't care about the data; I just want to have the table wiped out as quickly as possible. Is there a quicker way, or will I have to just stick it out overnight?
(As this turned up high in Google's results, I thought a little more instruction might be handy.)
MySQL has a convenient way to create empty tables like existing tables, and an atomic table rename command. Together, this is a fast way to clear out data:
CREATE TABLE new_foo LIKE foo;
RENAME TABLE foo TO old_foo, new_foo TO foo;
DROP TABLE old_foo;
Done
The quickest way is to use DROP TABLE to drop the table completely and recreate it using the same definition. If you have no foreign key constraints on the table then you should do that.
If you're using MySQL version greater than 5.0.3, this will happen automatically with a TRUNCATE. You might get some useful information out of the manual as well, it describes how a TRUNCATE works with FK constraints. http://dev.mysql.com/doc/refman/5.0/en/truncate-table.html
EDIT: TRUNCATE is not the same as a drop or a DELETE FROM. For those that are confused about the differences, please check the manual link above. TRUNCATE will act the same as a drop if it can (if there are no FK's), otherwise it acts like a DELETE FROM with no where clause.
EDIT: If you have a large table, your MariaDB/MySQL is running with a binlog_format as ROW and you execute a DELETE without a predicate/WHERE clause, you are going to have issues to keep up the replication or even, to keep your Galera nodes running without hitting a flow control state. Also, binary logs can get your disk full. Be careful.
The best way I have found of doing this with MySQL is:
DELETE from table_name LIMIT 1000;
Or 10,000 (depending on how fast it happens).
Put that in a loop until all the rows are deleted.
Please do try this as it will actually work. It will take some time, but it will work.
Couldn't you grab the schema drop the table and recreate it?
drop table should be the fastest way to get rid of it.
Have you tried to use "drop"? I've used it on tables over 20GB and it always completes in seconds.
If you just want to get rid of the table altogether, why not simply drop it?
Truncate is fast, usually on the order of seconds or less. If it took 30 minutes, you probably had a case of some foreign keys referencing the table you were truncating. There may also be locking issues involved.
Truncate is effectively as efficient as one can empty a table, but you may have to remove the foreign key references unless you want those tables scrubbed as well.
We had these issues. We no longer use the database as a session store with Rails 2.x and the cookie store. However, dropping the table is a decent solution. You may want to consider stopping the mysql service, temporarily disable logging, start things up in safe mode and then do your drop/create. When done, turn on your logging again.
I'm not sure why it's taking so long. But perhaps try a rename, and recreate a blank table. Then you can drop the "extra" table without worrying how long it takes.
searlea's answer is nice, but as stated in the comments, you lose the foreign keys during the fight.
this solution is similar: the truncate is executed within a second, but you keep the foreign keys.
The trick is that we disable/enable the FK checks.
SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE NewFoo LIKE Foo;
insert into NewFoo SELECT * from Foo where What_You_Want_To_Keep
truncate table Foo;
insert into Foo SELECT * from NewFoo;
SET FOREIGN_KEY_CHECKS=1;
Extended answer - Delete all but some rows
My problem was: Because of a crazy script, my table was for with 7.000.000 junk rows. I needed to delete 99% of data in this table, this is why i needed to copy What I Want To Keep in a tmp table before deleteting.
These Foo Rows i needed to keep were depending on other tables, that have foreign keys, and indexes.
something like that:
insert into NewFoo SELECT * from Foo where ID in (
SELECT distinct FooID from TableA
union SELECT distinct FooID from TableB
union SELECT distinct FooID from TableC
)
but this query was always timing out after 1 hour.
So i had to do it like this:
CREATE TEMPORARY TABLE tmpFooIDS ENGINE=MEMORY AS (SELECT distinct FooID from TableA);
insert into tmpFooIDS SELECT distinct FooID from TableB
insert into tmpFooIDS SELECT distinct FooID from TableC
insert into NewFoo SELECT * from Foo where ID in (select ID from tmpFooIDS);
I theory, because indexes are setup correctly, i think both ways of populating NewFoo should have been the same, but practicaly it didn't.
This is why in some cases, you could do like this:
SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE NewFoo LIKE Foo;
-- Alternative way of keeping some data.
CREATE TEMPORARY TABLE tmpFooIDS ENGINE=MEMORY AS (SELECT * from Foo where What_You_Want_To_Keep);
insert into tmpFooIDS SELECT ID from Foo left join Bar where OtherStuff_You_Want_To_Keep_Using_Bar
insert into NewFoo SELECT * from Foo where ID in (select ID from tmpFooIDS);
truncate table Foo;
insert into Foo SELECT * from NewFoo;
SET FOREIGN_KEY_CHECKS=1;