MYSQL insert null for not null default column - mysql

I have curious about why some not null column already set default value, but during insert sql script, it will throw error.
Here is the sample table
drop table if exists `delivery`;
create table `delivery`(
`price` BIGINT not null default 0,
`created_time` TIMESTAMP(6) not null default CURRENT_TIMESTAMP (6)
) ENGINE=INNODB DEFAULT CHARSET=UTF8MB4
;
Let's say, execute the three statement below, only the second statement will not throw error
insert into `delivery` (`price`,`created_time`) values (null, null);
insert into `delivery` (`price`,`created_time`) values (1, null);
insert into `delivery` (`price`,`created_time`) values (null, now());
So does it have anyway to insert null for bigint datatype column and make it execute success? And any ideas for the logic behind.

You can't insert null values since you have NOT NULL constraints on the columns.
The first and third statement throw an error since you are trying to insert a null value into the column price and/or created_time, and that clearly doesn't satisfy the constraint(s).
If you really want to allow null values, then remove the NOT NULL constraint on the column(s).
Alternatively, you could sucessfully run your SQL statements as shown below:
insert into `delivery` () values ();
insert into `delivery` (`price`) values (1);
insert into `delivery` (`created_time`) values (now());
select * from `delivery`;
Result:
price created_time
----- --------------------------
0 2020-04-16 09:48:23.505147
1 2020-04-16 09:48:25.549202
0 2020-04-16 09:48:26.0
EDIT:
The second query actually succeeds in MySQL 5.7; it silently ignores the explicit null value and uses the default value.
It seems that the behavior was fixed in MySQL 8.x since it fails now (as it should).

Related

mysql 5.7 timestamp default insert null error

I have the following create table statement.
CREATE TABLE `test_table` (
`id` INT(11) NOT NULL,
`field1` varchar(10),
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
);
when I do the following insert, I'll get the erro "Column 'updated_at' cannot be null"
insert into test_table (id, field1, updated_at) values (1234, 'foo', null);
I expected updated_at would just take on the default value in this case.
mysql version 5.7.12
However when I do this in mysql version 5.6, the insert commands works.
Is there a change in the versoin from 5.6 to 5.7? The only difference I thought was 5.7 has NO_ZERO_DATE default to true. But I thought that was only for datetime. Is there a configuration change that I need to make?
It's possible to achieve the result by not passing in updated_at but I don't have over insert statement in this case.
I suspect that this is related to SQL Strict mode - but I can't find the exact quote in the documentation that matches your use case.
Bottom line, you should not be expecting the server to use the default when you provide it with an explicit null value.
If you can't remove the column from the insert list for some reason, a possible workaround is to use the default keyword, which makes your intent unambiguous:
insert into test_table (id, field1, updated_at)
values (1234, 'foo', default);
This error is thrown because explicit_defaults_for_timestamp is enabled. Disabling this will solve the issue
Refer: https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_explicit_defaults_for_timestamp

How to keep the same "INSERT INTO" statements in my code when adding a new column in my database with the "nullable" property and a default value?

Let's consider a "User" MySQL table with 2 columns:
Auto increment id
Full name
CREATE TABLE `user` ( `id` INT NOT NULL AUTO_INCREMENT, `fullname` TEXT NOT NULL, PRIMARY KEY (`id`));
INSERT INTO `user` VALUES (NULL, 'John Smith');
INSERT INTO `user` VALUES (NULL, 'James Miller');
Everywhere I add a user in my application, I'm having this code:
INSERT INTO `user` VALUES (NULL, <name to insert>);
Now if I add a 'is_admin' boolean with 0 as default value, like so:
ALTER TABLE `user` ADD COLUMN `is_admin` TINYINT NOT NULL DEFAULT 0;
If I run my insert query with VALUES (NULL, <name to insert>), I expect MySQL to understand that I want new users to have is_admin set to 0, but it doesn't work:
Error Code: 1136. Column count doesn't match value count at row 1
I thought it was because of the 'NOT NULL' flag so I changed the 'ADD COLUMN' statement from 'NOT NULL' to 'NULL':
ALTER TABLE `user` ADD COLUMN `is_admin` TINYINT NULL DEFAULT 0;
Now it's pretty obvious how I want it to behave. I said the default value should be 0 and I didn't even set it to mandatory. But I still get the same error.
I just have to update all my INSERT INTO user occurences to:
INSERT INTO `user` VALUES (NULL, <name to insert>, 0);
OR
INSERT INTO `user` VALUES (NULL, <name to insert>, default);
In this example it looks like it's not a big deal, but on a big application with tens of INSERT statements, it's a big deal because at each version, you must modify all insert statements for all altered tables, and if you miss a single one, then it doesn't work anymore.
I worked many years with Oracle and maybe I'm wrong but I thought I remembered Oracle was using default values when not provided.
Is there any way to do the same with MySQL?
Always list the columns when doing an insert. So:
INSERT INTO user (id, fullname)
VALUES (NULL, 'John Smith');
That, in turn, is overkill. Just do:
INSERT INTO user (fullname)
VALUES ('John Smith');
This will set is_admin (and any other columns) to their default values.

