Is it necessary to rebuild index after changing column default value? - mysql

Is is necessary to drop and re-create an index involving a particular column when that column is altered so that the default value is changed? My column looks like SubNum varchar(8) NOT NULL DEFAULT '' and I want to change it to SubNum varchar(8) NOT NULL. My related indexes looks like:
KEY `Docs1` (`First`,`SubNum`,`DocNum`),
KEY `Docs2` (`SubNum`,`DocNum`),
I'm using MySQL version 5.5.49 and the table is MyIsam.

Changing the default value of a column does not change it's data-type. Given that the column was not-null before the change, this change does not affect any existing data - it just changes the default for the next row inserted. Since the currently stored data does not change, there's no need to rebuild the index.

You don't need to reindex it after altering the table, internally it will create a new table and index it too.

Related

What is the standard way to add DEFAULT constraint using ALTER TABLE query?

I want to change the default value of a column after creating the table in MySQL. Which one of the following queries is the standard way to change the default value of the column after creating the table?
ALTER TABLE table_name
MODIFY attribute_name DATATYPE DEFAULT default_value;
ALTER TABLE table_name
ALTER attribute_name SET DEFAULT default_value;
Either works.
If you use MODIFY COLUMN, you must remember to include the column data type and other options that might be present on that column such as NOT NULL, AUTO_INCREMENT, or ZEROFILL. If you forget one of these options, it is removed from the column definition.
This can have unintended side effects. For example, changing the default of a column is a metadata-only change, so it is instant even if the table is huge. But changing a column's nullability to or from NOT NULL requires a table restructure. So if you accidentally change the nullability of the column by leaving that option out, you find yourself waiting for hours when you didn't have to.
If you use ALTER COLUMN ... SET DEFAULT, you don't have to spell out all those column options. They are left unaltered. This is more convenient and less error-prone if you only want to change the default value.
As for which one is standard, the ALTER COLUMN .. SET DEFAULT is in the ANSI/ISO SQL specification. MODIFY COLUMN is a MySQL extension to the standard for the sake of Oracle compatibility.

How do I remove ON UPDATE CURRENT_TIMESTAMP from an existing column?

I did a dump of a mysql 5.5 database and loaded it into a 5.6 server.
The dump added ON UPDATE CURRENT_TIMESTAMP to a bunch of columns that didn't have it previously.
I'm searching for an ALTER TABLE statement that will remove the ON UPDATE CURRENT_TIMESTAMP rule without making any other changes. In my imagination it should be something like ON UPDATE NOOP or ON UPDATE NO_CURRENT_TIMESTAMP.
ON UPDATE JUST_BE_A_NORMAL_COLUMN?
I tried using the "Clear default" option in mysql workbench and it did the opposite of what it should have done - it gave the column a default!
I was able to get rid of the default with ALTER TABLE t ALTER COLUMN c DROP DEFAULT, so the column is mandatory in INSERTs (just like it was before the dump/reload, as I wanted it) but the unwanted behavior on UPDATEs remains.
I have not enabled the explicit_defaults_for_timestamp option. If I was starting fresh I'd definitely use that option since it seems a lot more sane. But since I already had the columns configured the way I wanted them in 5.5, I expected them to keep the same semantics when transferred to 5.6. Apparently mysqldump just wasn't smart enough.
At this point I'm not sure I understand what effects would result from enabling explicit_defaults_for_timestamp. Would that option change the behavior of existing tables, or does it only change the interpretation of future CREATE TABLE commands? Would turning it on somehow help me fix the broken columns?
UPDATE:
A similar question is here but that one is about creating a new table, not altering an existing column. In fact that question is the one I used as a guide when creating the tables on the 5.5 server. I used the 2-step procedure: create with default 0 to suppress ON UPDATE CURRENT_TIMESTAMP, then drop default.
The 2-step procedure definitely doesn't produce the correct result on the 5.6 server without explicit_defaults_for_timestamp; this is a sign that either 5.6 doesn't perfectly imitate the old behavior in this mode, or the old server never did what I thought it was doing. I can't be sure which.
ALTER TABLE mytable
CHANGE mycolumn
mycolumn TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
I believe this will reset and void the ON UPDATE. This would effectively make this definition:
CREATE TABLE mytable (
# Other Columns
mycolumn timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP
)
Change into this one:
CREATE TABLE mytable (
# Other Columns
mycolumn timestamp NOT NULL default CURRENT_TIMESTAMP
)
If you wanted to reset the column entirely, you should be able to simply redefine it like:
ALTER TABLE mytable
CHANGE mycolumn
mycolumn TIMESTAMP NOT NULL;
Using the ideas from the other answers, and a couple of freshly installed mysql server instances, I have done a comparison of the behavior of several different CREATE and ALTER commands on 3 different server configurations:
mysql 5.5.45
mysql 5.6.26 without explicit_defaults_for_timestamp
mysql 5.6.26 with explicit_defaults_for_timestamp
The easiest one to explain is 5.6 with explicit_defaults_for_timestamp. Everything is sane. The timestamp type is not noticeably different from any other type. Columns created before the explicit_defaults_for_timestamp flag was turned on retain their old defaults and magic update.
In 5.5, the implicit defaults happen when a timestamp column is created (if it is the first timestamp column in the table). These are well documented already. The magic update behavior can be avoided by setting an explicit default, and then the default can be removed, leaving the column with the 3 desired attributes: non-nullable, no default, no magic update. This is the result of CREATE TABLE t (TIMESTAMP c NOT NULL DEFAULT 0) and ALTER TABLE t ALTER COLUMN c DROP DEFAULT.
This state can't be recreated with a single CREATE TABLE command, and it doesn't survive a mysqldump.
5.6 without explicit_defaults_for_timestamp is the most interesting case. It's almost the same as 5.5, but the DROP DEFAULT command is different. If you try the "create with default 0 then drop default" sequence, the magic update attribute appears as a side effect of the drop. But if you make the default CURRENT_TIMESTAMP instead of 0, then the DROP DEFAULT works without the side effect. (Must be a bug. I can't imagine any reason it would intentionally behave this way.)
Therefore this pair of commands will have the same result on all of the server configurations I tested:
ALTER TABLE t CHANGE COLUMN c c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
ALTER TABLE t ALTER COLUMN c DROP DEFAULT;
The column now has no default and no magic update.
For your use case I think you would be better served with DATETIME, eg:
ALTER TABLE `my_table`
CHANGE `my_col` `my_col` DATETIME NOT NULL DEFAULT NOW();
This will default to NOW() on insert, but remain unaffected on update.
See this question for a good explanation of the difference:
Should I use field 'datetime' or 'timestamp'?
Try enabling the explicit_defaults_for_timestamp system variable and then redefine the columns with:
ALTER TABLE `table` CHANGE COLUMN `col` `col` TIMESTAMP NOT NULL;
If I understand the documentation correctly enabling explicit_defaults_for_timestamp is mandatory to be able to define TIMESTAMP columns declared as NOT NULL and without an explicit DEFAULT.
If you want to remove both the DEFAULT value and ON UPDATE value, nothing but the following helped me
ALTER TABLE `your_table` CHANGE `your_column` `your_column` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00';

