Restrictions on type ENUM not enough? - mysql

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.

Related

Mysql: Not getting an error when updating a NOT NULL column to null

Why does mysql accepts null data when updating a not null column and then converts the data to 0.
I am expecting an error it just does not show up. How can I get an error if someone tries to update a not null column to null? I need it so I can rollback the transaction if I get an error.Is there any configuration needed within the database to do this? Thank you
You've not specified which version of Mysql you're using, and in which mode. I'll answer this assuming you're running Mysql 5.7 without strict 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.
If strict mode is not in effect, MySQL inserts adjusted values for invalid or missing values and produces warnings (see Section 13.7.5.40, “SHOW WARNINGS Syntax”). In strict mode, you can produce this behavior by using INSERT IGNORE or UPDATE IGNORE.
Source: https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sql-mode-full
I recommend you to enable strict mode (STRICT_ALL_TABLES) and fix your application to support it; this will also enforce other query limitations where people are most commonly hit by ONLY_FULL_GROUP_BY.
To set the SQL mode at server startup, use the --sql-mode="modes" option on the command line, or sql-mode="modes" in an option file such as my.cnf (Unix operating systems) or my.ini (Windows). modes is a list of different modes separated by commas. To clear the SQL mode explicitly, set it to an empty string using --sql-mode="" on the command line, or sql-mode="" in an option file.
To change the SQL mode at runtime, set the global or session sql_mode system variable using a SET statement:
SET GLOBAL sql_mode = 'modes';
SET SESSION sql_mode = 'modes';
Source: https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sql-mode-setting
Why does mysql accepts null data when updating a not null column and
then converts the data to 0.
You question is not clear as we need the DDL of the table and the update , but as from what you are saying, Well logically because the column not null has a default value 0. check the below example.
create table Test_table ( name varchar(100) null , position_s varchar(100) default 'Y' not null)
SQL>
Table created
insert into Emp_table (name) values('Me')
SQL>
1 row inserted
SQL>
NAME POSITION_S
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Me Y
#aaron0207 #Moudiz I am using laravel and updates data like this.
$specificReservation = Reservation::where('reference_id',$reference_id)->first();
$specificReservation->res_status = 1;
$specificReservation->payment_id = null;
$specificReservation->save();
I also tried to update manually in the database with this
UPDATE reservations SET payment_id = null
and it also shows no error so I think this is a database problem.

When to use strict mode in MySql or MariaDB

I can find plenty of information on what strict mode does in MySql and MariaDB, but nothing on when to use it. This is common sense to a degree, but I would still like to have some general guidelines. For example, perhaps you:
Always use strict mode
Never use strict mode
Always use strict mode on tables that have financial data
etc
First, from MySQL documentation:
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.
So, as #rick-james said: Always use strict mode. That is, until you get fed up with its restrictions. The mode is there to help you, but it may be painful.
Strict mode is also default on MariaDB since >10.2.3.
Get current mode: SHOW VARIABLES LIKE 'sql_mode';
Disable: mysql> SET sql_mode = '';
Enable: mysql> SET sql_mode = 'STRICT_ALL_TABLES'; (or STRICT_TRANS_TABLES).
For permanent change edit /etc/mysql/my.conf, [mysqld] section, sql_mode= variable.

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.

Why does MySQL inserts blank data in not null fields

I just wanted to know if somebody could explain this.
I was just testing my code and didn't check for empty input fields (I know I have to, but just testing).. In my database table, all the fields are NOT NULL, and I was expecting a exception because I wasn't inserting anything.. But it turns out that MySQL inserts all with blank values, also, from MySQL workbench is the same thing..
Is there a way to prevent this? (From a MySQL perspective)
This behavior, although atypical, is quite well documented:
Inserting NULL into a column that has been declared NOT NULL. For
multiple-row INSERT statements or INSERT INTO ... SELECT statements,
the column is set to the implicit default value for the column data
type. This is 0 for numeric types, the empty string ('') for string
types, and the “zero” value for date and time types. INSERT INTO ...
SELECT statements are handled the same way as multiple-row inserts
because the server does not examine the result set from the SELECT to
see whether it returns a single row. (For a single-row INSERT, no
warning occurs when NULL is inserted into a NOT NULL column. Instead,
the statement fails with an error.)
So, if you want to get an error, use VALUES() with a single row. Alternatively, define a trigger that does the check.
Why does MySQL work this way? I don't know, to differentiate itself from other databases and prevent ANSI-compatibility? More seriously, I assume that this a question of efficiency, and related to the fact that MySQL does not implement check constraints. The NOT NULL declaration is just an example of a check constraint, and these are not supported.

What does MySQL converting varchar to char?

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.