I have created a database table like this:
CREATE TABLE test(
name VARCHAR(30) NOT NULL,
password VARCHAR(40) NOT NULL);
I then added to it like this, which failed as expected.
INSERT INTO test(name, password) VALUES ('test', NULL);
But then when I tried this it inserted without a problem:
INSERT INTO test(name) VALUES ('test');
I tried to create the table differently but it didn't create:
CREATE TABLE test(
name VARCHAR(30) NOT NULL,
password VARCHAR(40) NOT NULL DEFAULT NULL );
So is there a way to get that to create an error when inserting?
Perhaps associated I think I will need to do something else to be able to validate data input into the database anyway and I think I saw something about constraints but I don't think these are supported in mysql? So is the null check and validation something I can't do the database with mysql?
By default, MySQL replaces implicit NULL values with zeroes (or empty strings for string datatypes).
You can work around this by enabling strict mode for your session or server:
SET sql_mode='STRICT_ALL_TABLES'
or add
sql_mode='STRICT_ALL_TABLES'
under [mysqld] in your my.cnf.
Related
This is my query:
INSERT INTO tabla (campo1,campo2,campo3) VALUES ('$campo1','$campo2','$campo3')
Since 'tabla' has many more columns and some of them are not null and neither have a default value, I'm getting the mysql message: "Fiel 'column4' doesn't have a default value".
I'm running that on my local server, tried it out at online server and it does insert the row with no issues.
Does anyone knows if this has to do with some sort of configuration of the mysql.ini file or something like that? There are too many columns like that on my db, so changing columns to 'null' or set them a default value would take a lot of time. I think it could be fixed as it works perfect on the server.
Thanks.
UPDATE:
It is the SQL mode. I queried SELECT ##GLOBAL.sql_mode;
My local server returned: STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
The remote server returned an empty row.
Where can I change that setting on my localhost?
If you are sure that you are using the same schema both locally and on the remote server, it's probably the SQL mode of the remote server that's set different than the local SQL mode, you can check it with one of those:
SELECT ##GLOBAL.sql_mode;
SELECT ##SESSION.sql_mode;
This will reproduce the problem:
CREATE TABLE tabla (
campo1 VARCHAR(255) NOT NULL,
campo2 VARCHAR(255) NOT NULL,
campo3 VARCHAR(255) NOT NULL,
campo4 VARCHAR(255) NOT NULL);
SET ##SESSION.sql_mode= 'STRICT_TRANS_TABLES';
INSERT INTO table (campo1, campo2, campo3) VALUES ('a', 'b', 'c');
and this will work, even if there's a column costraint on campo4:
CREATE TABLE tabla (
campo1 VARCHAR(255) NOT NULL,
campo2 VARCHAR(255) NOT NULL,
campo3 VARCHAR(255) NOT NULL,
campo4 VARCHAR(255) NOT NULL);
SET ##SESSION.sql_mode= '';
INSERT INTO table (campo1, campo2, campo3) VALUES ('a', 'b', 'c');
Please see fiddle here.
Have a look at the manual at the Server SQL Modes page.
This weird behavior might depend on "sql_mode" system variable - it controls vast amount of quirks and settings.
So, check the mode by running select ##sql_mode; command on your both servers - it must output different values, so you know what mode is used on your local server.
If the column is not null you must provide its value when inserting record. There is no other way - it is not null just for forcing ANY data in it (even if its just EMPTY string. But you must provide it in the insert query.
You may add default value for the column.
Try importing remote table to your local one - that will minimize future problems with schema.
I have been testing a database i am doing right now and i am noticing that it is letting me insert null values into fields that are part of a primary key, despite stating in the script that the value of the field should be NOT NULL. I am using MAC's MySQL Workbench, and I have been googling around and can't figure out why this is happening. (Maybe I am too brain-fried right now... I am even starting to doubt myself)
Part of the script of the database creation (these are the tables I have tested..):
DROP DATABASE IF EXISTS solytierra ;
CREATE DATABASE IF NOT EXISTS solytierra DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
USE solytierra ;
DROP TABLE IF EXISTS solytierra.Cliente ;
CREATE TABLE IF NOT EXISTS solytierra.Cliente (
CIF VARCHAR(25) NOT NULL,
Nombre VARCHAR(100) NULL,
EmailGeneral VARCHAR(45) NULL,
Web VARCHAR(45) NULL,
Notas VARCHAR(150) NULL,
insertado Timestamp,
CONSTRAINT pk_Cliente PRIMARY KEY (CIF)
) ENGINE=InnoDB;
DROP TABLE IF EXISTS solytierra.PersonaContacto ;
CREATE TABLE IF NOT EXISTS solytierra.PersonaContacto (
Cliente_CIF VARCHAR(25) NOT NULL,
Nombre VARCHAR(50) NOT NULL,
Apellidos VARCHAR(100) NOT NULL,
Notas VARCHAR(150) NULL,
CONSTRAINT pk_PersonaContacto PRIMARY KEY (Cliente_CIF , Nombre , Apellidos),
CONSTRAINT fk_PersonaContacto_Cliente FOREIGN KEY (Cliente_CIF)
REFERENCES solytierra.Cliente (CIF)
ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB;
...
It will let me create Clients without CIF, "PersonaContacto" without Cliente_CIF or without "Nombre"....
I have also tested other databases that i already had that used to work and it is happening the same in an all them.
Got it!!
I don't know what sql mode i was running on by default, but with this:
SET sql_mode = TRADITIONAL;
It is now running perfectly! I didn't know that there were different sql modes! Thanks a lot to everyone for your time and efforts! It really helped me to see that the problem was in my workbench, not the code and look for the answer accordingly! I hope this thread will be useful for future beginners like me!
If the value being stored in the column CIF is actually a NULL, then the expression LENGTH(CIF) should also return NULL. (If it's a zero length string, then LENGTH(CIF) will return 0.
To verify:
SELECT c.CIF, LENGTH(c.CIF) FROM solytierra.Cliente c ;
SELECT c.CIF FROM solytierra.Cliente c WHERE c.CIF IS NULL;
If you are running an INSERT statement, I can't explain the behavior you are observing, either MySQL allowing a NULL value to be stored or MySQL providing an implicit default value.)
If it's a zero length string being stored, that's the behavior we would expect if the columns were not explicitly declared to be NOT NULL but were later declared to part of the primary key. It's also the behavior we'd expect if the column were defined NOT NULL DEFAULT ''.
When the NOT NULL is omitted from the column declaration and the column is later declared to be part of the PRIMARY KEY, MySQL will use an an implicit default value based on the datatype of the column (zero length string for VARCHAR, zero for an integer, etc.)
But I'm not able to reproduce the problem you report, with the table definitions you've posted.
I recommend you check the table definition by getting the output from:
SHOW CREATE TABLE solytierra.Cliente;
I have a table 'user' already in db with fields
create Table user (
id INT(6) NOT NULL AUTO_INCREMENT PRIMARY KEY,
username varchar(20) NOT NULL,
password varchar(20) NOT NULL,
profilename varchar(20) NOT NULL,
email varchar(40) NOT NULL,
socialemail varchar(40) NOT NULL)engine=InnoDB;
The stated columns also contain values
I altered the table and added some more columns
ALTER TABLE user
ADD COLUMN enabled varchar(1),
ADD COLUMN accountnonexpired varchar(1),
ADD COLUMN credentialsnonexpired varchar(1),
ADD COLUMN accountnonlocked varchar(1);
Now when I am inserting values into new columns with the below command in MYSQL.
insert into user
(id,enabled,accountnonexpired,credentialsnonexpired,accountnonlocked) values ('1','Y','Y','Y','Y'),('2','Y','Y','Y','Y');
I am getting an error
Error Code: 1364. Field 'username' doesn't have a default value
Can anyone tell me why?
What should be the correct way to insert values in new columns?
INSERT adds new rows to your table, and those rows would have to have a non-null username for the INSERT to succeed It's not 100% clear but I think you are saying that you want to set the values of these new columns for all your existing rows. To do that you need UPDATE not INSERT:
UPDATE user SET id='1', enabled = 'Y', accountnonexpired = 'Y' WHERE 1
I omitted a few of your columns for brevity but you get the idea. You may also want to alter the table to make these values the DEFAULT for new rows inserted in the future.
Your table has NOT NULL set for the [username], [password], [profilename], [email] and [socialemail] fields. You will need to provide values while NOT NULL has been set and there is no default value.
Unless your intention is to insert data into pre-existing columns, then use the Update statement.
update user
set enabled = 'Y', accountnonexpired='Y', credentialsnonexpired='Y', accountnonlocked='Y'
from user
where id = 1
An INSERT is creating NEW records. You have a username field that is marked as NOT NULL But in your sql you are not including username and other NOT NULL fields in your statement.
Your insert would need to include all the NOT NULL fields.
insert into user(id,username,password,profilename,email,socialemail,enabled,accountnonexpired,credentialsnonexpired,accountnonlocked)
values ('1',<username>,<password>,<profilename>,<email>,<socialemail>'Y','Y','Y','Y'),('2',<username>,<password>,<profilename>,<email>,<socialemail>'Y','Y','Y','Y');
I suspect you actually want to UPDATE here instead of insert.
An update would look like this:
UPDATE user set enabled = 'Y', accountnonexpired='Y', credentialsnonexpired='Y', accountnonlocked='Y'
FROM user
WHERE id = 1
Give value for 'username' field. it has no default value and default is not null as per your table definition. This will work
In your insert procedure, there is no value assigned for username field, Since username varchar(20) is NOT NULLable, you need to set a default value for that col or alter the col property to accept null values.
I have this table for users that stores their usernames and other data, thats done like this (stripped down):
CREATE TABLE `prod_users` (
`p_user_id` INT(11) NOT NULL AUTO_INCREMENT,
`p_user_name` VARCHAR(200) NOT NULL DEFAULT ''
`p_comp_name` VARCHAR(300) NOT NULL DEFAULT '',
PRIMARY KEY (`p_user_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM
Each time a user signs up, he'll provide a company name as well.
There's another table called prod_profiles, which stores profile details like phone nos. fax nos. etc.
CREATE TABLE `prod_profiles` (
`pf_gen_id` INT(11) NOT NULL AUTO_INCREMENT,
`pf_user_id` INT(11) NOT NULL DEFAULT '0',
`pf_user_name` VARCHAR(200) NOT NULL DEFAULT ''
`pf_comp_name` VARCHAR(300) NOT NULL DEFAULT '',
PRIMARY KEY (`pf_gen_id`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM
When a new user signs up and his details are added to prod_users, is it possible to automatically add his new user_id, user_name and comp_name details to prod_profile using MySql itself? Since each user will have a new p_user_id and we wont know it, it'll be difficult using php. Can this be achieved inside MySql itself without any problems?
It isn't difficult using PHP, since you have the LAST_INSERT_ID() available for use, be it via mysql_insert_id() or mysqli::$insert_id, PDO::lastInsertId() or whatever your API provides. As long as you call the two INSERT statements in immediate succession on the same script (it is connection dependent), MySQL will supply the correct p_user_id.
However, you can use an AFTER INSERT trigger to force MySQL to create the new row automatically:
CREATE TRIGGER build_profile AFTER INSERT ON prod_users
FOR EACH ROW
BEGIN
INSERT INTO prod_profiles
(pf_user_id, pf_user_name, pf_comp_name)
VALUES (NEW.p_user_id, NEW.p_user_name, NEW.p_comp_name)
END
Review the MySQL CREATE TRIGGER syntax reference for full details and options.
You can use the next mysql function: LAST_INSERT_ID(); which returns the last auto increased id.
Therefore , add a user and then add a prod_profile , while pf_user_id value will be the returned value of last_insert_id().
INSERT INTO `prod_users`(`p_user_name`,`p_comp_name`) VALUES('Dan' , 'Stackover')
INSERT INTO `prod_profiles`(`pf_user_id`,`pf_user_name`,`pf_comp_name`) VALUES(LAST_INSERT_ID(),'Dan','Stackover')
Please notice: I have to say , that storing the username and company_name twice for the same user in two different tables is a reall waste...
Consider re-thinking about your DB structre and logic.
How to make sure that field is mandatory ? Here is what I mean
I have the following mysql table structure:
CREATE TABLE `new` (
`id` int(11) DEFAULT NULL,
`name` int(11) DEFAULT NULL,
`phone` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Here is query with no data for phone
insert into new values(1, 'm', '');
But the query runs fine. What should be done so that mysql returns an error if there is no data for phone field? I can do that validation by php, but I'm curious how to do that in mysql.
Possibly setting the default value of the 'phone' column to NULL would make it fail insertion because it would end up null if you did not specify it.
Otherwise you're going to need to omit the phone column for the default to kick in, say in php you'd use empty($phone) ? null : $phone; or something along those lines.
INSERT INTO new VALUES(1,'m',NULL)
will cause error.
If you want to check whether is the phone number field is a blank string,
you can use a trigger in MySQL.
I haven't tested this, but I have a feeling the '' != null. What happens if you run
insert into new(id, name) values (1, 'test');
I bet you get an insert error...
Anyway, I think its probably better to be validating in PHP than waiting till you get to the database... inserts are expensive...
'' as the 3rd option doesnt make the value of phone null.. It is just equal to a blank string thats all.
if you want to see an error, replace '' with NULL.