MySQL Truncation Error

In one of my tables, I have a column with some null values and some integer values. When I use MySQL Workbench to set a default value and non-null for that column, I get a truncation error.
When my colleague performs the same operation, his apply works and the null value are set to 0.
The only obvious difference is that he is running MySQL Server 5.6 and I am running 5.5.
An example table can be created with the following CREATE:
CREATE TABLE 'resource`.`test_table` (
`idtest_table` INT NOT NULL ,
`bad_column` BIGINT(20) NULL ,
PRIMARY KEY (`idtest_table`) );
Insert some values as follows:
INSERT INTO `resource`.`test_table` (`idtest_table`) VALUES (1);
INSERT INTO `resource`.`test_table` (`idtest_table`) VALUES (2);
INSERT INTO `resource`.`test_table` (`idtest_table`) VALUES (3);
The command that is failing is:
ALTER TABLE `resource`.`test_table` CHANGE COLUMN `bad_column` `bad_column` BIGINT(20) NOT NULL DEFAULT 0 ;
with the following error:
ERROR 1265: Data truncated for column 'bad_column' at row 1
SQL Statement:
ALTER TABLE `resource`.`test_table` CHANGE COLUMN `bad_column` `bad_column` BIGINT(20) NOT NULL DEFAULT 0
ERROR: Error when running failback script. Details follow.
ERROR 1050: Table 'test_table' already exists
SQL Statement:
CREATE TABLE `test_table` (
`idtest_table` int(11) NOT NULL,
`bad_column` bigint(20) DEFAULT NULL,
PRIMARY KEY (`idtest_table`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Is there a setting in the MySQL config that allows this? Is it the version?
The error is occurring because bad_columns has a value of NULL after the insert.
You are changing the column type to "not NULL", so what can the database do? It can generate an error. The default value doesn't apply to existing rows.
If you want to do this, then update the column first:
update resource.test_table
set bad_column = 0
where bad_column is null;

Will ignoring the AUTO_INCREMENT in my table SQL have an effect?

Will ignoring the value AUTO_INCREMENT in my table SQL have an effect on my current content?
No, it won't.
15char
no..it won't effect anything..
AUTO_INCREMENT function is for make array number..it make all data which have been input automatically sequential..and also counting..from 1,2,3,..n..
No, it won't. An AUTO_INCREMENT will keep a counter so that you can INSERT a row without specifying a value for that column.
If you ignore the AUTO_INCREMENT and do explicitly state a value for the column, the counter will be updated. The next insert without explicit value will take the previous insert into account - you don't risk a duplicate value.
Testcase:
Create the table:
CREATE TABLE `counter` (
`1` int(11) NOT NULL auto_increment,
PRIMARY KEY (`1`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 ;
Insert a row, without stating the value:
INSERT INTO `test`.`counter` (`1` ) VALUES (NULL);
There will now be one row, with value 1.
Insert another row, without stating the value:
INSERT INTO `test`.`counter` (`1` ) VALUES (NULL);
There will now be two rows, 1 and 2.
Insert a row while explicitly stating the value:
INSERT INTO `test`.`counter` (`1` ) VALUES ('8');
You will now have three rows, 1, 2, 8
Now insert another row without stating the value:
INSERT INTO `test`.`counter` (`1` ) VALUES (NULL);
The new row will not have value 3 or 4, but the correct value 9:
SELECT * FROM `counter`;
1
2
8
9

MySQL, better to insert NULL or empty string?

I have a form on a website which has a lot of different fields. Some of the fields are optional while some are mandatory. In my DB I have a table which holds all these values, is it better practice to insert a NULL value or an empty string into the DB columns where the user didn't put any data?
By using NULL you can distinguish between "put no data" and "put empty data".
Some more differences:
A LENGTH of NULL is NULL, a LENGTH of an empty string is 0.
NULLs are sorted before the empty strings.
COUNT(message) will count empty strings but not NULLs
You can search for an empty string using a bound variable but not for a NULL. This query:
SELECT *
FROM mytable
WHERE mytext = ?
will never match a NULL in mytext, whatever value you pass from the client. To match NULLs, you'll have to use other query:
SELECT *
FROM mytable
WHERE mytext IS NULL
One thing to consider, if you ever plan on switching databases, is that Oracle does not support empty strings. They are converted to NULL automatically and you can't query for them using clauses like WHERE somefield = '' .
One thing to keep in mind is that NULL might make your codepaths much more difficult. In Python for example most database adapters / ORMs map NULL to None.
So things like:
print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow
might result in "Hello, None Joe Doe!" To avoid it you need something like this code:
if databaserow.title:
print "Hello, %(title)s %(firstname) %(lastname)!" % databaserow
else:
print "Hello, %(firstname) %(lastname)!" % databaserow
Which can make things much more complex.
Better to Insert NULL for consistency in your database in MySQL. Foreign keys can be stored as NULL but NOT as empty strings.
You will have issues with an empty string in the constraints.
You may have to insert a fake record with a unique empty string to satisfy a Foreign Key constraint. Bad practice I guess.
See also: Can a foreign key be NULL and/or duplicate?
I don't know what best practice would be here, but I would generally err in favor of the null unless you want null to mean something different from empty-string, and the user's input matches your empty-string definition.
Note that I'm saying YOU need to define how you want them to be different. Sometimes it makes sense to have them different, sometimes it doesn't. If not, just pick one and stick with it. Like I said, I tend to favor the NULL most of the time.
Oh, and bear in mind that if the column is null, the record is less likely to appear in practically any query that selects (has a where clause, in SQL terms) based off of that column, unless the selection is for a null column of course.
If you are using multiple columns in a unique index and at least one of these columns are mandatory (i.e. a required form field), if you set the other columns in the index to NULL you may end up with duplicated rows. That's because NULL values are ignored in unique columns. In this case, use empty strings in the other columns of the unique index to avoid duplicated rows.
COLUMNS IN A UNIQUE INDEX:
(event_type_id, event_title, date, location, url)
EXAMPLE 1:
(1, 'BBQ', '2018-07-27', null, null)
(1, 'BBQ', '2018-07-27', null, null) // allowed and duplicated.
EXAMPLE 2:
(1, 'BBQ', '2018-07-27', '', '')
(1, 'BBQ', '2018-07-27', '', '') // NOT allowed as it's duplicated.
Here are some codes:
CREATE TABLE `test` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`event_id` int(11) DEFAULT NULL,
`event_title` varchar(50) DEFAULT NULL,
`date` date DEFAULT NULL,
`location` varchar(50) DEFAULT NULL,
`url` varchar(200) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `event_id` (`event_id`,`event_title`,`date`,`location`,`url`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Now insert this to see it will allow the duplicated rows:
INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`,
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);
INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`,
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-27', NULL, NULL);
Now insert this and check that it's not allowed:
INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`,
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');
INSERT INTO `test` (`id`, `event_id`, `event_title`, `date`, `location`,
`url`) VALUES (NULL, '1', 'BBQ', '2018-07-28', '', '');
So, there is no right or wrong here. It's up to you decide what works best with your business rules.