AS described in the MySQL documentation here, it should be possible to drop a column instantly with a syntax like this one:
ALTER TABLE tbl_name DROP COLUMN column_name, ALGORITHM=INSTANT;
It is documented that it is only possible with the following constraints:
Dropping a column cannot be combined in the same statement with other ALTER TABLE actions that do not support ALGORITHM=INSTANT.
Columns cannot be dropped from tables that use ROW_FORMAT=COMPRESSED, tables with a FULLTEXT index, tables that reside in the data dictionary tablespace, or temporary tables. Temporary tables only support ALGORITHM=COPY.
Unfortunately, I am unable to use the syntax described above. For example, here is my test code:
CREATE TABLE MyTable (
MyPrimaryKey bigint NOT NULL AUTO_INCREMENT,
UserId char(36) NOT NULL,
Username varchar(254) NOT NULL,
PRIMARY KEY (MyPrimaryKey),
UNIQUE KEY IX_UserId (UserId)
) ENGINE=InnoDB;
ALTER TABLE MyTable DROP COLUMN Username, ALGORITHM=INSTANT;
When I run this against MySQL 8.0.28, I get the following error:
Error Code: 1845. ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=COPY/INPLACE.
Am I doing something wrong or the documentation is missing something?
Note that the ROW_FORMAT of my table is Dynamic. Here is how I got the row format:
SELECT table_name, row_format
FROM information_schema.tables
WHERE table_schema=DATABASE() AND table_name = 'MyTable';
This functionality has been added to mysql 8.0.29. See the release notes for more details.
Related
I'm digging on MySQL's online ddl (5.7)
For some operations, it support ALGORITHM such as INPLACE, COPY.
This is I understood
INPLACE modifies original table
COPY creates temporary table -> copies all records to it -> and replace original table
Plus, this link refers that adding index to a table does not rebuild table
https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html
but, after I add index and check tables CREATE_TIME it is updated
CREATE DATABASE db;
USE db;
CREATE TABLE hello(id int primary key auto_increment, col varchar(20));
SELECT CREATE_TIME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='db' and TABLE_NAME='hello';
ALTER TABLE hello ADD INDEX `idx_col` (col), ALGORITHM=INPLACE;
# CREATE TIME is updated
SELECT CREATE_TIME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='db' and TABLE_NAME='hello';
I'm not sure whether CREATE_TIME doesn't actually mean table creation time, or
whether table is rebuilt even with ALGORITHM=INPLACE specified.
Could anyone help me find out what is going on here?
I'm reorganizing our MySQL database, changing MyISAM tables to InnoDB and setting foreign keys, and I'm wondering if there's a way to link the column settings also?
Example:
in my useraccount table, the user column is varchar(20). In all my other tables another user column to record who entered the record, also varchar(20).
I'm wondering how I might go about linking all those dependent user columns, like if I had to change the useraccount.user column to varchar(40), can I set all other table user columns to cascade to varchar(40) as well?
I'm sure I could use the information schema to write a PHP script to do this but I'd rather have the database modify itself without outside help if possible. Could this be done through a trigger on the schema record for the username.user column? And if so could I then also make a trigger to automatically add foreign key constraints on any new table where a 'user' column gets added?
seems like it should be possible but I'll admit I don't know MySQL well enough to go screwing around with schema tables ;)
Edit: Here is some sample SQL I wrote to find the mismatched tables
SELECT TABLE_NAME, COLUMN_TYPE
FROM information_schema.COLUMNS
WHERE TABLE_NAME != 'user_accounts'
AND COLUMN_NAME = 'user'
AND COLUMN_TYPE != (
SELECT COLUMN_TYPE
FROM information_schema.COLUMNS
WHERE TABLE_NAME = 'user_accounts'
AND COLUMN_NAME = 'user'
)
Ideally I'd like to use this information_schema result to loop through each row of the above result and ALTER the tables to change the Column Types to match the column type of user_account.user
In SQL, DDL doesn't cascade.
In standard SQL, you'd use domains (which MySQL unfortunately doesn't support). Let's say you had this PostgreSQL code stored in your version control system.
create domain USER_DOMAIN varchar(15) not null;
create table users (
user USER_DOMAIN primary key
);
create table another_table (
user USER_DOMAIN references users (user),
other_column char(1) not null,
primary key (user, other_column)
);
When the need arises, you can change one line of code in version control . . .
create domain USER_DOMAIN varchar(20) not null;
. . . dump the data, load the new schema, reload the data, and you're done. But be warned that this can take quite a while on a huge database. (Moving the data takes the most time.)
You can accomplish the same thing in MySQL, even though it doesn't support the CREATE DOMAIN statement. Instead of SQL, use the m4 macro processor.
# test.m4 -- demonstrate replacing CREATE DOMAIN with m4 macro.
define(`USER_DOMAIN', `varchar(15) not null')dnl
create table users (
user USER_DOMAIN primary key
);
create table another_table (
user USER_DOMAIN references users (user),
other_column char(1) not null,
primary key (user, other_column)
);
Then run that code through m4 as part of your makefile. m4 will replace USER_DOMAIN with 'varchar(15) not null'.
$ m4 test.m4
create table users (
user varchar(15) not null primary key
);
create table another_table (
user varchar(15) not null references users (user),
other_column char(1) not null,
primary key (user, other_column)
);
Now changing to varchar(20) is still only a one-line change.
CREATE TABLE t1 (id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT )
The above command increases id from 0 ,but i want to increase it from a specific no. say like 1234567890 ..
how can i do that??
How can i set auto increment from a specific no.??
I tried something like this but it did not work
CREATE TABLE t1 AUTO_INCREMENT = 1234567890, (id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT)
If the question is not clear pllzz comment..
CREATE TABLE t1 (
`id` BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT
)
ENGINE = MyISAM
AUTO_INCREMENT = 1234567890;
Edit: A quick note with regards to storage engine support for setting the AUTO_INCREMENT value, which will depend on the version of MySQL you're running.
From MySQL 5.0 Manual,
In MySQL 5.0, this works for MyISAM
and MEMORY tables. It is also
supported for InnoDB as of MySQL
5.0.3.
From MySQL 5.1 Manual,
In MySQL 5.1, this works for MyISAM,
MEMORY, and InnoDB tables. It also
works for ARCHIVE tables as of MySQL
5.1.6.
After your create table script, use the alter table syntax to update the auto_increment value:
ALTER TABLE t1 AUTO_INCREMENT = 12345
You can alter the table:
ALTER TABLE tbl AUTO_INCREMENT = 100;
Just create your table like your first statement, then add
ALTER TABLE tbl AUTO_INCREMENT = 1234567890;
...where 1234567890 is ofc the value you want the value. More details can be found here: http://dev.mysql.com/doc/refman/5.1/en/example-auto-increment.html
I am setting up a table in mysql of engine type merge in mysql and was wondering if i have to have all my tables created previously that i want to merge. For example:
CREATE TABLE t1 (
a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
message CHAR(20)) ENGINE=MyISAM;
CREATE TABLE t2 (
a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
message CHAR(20)) ENGINE=MyISAM;
INSERT INTO t1 (message) VALUES ('Testing'),('table'),('t1');
INSERT INTO t2 (message) VALUES ('Testing'),('table'),('t2');
CREATE TABLE total (
a INT NOT NULL AUTO_INCREMENT,
message CHAR(20), INDEX(a))
ENGINE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
Now if i have code that automatically created a t3 table i would have to modify the merge table to add this to the union? Would i use an ALTER query for that?
note: i am not using MySQL partitions because i have a mysql version 5.0.
Now if i have code that automatically created a t3 table i would have to modify the merge table to add this to the union? Would i use an ALTER query for that?
From the documentation:
To remap a MERGE table to a different collection of MyISAM tables, you can use one of the following methods:
DROP the MERGE table and re-create it.
Use ALTER TABLE tbl_name UNION=(...) to change the list of underlying tables.
Beginning with MySQL 5.0.60, it is also possible to use ALTER TABLE ... UNION=() (that is, with an empty UNION clause) to remove all of the underlying tables.
A show create table command shows the following:
'columnA' varchar(6) NOT NULL DEFAULT '';
How do I modify that column so that the not null is removed?
I need it to be:
'columnA' varchar(6) DEFAULT NULL;
I thought the following would work, but it has no effect:
ALTER TABLE tbl_name MODIFY columnA varchar(6) DEFAULT NULL;
Try this instead:
ALTER TABLE tbl_name MODIFY columnA varchar(6) NULL DEFAULT NULL;
Normally, Eric's answer should work:
ALTER TABLE tbl_name MODIFY columnA varchar(6) NULL DEFAULT NULL;
(Although the 'NULL DEFAULT NULL' part is optional).
But like you, I had a case that just returned OK without doing anything. In my case it appears to be due to the fact that my key was part of the primary key. So I had to do the following:
ALTER TABLE tbl_name DROP PRIMARY KEY;
ALTER TABLE tbl_name MODIFY columnA varchar(6);
ALTER TABLE tbl_name ADD PRIMARY KEY (columnA);
with that last query specifying whatever your primary key actually is.
Also, in case anyone thinks that is too verbose, the following combined query does NOT work, even though it should be identical:
ALTER TABLE tbl_name DROP PRIMARY KEY, MODIFY columnA varchar(6), ADD PRIMARY KEY (columnA);
I assume that mysql rewrites that last query into a different order so that the primary key still exists when the modify is performed, hence the need to break it out into three statements.
FYI, this is on mysql 5.1.47 but I haven't yet found any documentation indicating why this happens so I don't know what versions are affected.
Make the change (locally) in phpMyAdmin. It will show the query it used for the change. Execute this query in production and you're done.
You can use this strategy in any GUI tool to see the queries it performs. I personally use Sequel Pro (for Mac OS X) instead of phpMyAdmin.