If you are explicitly setting the value to NULL in your insert, but want MySQL to replace the NULL with 0, one way to do that is to define the column to allow NULL in the CREATE TABLE statement, and then replace the NULL with a TRIGGER.
Something like this:
CREATE TABLE `listings` (
`ListingID` int(11) NOT NULL,
`BathsFull` int(6) NULL DEFAULT 0,
PRIMARY KEY (`ListingID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
delimiter $$
create trigger tr_b_ins_listings before insert on listings for each row
begin
set new.BathsFull = coalesce(new.BathsFull,0);
end $$
delimiter ;
Try it for yourself in this SQL Fiddle
Answer from Ike Walker on Stack OverflowIf you are explicitly setting the value to NULL in your insert, but want MySQL to replace the NULL with 0, one way to do that is to define the column to allow NULL in the CREATE TABLE statement, and then replace the NULL with a TRIGGER.
Something like this:
CREATE TABLE `listings` (
`ListingID` int(11) NOT NULL,
`BathsFull` int(6) NULL DEFAULT 0,
PRIMARY KEY (`ListingID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
delimiter $$
create trigger tr_b_ins_listings before insert on listings for each row
begin
set new.BathsFull = coalesce(new.BathsFull,0);
end $$
delimiter ;
Try it for yourself in this SQL Fiddle
You can definitely use a trigger for that
Assuming that you make the field nullable
CREATE TABLE `listings` (
`ListingID` int(11) NOT NULL,
`BathsFull` int(6), <-----
PRIMARY KEY (`ListingID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Trigger
DELIMITER $$
CREATE TRIGGER tg_lst_insert BEFORE INSERT ON listings
FOR EACH ROW
BEGIN
SET NEW.BathsFull = IFNULL(NEW.BathsFull, 0);
END $$
DELIMITER ;
Inserting some rows
INSERT INTO `listings` VALUES(1, '');
INSERT INTO `listings` VALUES(3, 'a');
INSERT INTO `listings` VALUES(4, NULL);
INSERT INTO `listings` (ListingID) VALUES(2);
INSERT INTO `listings` VALUES(5, 3);
Result
+-----------+-----------+
| ListingID | BathsFull |
+-----------+-----------+
| 1 | 0 |
| 2 | 0 |
| 3 | 0 |
| 4 | 0 |
| 5 | 3 |
+-----------+-----------+
mysql - Field both NOT NULL and DEFAULT NULL - Database Administrators Stack Exchange
mysql - What is the default value for a field if no default value is provided? - Stack Overflow
VARCHAR/CHAR.. column NOT NULLABLE but DEFAULT NULL may should show Default NULL(not blank) in table structure view
Mysql: Unable to drop a columns NULL default - Database Administrators Stack Exchange
I couldn't find this behavior described in the official MySQL documentation
A few minutes of looking in the MySQL docs found this:
Column values can be given in several ways:
If you are not running in strict SQL mode, any column
not explicitly given a value is set to its default
(explicit or implicit) value. For example, if you specify a
column list that does not name all the columns in the
table, unnamed columns are set to their default values.
Default value assignment is described in Section 11.6,
โData Type Default Valuesโ. See also Section 1.8.3.3,
โConstraints on Invalid Dataโ.
If you want an INSERT statement to generate an error unless
you explicitly specify values for all columns that do not
have a default value, you should use strict mode. See
Section 5.1.7, โServer SQL Modesโ.
Use SQL mode STRICT_ALL_TABLES per http://dev.mysql.com/doc/refman/5.6/en/sql-mode.html#sqlmode_strict_all_tables.
Referring to the manual,
For data entry for a NOT NULL column that has no explicit DEFAULT clause, if an INSERT or REPLACE statement includes no value for the column, or an UPDATE statement sets the column to NULL, MySQL handles the column according to the SQL mode in effect at the time:
- If strict SQL mode is not enabled, MySQL sets the column to the implicit default value for the column data type.
- If strict mode is enabled, an error occurs for transactional tables and the statement is rolled back. For nontransactional tables, an
error occurs, but if this happens for the second or subsequent row of a multiple-row statement, the preceding rows will have been inserted.
So your question now may be, what are the implicit default values for the various column data types? Here you go:
Implicit defaults are defined as follows:
- For numeric types, the default is 0, with the exception that for integer or floating-point types declared with the AUTO_INCREMENT
attribute, the default is the next value in the sequence.- For date and time types other than TIMESTAMP, the default is the appropriate โzeroโ value for the type. For the first TIMESTAMP column in a table, the default value is the current date and time. See Section 10.3, โDate and Time Typesโ.
- For string types other than ENUM, the default value is the empty string. For ENUM, the default is the first enumeration value.
There IS no default value unless you specify one (i.e. unless you define a "default constraint" for the column in question).
Here's an example for adding a default on an existing column:
ALTER TABLE dbo.customer ALTER COLUMN contactname SET DEFAULT 'Unknown'
Here's an example creating the table with a default:
CREATE TABLE Books (
ID SMALLINT NOT NULL,
Name VARCHAR(40) NOT NULL,
PubID SMALLINT NOT NULL DEFAULT 0
)
It's good practice to declare ALL columns "not null", and provide default constraints as appropriate.
In the "books" example above, if you "insert" without specifying PubID, the PubID will be zero.
In the same example, if you "insert" without specifying ID or Name ... you'll get an error.
If you want MySQL to auto-assign an ID, use this syntax instead:
CREATE TABLE Books (
ID SMALLINT NOT NULL AUTO_INCREMENT,
Name VARCHAR(40) NOT NULL,
PubID SMALLINT NOT NULL DEFAULT 0
)
The answer is to use the following (slightly odd) syntax:
ALTER TABLE items ALTER ordering DROP DEFAULT;
When trying to modify a column with ALTER TABLE, there are 4 keywords that can be used, each with different capabilities:
CHANGE [COLUMN]MODIFY [COLUMN]RENAME COLUMNALTER [COLUMN]
CHANGE is a MySQL extension to standard SQL. MODIFY and RENAME COLUMN are MySQL extensions for Oracle compatibility.
ALTER [COLUMN] is standard SQL (I think).
The docs about ALTER TABLE have more details:
Renaming, Redefining, and Reordering Columns
The
CHANGE,MODIFY,RENAME COLUMN, andALTERclauses enable the names and definitions of existing columns to be altered. They have these comparative characteristics:
CHANGE:
- Can rename a column and change its definition, or both.
- Has more capability than
MODIFYorRENAME COLUMN, but at the expense of convenience for some operations.CHANGErequires naming the column twice if not renaming it, and requires respecifying the column definition if only renaming it.- With
FIRSTorAFTER, can reorder columns.
MODIFY:
- Can change a column definition but not its name.
- More convenient than
CHANGEto change a column definition without renaming it.- With
FIRSTorAFTER, can reorder columns.
RENAME COLUMN:
- Can change a column name but not its definition.
- More convenient than
CHANGEto rename a column without changing its definition.
ALTER:
- Used only to change a column default value.
In this case, you have 3 options:
ALTER TABLE items
CHANGE ordering ordering int NOT NULL;
ALTER TABLE items
MODIFY ordering int NOT NULL;
ALTER TABLE items
ALTER ordering DROP DEFAULT ;
Use the DEFAULT keyword instead:
INSERT INTO users (TimeZoneId) VALUES (DEFAULT);
Do not insert NULL values. I'm assuming you were trying this syntax:
INSERT INTO users VALUES (null, 'Jones', 'yarg', 1, null, null, null);
Instead, use this syntax:
INSERT INTO users SET UniqueName='Jones', Password='yarg';
For more info, see the MySQL docs on INSERT.
I've been developing PHP / MySQL web based applications for 15 years (hand coded. no frameworks) and only this week, have I discovered 'strict mode' when the Host that I host most of my apps on ran updates overnight and MySQL is now in strict mode on their servers. (rude shock in the morning)
I've always had no default value for my table columns and set to not nullable and MySQL has taken care of the INSERT when the value was not supplied.
Now with many apps broken, I am frantically going through all the tables in my apps, adding default values, adding '0' for INTEGER and '1970-01-01' for DATE (and updating my display code to test for '1970-01-01' instead of testing for '0000-00-00').
My question is what to do for VARCHAR and TEXT columns. Should I have an empty string as the default, or should I make them nullable? I've been searching the internet since yesterday with most advice (from years ago with the upgrade to 5.7) and most of what I find just suggests to turn strict mode off again. This is not a viable solution.
If I choose NULL I will have to update some display code that tests for empty string, but is choosing empty string as a default, a safe and viable option?
Any advice on these two options or other alternatives would be greatly appreciated. Cheers.
To insert the default value, you have to not specify any value for the column, not even NULL, because NULL is a specific value.
NULL is a correct value for any mysql column / type.
you can set the column to NOT NULL or you need to resolve it in your scripting language, so the null does not get inserted.
Are you using a framework where objects are automatically converted into SQL statements for saving? If the value of the property in your PHP class is not set and the column is nullable then it will insert null instead of 0.
Consider:
class Foo{
protected $propertyName;
}
That is equivalent in PHP to
class Foo{
protected $propertyName = null;
}
If the TINYINT(4) column for propertyName is nullable when it builds the query to save the data it will save as null in the database. If you are using a design pattern like this you need set the default value in the PHP class itself. Something like
class Foo{
protected $propertyName = 0;
}
Note, if the column is not null-able then saving the object would throw an error in this scenario. If you wanted to get fancy, you can fetch the default values for a column using
DESC tableName;
That will return information about the table, there will be a column NULL which will be YES or NO (describing if the column is null-able). And a column Default which will be the default value (or NULL if there is none). You could then populate null fields in your class based on the default values from the database. You would want to be careful here as there are likely some columns that should be NULL. Ideally, you would make any fields that can't accept null non-nullable and then key your logic for handling defaults only fire when the Null column is NO.
When inserting a new row, the default value for a column with an expression default can be inserted either by omitting the column name or by specifying the column as
DEFAULT(just as for columns with literal defaults).
source: https://dev.mysql.com/doc/refman/8.0/en/data-type-defaults.html
In case you specify NULL for the column on INSERT MySQL try to set the NULL for the column (and fails in case of NOT NULL). You have to ommit the column on INSERT or using DEFAULT as value on the INSERT statement.
See the following example:
CREATE TABLE test (
col1 INT DEFAULT 0 NOT NULL,
col2 INT DEFAULT 0 NULL,
col3 INT NULL
);
-- doesn't work since col1 can't be NULL
INSERT INTO test VALUES (NULL, NULL, NULL)
-- is working: col1 is 0 after INSERT, col2 IS NULL
INSERT INTO test (col2, col3) VALUES (NULL, NULL)
-- is working: col1 is 0 after INSERT, col2 IS 0 - because using DEFAULT instead of NULL.
INSERT INTO test (col2, col3) VALUES (DEFAULT, NULL)