What does MySQL converting varchar to char? - mysql

When we add a new table, we made a mistake : a field was a varchar(255), but we have to write join queries.
So we alter table to make a char(6).
My question is : what does MySQL in this case ?
It trims right ?

Rather than worry about what MySQL does or doesn't do why not just convert the data yourself before the change.
e.g.
UPDATE YourTable
SET YourField = LEFT(YourField,6);
ALTER TABLE YourTable MODIFY COLUMN YourField Char(6)
You should note that if your column data is too long it won't let you do the alter assuming enable strict SQL mode see Shef's complete answer

It will try to convert the format. In your case, the column is a string type, so it will truncate the value, if the strict SQL mode is not enabled.
When you change a data type using CHANGE or MODIFY, MySQL tries to
convert existing column values to the new type as well as possible.
Warning This conversion may result in alteration of data. For example,
if you shorten a string column, values may be truncated. To prevent
the operation from succeeding if conversions to the new data type
would result in loss of data, enable strict SQL mode before using
ALTER TABLE (see Section 5.1.6, “Server SQL Modes”).
Read the fine warning down two fifth of the page.

MySQL won't even let you alter the table if there's any case you'll lose data (e.g. a row has an entry where the field's text is longer than six characters), so you're better off converting the data how you see fit.

Related

Migrating Varchar to Text in Mysql

I am converting one of the "Varchar" column in mysql table to a text field. I am simply using single alter command to convert the type. When i read about text and varchar came to know that it had difference in storing mechanisms.
Am I supposed to write any migration script to change the type of column and move data or a single type altering command is enough ?
ALTER TABLE table_name MODIFY column_name TEXT NOT NULL;
There is no a big problem to change varchar to text because text supports more data length than varchar, but if the field has a index it must be drop and create new index with prefix col_name(length) (see CREATE INDEX syntax).
According to your data content maybe would be a good idea use fulltext indexes but that implies change your search expressions on that field.
If you are in production environment, the table will be locked meanwhile the migration is in progress to prevent data loss.

Why is it possible to use numeric string values to set integer fields in MySQL, and is this a feature that will always work?

I just noticed that phpMyAdmin for some reason always seems to use numeric string values instead of integer values (i.e. '5' instead of 5) in its generated SQL queries for writing data to integer fields in MySQL databases, which I did not know was even valid SQL.
This made me curious, so I did some follow-up experiments myself, and could confirm that this is indeed allowed, even in DDL queries like:
ALTER TABLE MyTable ALTER COLUMN MyIntField SET DEFAULT '5'
(where, possibly needless to say, the "MyIntField" is of the "int" type)
and also in normal insert and update queries like:
INSERT INTO MyTable (MyIntField) VALUES ('5');
UPDATE MyTable SET MyIntField = '5' WHERE id = 1;
How/why is this allowed by MySQL? Databases normally care about types, and strings and integers are definitely different types?
Also, with this "feature", the same SQL injection sanitation procedure could be used for both string values and integer values (instead of integer validation testing input values for integer fields and quote-escape-testing input values for string fields separately), so my follow-up question is: Can I depend on the existence and support of this feature under all conditions in MySQL, and also in future versions of MySQL, i.e. is it documented somewhere officially?
MySQL is pretty lax about most things, by default fixing these errors by doing everything it can to not error out.
MySQL does have a strict mode though which would not allow that behaviour
http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sql-mode-strict
For more info.
This 'feature' can also cause performance issues, comparing a sting to an index'ed int makes the index useless (in some cases, sometimes the optimiser can spot this and cast only the input)
Strict SQL Mode
Strict mode controls how MySQL handles invalid or missing values in
data-change statements such as INSERT or UPDATE. A value can be
invalid for several reasons. For example, it might have the wrong data
type for the column, or it might be out of range. A value is missing
when a new row to be inserted does not contain a value for a non-NULL
column that has no explicit DEFAULT clause in its definition. (For a
NULL column, NULL is inserted if the value is missing.) Strict mode
also affects DDL statements such as CREATE TABLE.
I would add, numeric strings is always safer than the opposite.
It will never lead to any critical problem if you use a numeric string to query a numeric field, i.e. update table where number='1' will work like a charm.
Whereas the opposite, if happens could be a disaster. If you compare a number with a string the latter is converted to a number. I.e. update table where string=0 will likely update all rows in the database while a numeric string won't cause any harm: update table where string='0' will just leave all strings alone.

