I just discovered NOT NULL does not make a field required.
When creating a mysql table, how do I create a field that cannot contain null or blank (must have something in it)?
By default, MySQL accepts invalid values. You can set MySQL to strict mode to force valid values. This will reject a query that does not provide a value for a NOT NULL column as well as enforce integrity on all types of columns.
Update: MySQL 5.7 and above now have strict mode on by default. So it would not accept invalid values by default like previous versions.
http://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sql-mode-important
http://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_strict_all_tables
Edit:
#Barranka and #RocketHazmat made good points in the comments. '' is not the same as null, so MySQL will allow that in a NOT NULL column. In that instance, you would have to resort to your code or a trigger.
In the code (PHP for example), this could be easy enough, running something like:
if (!strlen($value)) {
// Exclude value or use NULL in query
}
I think you should do two things:
Set the column to NOT NULL to force the input of a value
Use a trigger to validate the values.
Within the trigger you can cancel the operation if the desired column does not fulfill a required condition (for example, having zero-length).
This question and its answers address this second thing, and here is an example:
delimiter $$
CREATE TRIGGER `cancel_insert_if_empty`
BEFORE INSERT ON `your_table`
FOR EACH ROW
BEGIN
declare msg varchar(255);
if NEW.your_column is null or length(NEW.your_column) = 0 then
set msg = "You're doing something wrong! Now suffer the consequences";
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
end if;
END$$
delimiter ;
In this example, if you try to insert a null value or a zero-length string in your_column an error will rise and the insert will be canceled. Quoting from the reference manual:
MySQL handles errors during trigger execution as follows:
If a BEFORE trigger fails, the operation on the corresponding row is not performed.
A BEFORE trigger is activated by the attempt to insert or modify the row, regardless of whether the attempt subsequently succeeds.
An error during either a BEFORE or AFTER trigger results in failure of the entire statement that caused trigger invocation.
Of course, you can write a trigger to check the updates too.
Hope this helps.
You can set default value for that field: City varchar(40) DEFAULT 'Sandnes'
Related
create trigger cal_retweet before insert on T
for each row begin
set NEW.retweet_change = NEW.retweet_count - retweet_count where id_str = NEW.id_str
end
SQL said there is syntax error near "where id_str = NEW.id_str"
My table looks like this. Where id_str is a unique identifier for a specific tweet. Since I am inserting 50 tweets from a single user every minute, there would be many same id_str. What I want to look at is the change of retweet_count every minute. tweeted_at is when the user tweeted, created_at is when this data is inserted into my database. I want to generate retweet_change for each new data inserted into the database compared to the same old tweet (into the column retweet_change). How should I write the trigger?
After reading some of your comments I changed my code to :
create trigger cal_retweet before update on T
for each row
begin
set NEW.retweet_change = NEW.retweet_count - OLD.retweet_count;
end;
There is still syntax error
There are several issues with this trigger.
You have some syntax errors. You need proper semicolons to delimit your statements.
You have a WHERE statement that is out of place (and actually not needed). You are acting on only a single row at a time, you don't have to match on the id_str.
In order to factor in a calculation using an existing value from the row, you need access to the OLD keyword. For that, you need a trigger that happens on UPDATE, not INSERT. On INSERT, the retweet_change is simply the same as retweet_count; you could alter your INSERT statement to fix that problem.
You may need to explicitly add a statement delimiter as per the comments below.
So all together, I think this trigger should look like:
DELIMITER //
CREATE TRIGGER cal_retweet BEFORE UPDATE ON T
FOR EACH ROW
BEGIN
SET NEW.retweet_change = NEW.retweet_count - OLD.retweet_count;
END;//
DELIMITER ;
I want to insert only one letter into the table field. What will be the data type that will accept only one character?
I don't want to use VARCHAR(1), because it will truncate the remaining characters. I want that if the input is 1 character, it will insert otherwise it will not insert into the table
If you set the column length to be longer (for example, 255), then you can add a trigger which checks the length of the new field. If greater than 1 then you can trigger an error.
For a test example:-
CREATE TABLE IF NOT EXISTS `insert_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`sometext` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
--
-- Triggers `insert_test`
--
DROP TRIGGER IF EXISTS `length_check_trigger`;
DELIMITER //
CREATE TRIGGER `length_check_trigger` BEFORE INSERT ON `insert_test`
FOR EACH ROW BEGIN
DECLARE msg VARCHAR(255);
IF LENGTH(NEW.sometext) > 1 THEN
SET msg = "DIE: String Too Long.";
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
END IF;
END
//
DELIMITER ;
You can change the message to what you want. You will need a similar trigger to catch updates as well.
In mysql the data type itself does not control if the attempt to insert / update a field to a longer (invalid) data, than it is allowed by the field definition results in an error or warning.
In mysql you need to set the sql mode to one of the strict sql modes as described by mysql's documentation on sql mode.
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.
So, both varchar(1) and char(1) are correct definitions, however, you need to enable strict sql mode in order for inserting / updating invalid data to produce an error. Setting sql mode in config file or using set statement is described in the linked documentation:
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';
Have you tried the datatype:
TINYTEXT
?
or would it not work on the system you are using?
I'm trying to work out a MySQL query that only adds a new row to an existing table if all fields have a value present, otherwise it should be dropped/ignored.
The query I have at the moment is as follows:
INSERT INTO markers (`name`, `address`, `details`, `date`, `link`, `lat`, `lng`, `type`)
VALUES ("{1}", "{2}", "{3}", "{15}", "{4}", "{11}", "{12}", "{5}")
If {15} is left blank by my form then I don't want any of the other values added to the table.
Hope that makes sense!
Thanks
I would suggest you do a couple of different solutions.
You could setup your database to not allow null values, and then when you go to insert, handle your null errors (probably not the best solution out there though). If you need to have null values, then you will have to handle this in code.
The other thing is to implement form validation. You can do this with JavaScript, code behind, or even both. Both is suggested as some people may have JavaScript disabled on their browser.
I'd say check the inputs on the front-end with Java, C#, Swift, whatever. Then if an entry is blank, just make a pop-up message letting your user know to fill out every field, or for your application to just skip that record.
If you want to do this directly in MySQL, you can create a trigger that checks the values before they are inserted, and throw an error if some validation rule is not fulfilled.
Example:
delimiter $$
create trigger no_emtpy_values before insert into markers
for each row
begin
declare msg varchar(255);
declare condition_fail int default 0;
-- Write the appropriate validations and set condition_fail to 1
-- if the validations are not fulfilled. For example:
if NEW.`date` IS NULL then
set condition_fail = 1;
end if;
-- That "NEW" refers to the row about to be inserted
-- If the validation rules are not fulfilled, throw an error:
if condition_fail then
set msg = "You can't insert the data!";
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
end if;
end $$
delimiter ;
References:
"How to abort INSERT operation in MySql trigger?"
MySQL reference manual: CREATE TRIGGER Syntax
Hope this helps
I am Writing a MYSQL Stored Procedure. In that i know using HANDLER we can check the condition for SELECT STATEMENT.
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET NO_MORE_ROWS = TRUE;
In DB2 we can check the return code using SQLCODE immediatly after the statement.
Please let me know how i need to handle the Duplicate Index, More than one Row, Cursor Problem, Data mismatch in Source variable against table fields. Is there a way in MYSQL.
Basically i want to know in MYSQL How to handle the below condition.
SELECT - NOT FOUND, MORE THAN ONE ROW, EXCEPTION, DATATYPE MISMATCH IN TO CONDITION
INSERT - DUPLICATE INDEX, DATATYPE MISMATCH, OTHER INERT FAILURE
UPDATE - NO DATA FOR UPDATE, UPDATE WHERE CONDITION NOT MET
DELETE - NOT DELETED BECAUSE OF FOREIGN KEY ISSUE.
CURSOR - CURSOR FAILURE
Thanks.
As documented under DECLARE ... HANDLER Syntax:
The condition_value for DECLARE ... HANDLER indicates the specific condition or class of conditions that activates the handler:
A MySQL error code (a number) or an SQLSTATE value (a 5-character string literal). You should not use MySQL error code 0 or SQLSTATE values that begin with '00', because those indicate success rather than an error condition. For a list of MySQL error codes and SQLSTATE values, see Section C.3, “Server Error Codes and Messages”.
I want to protect existing dates in a date column from being overwritten. So disallow updates to the date column and only allow inserts if the existing field value is NULL (date column default is NULL). Are triggers the only way to accomplish this in MySQL? If so, would the trigger below work?
create trigger date_check
before insert, update on date
for each row
begin
if(date IS NOT NULL) then
SIGNAL 'date already set'
end if ;
end ;
Background: I have a table with critical dates that was accidentally changed due to user error. I put some checks in the user interface to prevent this from happening again but want another layer of safety directly with the database if possible.
Yes, in MySQL triggers are the only way to do this. MySQL does not support constraints.
Your trigger is not exactly right. First, you have update on date, but this should be update on <table name>. Second, you are checking the date value used for the update. Perhaps you mean:
create trigger date_check_update
before update on <the table name goes here>
for each row
begin
if (old.date IS NOT NULL) then
SIGNAL 'date already set'
end if ;
end;
An insert trigger on this condition doesn't make sense.
If anyone like me stumble upon this thread and is getting syntax error, it's because "When you try to raise errors via SIGNAL you need to specify the SQLSTATE which is the error code and for the user defined generic error codes its 45000 along with the message text MESSAGE_TEXT"
So the SIGNAL line should look like this.
signal SQLSTATE VALUE '45000' SET MESSAGE_TEXT = 'Your custom error message';
See this answer for more details.
https://stackoverflow.com/a/42827275/4164651
Just combining the above two answers, however, if you are writing triggers directly at the terminal, you'll have to change the delimiter before writing the trigger and then change it back once done.
delimiter $$
create trigger date_check_update
before update on <the table name goes here>
for each row
begin
if (old.date IS NOT NULL) then
signal SQLSTATE VALUE '45000' SET MESSAGE_TEXT = 'Your custom error message';
end if ;
end $$
delimiter ;