INSERT INTO new MYSQL row only if all values are present - mysql

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

Related

How to create a log to track the column name, old values, new values, when user updates as table in mysql

Hello i am tring to take a log of the column name old value and new value that is being modified.I went through the solution available but getting the errors of sql syntax. Unsure where issue actually lies.
Trigger i genrated in as below
CREATE TRIGGER `products_change` AFTER UPDATE ON `products`
FOR EACH ROW in
BEGIN
IF NEW.name <> OLD.name THEN
INSERT INTO product_change_logs(column_name, old_value, new_value) values ('name', OLD.name ,NEW.name);
END IF;
END
Also tried information schema to loop through the column name to avoid the if else but facing the same. Request to please guide with a best approach to create the same, also way to pass the value to trigger like user_id or something.
Any help is deeply appreciated.

Do I need to duplicate my triggers to cover the before insert and before update scenarios?

I created some triggers to make some simple validations. I covered the before insert scenario, for example:
CREATE TRIGGER TR_before_insert_login
BEFORE INSERT ON login
FOR EACH ROW
BEGIN
IF (CHAR_LENGTH(NEW.password) < 4 OR CHAR_LENGTH(NEW.password) > 10) THEN
SIGNAL SQLSTATE '42000'
SET MESSAGE_TEXT = 'password must be between 4 e 10 characters';
END IF;
......
But if the user performs an update I can't prevent it from entering incorrect data. Do I need to create a before update and duplicate my validation code or there is a better way to do this.
Why don't put the logic (your validation code) into procedure and execute it inside the separate triggers (insert/update).
-- pseudo code
create procedure PASSWORD_VALIDATION(_psswd) { /* validation */ };
create trigger table_ub BEFORE UPDATE { CALL PASSWORD_VALIDATION(NEW.password);};
create trigger table_ib BEFORE INSERT { CALL PASSWORD_VALIDATION(NEW.password);};
Thus, your validation code is not duplicated.
ALTER TRIGGER [dbo].[trigger_name]
ON [dbo].[table_name]
FOR DELETE, INSERT, UPDATE
AS
BEGIN
'your code here'
END
you can use structure like this to call same trigger for insert,update and delete

How do I require a mysql field?

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'

Protect column, disallow update, only allow insert if NULL in MySQL

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 ;

mysql: Insert only if certain conditions are respected

I'm trying to find a way to check ,before adding a new tuple in a table, if the tuple respect some condition and in case of one of the conditions is not respected do not allow the insert.
I've thought of something like
DELIMITER //
CREATE TRIGGER t BEFORE INSERT ON Table
FOR EACH ROW
CALL CHECK1(…);
CALL CHECK2(…);
CALL CHECK3(…);
//
DELIMITER;
Where check1,check2,check3 are procedures that raise an exception if the NEW.(attributes) that I pass do not respect condition in the inserting table and/or with other tables.
Is this a correct and/or good way to make what I'm trying to do?
What is the best way to do that?
The best way to do it, is to do the data validation using stored procedures, instead of triggers. The trigger strategy is useful if you only want to filter incoming data. If the objective is to cancel an operation entirely when data values are unsuitable, you cannot do this in MySQL using a trigger.
I'm answering to reply(with a comment my answer would be incomprehensible) and to give more details:
I've used 2 strategies to make my goal, here 2 examples
1)if the check is easy
DELIMITER $$
create trigger RV5_1 before insert on Customer
for each row begin
IF(DATEDIFF(CURDATE(),NEW.birthdate)/365<18)
THEN
SIGNAL sqlstate '45006' set message_text = "too young to be a customer";
END IF;
END;
$$
DELIMITER ;
2) if the check is not easy and need cursors, variables etc
DELIMITER $$
create trigger T2 before insert on Table
for each row begin
IF (check1(NEW.[_some_attribute/s_]) or
check2(NEW.[_some_attribute/s_]))
THEN
SIGNAL sqlstate '45002' set message_text = "invalid insert";
END IF;
END;
$$;
DELIMITER ;
where check1 and check2 are stored functions that returns 0 if it's ok or 1 if there are problem with the new tuple.
Maybe someone with the same problem will found this helpful.