I've created a table with some NOT NULL columns using phpMyAdmin.
CREATE TABLE `TEST` (`ID` INT PRIMARY KEY AUTO_INCREMENT,
`Firstname` VARCHAR(20) NOT NULL,
`Lastname` VARCHAR(20) NOT NULL)
There is no problem with INSERT operation. Database prevent to set a NULL field properly.
INSERT INTO `TEST`(`Firstname`, `Lastname`) VALUES ("Peter", null)
#1048 - Column 'Lastname' cannot be null
The accepted one is:
INSERT INTO `TEST`(`Firstname`, `Lastname`) VALUES ("Peter", "Smith")
1 row inserted.
Inserted row id: 1 (Query took 0.0004 sec)
But after I've created a record with non-NULL fields successfully, database allows me to UPDATE these fields to NULL.
UPDATE `TEST` SET `Lastname`=NULL WHERE `ID` = 1
1 row affected. (Query took 0.0006 sec)
I've tried "NULL" and 'NULL' as well, but database put them in the field as a string.
I'm really confused about this issue. Is this a phpMyAdmin bug or I'm doing something wrong?
You must not have SQL_MODE set to strict on your installation.
Issue
SET SQL_MODE='STRICT_ALL_TABLES'
or add
SQL_MODE='STRICT_ALL_TABLES'
under [mysqld] into your my.cnf
To find my.cnf, look in the MySQL config file C:\xampp\mysql\bin\my.ini.
At the top of that file are some comments:
# You can copy this file to
# C:/xampp/mysql/bin/my.cnf to set global options,
# mysql-data-dir/my.cnf to set server-specific options (in this
# installation this directory is C:/xampp/mysql/data) or
# ~/.my.cnf to set user-specific options.
There it tells you where to find your my.cnf file.
Restart your mysql if necessary.
Maybe you have the rights to change the SQL mode via phpMyAdmin. Go the home (starting) page of phpMyAdmin, then click on Variables and enter "SQL mode" in the filter. Then you have access to some explanations via the question mark, and by clicking on this line you can edit the value of SQL mode and save it.
However this would be just for testing purposes, at the setting will revert to its original value once the server is restarted; hence the need to change the configuration file.
Related
On azure I created a new MySQL Database instance. In this db I create a table using this script:
CREATE TABLE ROLES(
ID INTEGER PRIMARY KEY AUTO_INCREMENT,
ROLE_NAME VARCHAR(30) NOT NULL
);
Then I insert values using this script:
INSERT INTO `beezzy`.`roles` (`ROLE_NAME`) VALUES ('admin');
INSERT INTO `beezzy`.`roles` (`ROLE_NAME`) VALUES ('owner');
INSERT INTO `beezzy`.`roles` (`ROLE_NAME`) VALUES ('consultant');
after execution table contains such rows:
Why DB generates IDs like '11' and '21'?
I run the same script on my local machine and everything works fine. IDs was '1', '2', '3'
Please run the following query.
SELECT ##auto_increment_increment
If the value is more than 1 then set it to 1 by the following query:
SET ##auto_increment_increment=1;
Note: This change is visible for the current connection only.
EDIT:
In order to set it globally so that other connections can also see the change you need to set it for global and session too.
SET ##GLOBAL.auto_increment_increment = 1;
SET ##SESSION.auto_increment_increment = 1;
So other connections can see this change now.
More:
This value will be reset if you restart your MySQL server. In order to make this change permanent you need to write this variable under [mysqld] secion in your my.cnf [for linux] or my.ini [for windows] file.
[mysqld]
auto-increment-increment = 1
Your autoincrement is probably 10, however this is probably by design. Azure uses ClearDB which uses an autoincrement of 10 with a reason: namely replication.
When I use auto_increment keys (or sequences) in my database, they
increment by 10 with varying offsets. Why?
ClearDB uses circular replication to provide master-master MySQL
support. As such, certain things such as auto_increment keys (or
sequences) must be configured in order for one master not to use the
same key as the other, in all cases. We do this by configuring MySQL
to skip certain keys, and by enforcing MySQL to use a specific offset
for each key used. The reason why we use a value of 10 instead of 2 is
for future development.
You should not change the autoincrement value.
cleardb faq
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.
On azure I created a new MySQL Database instance. In this db I create a table using this script:
CREATE TABLE ROLES(
ID INTEGER PRIMARY KEY AUTO_INCREMENT,
ROLE_NAME VARCHAR(30) NOT NULL
);
Then I insert values using this script:
INSERT INTO `beezzy`.`roles` (`ROLE_NAME`) VALUES ('admin');
INSERT INTO `beezzy`.`roles` (`ROLE_NAME`) VALUES ('owner');
INSERT INTO `beezzy`.`roles` (`ROLE_NAME`) VALUES ('consultant');
after execution table contains such rows:
Why DB generates IDs like '11' and '21'?
I run the same script on my local machine and everything works fine. IDs was '1', '2', '3'
Please run the following query.
SELECT ##auto_increment_increment
If the value is more than 1 then set it to 1 by the following query:
SET ##auto_increment_increment=1;
Note: This change is visible for the current connection only.
EDIT:
In order to set it globally so that other connections can also see the change you need to set it for global and session too.
SET ##GLOBAL.auto_increment_increment = 1;
SET ##SESSION.auto_increment_increment = 1;
So other connections can see this change now.
More:
This value will be reset if you restart your MySQL server. In order to make this change permanent you need to write this variable under [mysqld] secion in your my.cnf [for linux] or my.ini [for windows] file.
[mysqld]
auto-increment-increment = 1
Your autoincrement is probably 10, however this is probably by design. Azure uses ClearDB which uses an autoincrement of 10 with a reason: namely replication.
When I use auto_increment keys (or sequences) in my database, they
increment by 10 with varying offsets. Why?
ClearDB uses circular replication to provide master-master MySQL
support. As such, certain things such as auto_increment keys (or
sequences) must be configured in order for one master not to use the
same key as the other, in all cases. We do this by configuring MySQL
to skip certain keys, and by enforcing MySQL to use a specific offset
for each key used. The reason why we use a value of 10 instead of 2 is
for future development.
You should not change the autoincrement value.
cleardb faq
I have integer fields in a table. The POSTs are sent by a complicated JavaScript. They send empty strings like "" but as you guessed MySQL doesn't allow empty strings in integer fields. Are there any options to allow empty strings? Like if it takes an empty string it will save it as NULL.
There are 2 ways to do this.
For Current Mysql Session (Temporary Solution)
First execute query to get current SQL mode of your mysql server.
mysql> SELECT ##sql_mode;
+----------------------------------------------------------------+
| ##sql_mode |
+----------------------------------------------------------------+
|STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+----------------------------------------------------------------+
1 row in set (0.00 sec)
If result contains STRICT_TRANS_TABLES, you have to remove that value to allow insert query to pass NULL value. Make sure your mysql User have privileges to apply this changes and restart Mysql Server after applying this.
SET GLOBAL sql_mode = '';
For Life Time of Mysql (Permanent Solution)
You have to update my.cnf file. Location of that file is : \etc\my.cnf or \etc\mysql\mysql.cnf
There will be some default parameters set under [mysqld] like
[mysqld]
innodb_file_per_table=1
default-storage-engine=MyISAM
performance-schema=0
max_allowed_packet=268435456
open_files_limit=10000
Just add one line under that
sql-mode=""
Make sure to restart Mysql Server after changing this file. Normally root user will be the owner of file so you have to login with root user on server.
For more details to understand what this SQL mode do.
STRICT_TRANS_TABLES
Enable strict SQL mode for transactional storage engines, and when possible for non-transactional storage engines. For details, see Strict SQL Mode.
Refer : http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_strict_trans_tables
NO_AUTO_CREATE_USER
Prevent the GRANT statement from automatically creating new user accounts if it would otherwise do so, unless authentication information is specified. The statement must specify a nonempty password using IDENTIFIED BY or an authentication plugin using IDENTIFIED WITH.
Refer: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_auto_create_user
NO_ENGINE_SUBSTITUTION
Control automatic substitution of the default storage engine when a statement such as CREATE TABLE or ALTER TABLE specifies a storage engine that is disabled or not compiled in.
Refer : http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_engine_substitution
Removing sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" from my.ini has solved the issue.
Edit: Removing the line above works but it is a bad idea. It allows to have things like 0000-00-00 or empty string dates. Better keep the line above and don't insert empty sting into an integer field, instead convert empty string into NULL and then insert that NULL into integer field.
Assuming that the column allows for NULL values, you must explicitly tell MySQL to use a value of NULL, rather than passing an empty string (which is cast to 0):
INSERT INTO table (column_name) VALUES (NULL);
I have a MySql table with a field defined as:
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
On my local machine, I can run:
INSERT INTO mytbl (id, user_id, created) VALUES(88882341234, 765, null);
SELECT id, user_id, created FROM mytbl WHERE id = '88882341234';
And then 'created' will show something like '2014-06-13 21:16:42'.
But on my staging server, if I run the same queries, I get this error:
Column 'created' cannot be null.
The schemas of the tables are the same (across local and staging), which I ensured via mysqldump (to clone the table before running this test).
I'm running MySql 5.6.17 on both machines. I've also ensured that both have the same sql_mode.
What could be the problem?
P.S. For people who don't know why I'd be setting a non-nullable field's value to null, MySql Docs say:
In addition, you can initialize or update any TIMESTAMP column to the
current date and time by assigning it a NULL value, unless it has been
defined with the NULL attribute to permit NULL values.
I found what the problem was. The MySql variable/parameter explicit_defaults_for_timestamp was OFF on my local machine but ON on my remote machine.
I visited my AWS RDS Parameter Groups page and changed explicit_defaults_for_timestamp from 1 to 0.
Then I went to my AWS RDS instances page to watch when "Parameter Group" changed from "Applying" to "pending-reboot".
Then I rebooted the particular instance.
These links helped me:
https://stackoverflow.com/a/23392448/470749
How to import MySQL binlog that contains INSERTs of a TIMESTAMP field with default value CURRENT_TIMESTAMP
https://forums.aws.amazon.com/thread.jspa?threadID=132676
The main problem is that the INSERT is just wrong: it's trying to insert a NULL into a non-nullable column.
What you should do is simply fix the query:
INSERT INTO mytbl (id, user_id) VALUES(88882341234, 765);
The reason this causes an error only on the staging server is that the server operates in strict SQL mode and therefore immediately aborts when you try to insert an incorrect value into created.
You can easily check the SQL mode in effect with SELECT ##SESSION.sql_mode and change it (perhaps so you can reproduce the error on your own server) with
SET SESSION sql_mode = 'STRICT_ALL_TABLES'