How do you change an autoincremented columns starting value through liquibase?

I am using MySql for my database. I have found how to set a column's starting autoincrement value when creating a table, but I need to know how to set a new starting value for an existing column. What does the liquibase script look like to do that?
The MySQL syntax is pretty straightforward:
ALTER TABLE mytable AUTO_INCREMENT = val ;
(Note that this is really a table attribute, not a column attribute. There can be only one column in a table declared to be AUTO_INCREMENT.)
This syntax isn't supported in SQL Server or Oracle; Oracle doesn't even have a concept of an "auto_increment" column, apart from a SEQUENCE object and a TRIGGER. SQL Server calls it an IDENTITY property. So I don't know how this statement would be represented in "liquibase" syntax, other than specifying that this statement is native MySQL syntax.
You can use addAutoIncrement (http://www.liquibase.org/documentation/changes/add_auto_increment.html) to change your existing AUTO_INCREMENT column.
Don't forget to specify columnDataType in the addAutoIncrement.
I used this yesterday for our project and it worked (for MySQL).

Restrictions on type ENUM not enough?

Can't find a straight answer to the following problem / question.
I created a database, and one of the fields is of type ENUM and restriction NOT NULL.
It works fine, but when I try to insert a record with a value that is not allowed for this field, the records is not rejected but inserted anyway with the field empty. That is, I think that it is an empty string (""), since I added the restriction NOT NULL.
I want the record of course rejected as a whole. How can I achieve that.
I assume sample code is not necessary since it is common knowledge.
If you insert an incorrect value into an ENUM column or if you force a value into an ENUM column with IGNORE, it is set to the reserved enumeration value of 0, which is displayed as an empty string in string context.
http://dev.mysql.com/doc/refman/5.1/en/constraint-enum.html
Try this:
SET sql_mode = 'STRICT_ALL_TABLES'; or STRICT_TRANS_TABLES
Depending on if your table is transactional or nontransactional. This should take care of it through mySQL and cause it to abort and rollback with an integrity constraint before the method even tries to operate.
I found that you should enable strict mode in mysql. To do this you should:
edit /etc/mysql/my.cnf
add/edit sql-mode = STRICT_ALL_TABLES
restart MySQL
This is solution on MySQL level. If you try inserting an empty value in an ENUM field, it should now be rejected.

Changing a data column from varchar(max) to nvarchar(max) in SQL Server 2008

I have to change the data type in a SQL Server 2008 table from varchar(max) to nvarchar(max). This table has data in it. Is there a way to change the data type without losing the data?
You can just use standard syntax to alter the table:
ALTER TABLE some_table ALTER COLUMN some_column nvarchar(max)
You will probably want to rebuild any indices however, to make sure they work as expected.
Another option to minimize disruption (since I don't believe the ALTER COLUMN will occur online), is:
ALTER TABLE dbo.table ADD new_column NVARCHAR(MAX); -- metadata operation
Now you can update the data in waves/batches/transactions instead of applying the change to the whole table in one long transaction. When you're satisfied that the data is copied over, you can drop the old column, rename the new one, and re-create any affected indexes (your MAX column can't be in the key of any index, but you might have inadvertently put it into an INCLUDE definition - if that is the case you should question that anyway).
You'll still want to rebuild all indexes to reclaim the now unused space (which you can do online if you're using Enterprise Edition).
Always take a backup so no matter what happens you can go back to the way things were.
With that said changing from varchar(max) to nvarchar(max) should not lose data.
Side note: you might have concerns if you were changing in the other direction nvarchar(max) to varchar(max) as the process would have to convert extended characters if any were present.
As of SQL Server 2016, this can now be an ONLINE operation
SQL 2016 ALTER COLUMN online