Will MySQL ALTER TABLE reformat field data?

I need to alter a table to change the Type of a column. If the current column Type is DECIMAL(8,2) and I alter that column to be DOUBLE, will the already-existing data in the column also be changed to reflect the column's new Type?
It should. However, always be safe when altering existing tables.
My preferred way of doing this type of operation is:
make a backup
create a new column
update all rows moving the old data over to new column
inspect the new column for anything wrong and fix if necessary
delete the old column

How to alter MySQL table without losing data?

In my application, I make some changes and upload them to a testing server. Because I have no access to the server database I run ALTER commands to make changes on it.
Using a method I ran the following command on server:
ALTER TABLE `blahblahtable` ADD COLUMN `newcolumn` INT(12) NOT NULL
After that, I found that the all the data of the table has been removed. Now the table is blank.
So I need to alter the table without removing his data. Is there any way to do that?
Your question is quite obvious. You're adding a new column to the table, and setting it to NOT NULL.
To make things clearer, I will explain the reaction of the server when you run the command:
You add a new column, so every row of the table has to set a value for that column.
As you don't declare any default value, all the rows set null for this new column.
The server notices that the rows of the table have a null value on a column that doesn't allow nulls. This is illegal.
To solve the conflict, the invalid rows are deleted.
There are some good fixes for this issue:
Set a default value (recommended) for the column you're creating.
Create the column without the NOT NULL, set the appropiate values, and then make the column NOT NULL.
You can create a temp table, pass all the information from the table you want to alter, and then return the info to the altered table.

Not getting concept of null

Hy Guys,
Beginning with mysql. I am not able to grasp the concept of NULL. Check screen-shot (*declare_not_null, link*). In it when I specifically declared 'name' field to be NOT NULL. When i run the 'desc test' table command, the table description shows default value for name field to be NULL.Why is that so?
From what I have read about NULL, it connotes a missing or information that is not applicable. So when I declare a field to be NOT NULL it implies (as per my understanding) that user must enter a value for the name field else the DB engine should generate an error i.e. record will not be entered in DB. However when i run 'insert into test value();' the DB engine enters the record in table. Check screen-shot(*empty_value, link*).
FLICKR LINKS
*declare_not_null*
http://www.flickr.com/photos/55097319#N03/5302758813/
*empty_values*
Check the second screenshot on flickr
Q.2 what would be sql statemetn to drop a primary key from a table's field.
If I use 'ALTER TABLE test drop key id;' it gives the following:
ERROR:
Incorrect table definition; there can be only one auto column and it must be defined as a key.
Thanks for your help..
You are looking at the default value column. The database won't let you update or insert that column with null.
I'll take the first question:
When i run the 'desc test' table command, the table description shows default value for name field to be NULL.Why is that so?
The default being NULL means either:
You have specified that the default is NULL or
You haven't specified a default value for that column.
In this case it is the second option. It does not mean that it is possible to insert a NULL.
Q.1. I don't have access to Flickr so I can't see your screenshots, anyway, if you declare a column NOT NULL, there may be a default value for this column set, and that is why you can add a record.
Q.2. Looks like you cannot have an auto increment column that is not a Primary Key. So if you want to drop the Primary Key, you need to drop the auto increment first.