How do I realize the following in MySQL with Triggers:
When value of some column is null -> set other column values to null
and
when value of some column is not null -> set other column values to null
table definition:
CREATE TABLE variations (
id int(10) NOT NULL,
x1 int(10) NOT NULL,
x2 int(10),
x1_option1 BOOL,
x2_option1 BOOL,
x1_option2 varchar(10),
x2_option2 varchar(10)
);
The idea is that we have 2 Elements, x1and x2. While x1is mandatory, x2is optional and can be null. Both, x1 and x2 have two options: x1_option1 , x2_option1, x1_option2 and x2_option2.
The first rule should be that when x2 is null, both options for x2 (x2_option1, x2_option2) must also be null.
My attempt:
CREATE
TRIGGER check_null_x2 BEFORE INSERT
ON variations
FOR EACH ROW BEGIN
IF NEW.x2 IS NULL THEN
SET NEW.x2_option1 = NULL;
SET NEW.x2_option2 = NULL;
END IF;
END$$
Throws Error:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 6
Can you please help me figuring out whats wrong? I just dont understand what '' means.
The second rule should be that there can only be one of the two options selected. that means if x2_option1 is NOT NULL, x2_options2 must be NULL. In general i think this can be done the same way as the first rule. My question: how can i do multiple 'IF', 'ELSE IF' etc in one trigger?
This is syntax for trigger:
delimiter //
CREATE TRIGGER upd_check BEFORE UPDATE ON account
FOR EACH ROW
BEGIN
IF NEW.amount < 0 THEN
SET NEW.amount = 0;
ELSEIF NEW.amount > 100 THEN
SET NEW.amount = 100;
END IF;
END;//
delimiter ;
...and your code is here:
DELIMITER //
CREATE TRIGGER check_null_x2 BEFORE INSERT ON variations
FOR EACH ROW
BEGIN
IF NEW.x2 IS NULL THEN
SET NEW.x2_option1 = NULL;
SET NEW.x2_option2 = NULL;
END IF;
END$$ -- THIS LINE SHOULD BE: "END;//"
DELIMITER ;
EDIT:
The official Documentation says the following:
If you use the mysql client program to define a stored program containing semicolon characters, a problem arises. By default, mysql itself recognizes the semicolon as a statement delimiter, so you must redefine the delimiter temporarily to cause mysql to pass the entire stored program definition to the server.
To redefine the mysql delimiter, use the delimiter command. The following example shows how to do this for the dorepeat() procedure just shown. The delimiter is changed to // to enable the entire definition to be passed to the server as a single statement, and then restored to ; before invoking the procedure. This enables the ; delimiter used in the procedure body to be passed through to the server rather than being interpreted by mysql itself.
you seem to have ";" set as DELIMETER, which causes the query to execute once it sees a ";". try changing it first:
DELIMITER //
CREATE
TRIGGER check_null_x2 BEFORE INSERT
ON variations
FOR EACH ROW BEGIN
IF NEW.x2 IS NULL THEN
SET NEW.x2_option1 = NULL;
SET NEW.x2_option2 = NULL;
END IF;
END;//
DELIMITER ;
CREATE TRIGGER `XXXXXX` BEFORE INSERT ON `XXXXXXXXXXX` FOR EACH ROW BEGIN
IF ( NEW.aaaaaa IS NULL ) THEN
SET NEW.XXXXXX = NULL;
SET NEW.YYYYYYYYY = NULL;
END IF;
END
Worked for me....
Related
I tried to make a simple procedure in MariaDB 10.2 but I encountered an issue regarding variables defining.
I am receiving (conn:107) You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 3 message when I declare a variable.
I read the MariaDB documentation and I it says that a variable is defined like this DECLARE var_name [, var_name] ... type [DEFAULT value]
Where I am wrong? I am coming from Oracle SQL and some sintax is wired for me.
I use Eclipse with MariaDB JDBC to connect on SQL.
CREATE PROCEDURE nom_jobs_insert(IN p_name varchar(100) CHARACTER SET 'utf8')
BEGIN
DECLARE counter INT DEFAULT 0;
SELECT count(*) INTO counter
FROM nom_jobs
WHERE lower(name) = lower(p_name)
IF counter = 1 THEN
INSERT INTO nom_jobs(name) VALUES (p_name);
END IF;
END;
I found the solution.
In MariaDB you have to define a delimiter before create a procedure and you need to mark where the procedure code is finished.
DELIMITER //
CREATE PROCEDURE nom_jobs_insert(IN p_name varchar(100) CHARACTER SET 'utf8')
BEGIN
DECLARE counter INT DEFAULT 0;
SELECT count(*) INTO counter
FROM nom_jobs
WHERE lower(name) = lower(p_name);
IF counter = 1 THEN
INSERT INTO nom_jobs(name) VALUES (p_name);
END IF;
END; //
You have error not in DECLARE expression, add ; after SELECT statement
Here are the clues that point to a missing DELIMITER:
near '' at line 3
Line 3 contains the first ;
When the error says near '', the parser thinks it has run off the end of the "statement".
Put those together -- it thinks that there is one 3-line statement ending with ;. But the CREATE PROCEDURE should be longer than that.
CREATE PROCEDURE nom_jobs_insert(IN p_name varchar(100) CHARACTER SET 'utf8')
IS
DECLARE counter INTEGER DEFAULT 0;
BEGIN
SELECT count(*) INTO counter
FROM nom_jobs
WHERE lower(name) = lower(p_name)
IF counter = 1 THEN
INSERT INTO nom_jobs(name) VALUES (p_name);
END IF;
END;
I have a problem with this SQL code. I want to create a trigger, here it is.
CREATE TRIGGER `blog_after_insert` AFTER UPDATE ON `agent`
FOR EACH ROW
BEGIN
DECLARE costvalue INTEGER default 0;
IF (OLD.PacketStatusType_Id!=NEW.PacketStatusType_Id) THEN
IF (OLD.Packet_Cost IS NULL) THEN
SET costvalue = OLD.Packet_Cost;
ELSE
SET costvalue = OLD.Packet_SMSCount;
END IF;
IF (costvalue IS NOT NULL) THEN
CALL tcksms_packet_update_proc(OLD.Transaction_Id,OLD.PacketStatusType_Id,costvalue,-1);
ELSE
CALL tcksms_packet_update_proc(OLD.Transaction_Id,OLD.PacketStatusType_Id,0,-1);
END IF;
DECLARE COST_VALUE_NEW INT DEFAULT 0;
IF (NEW.Packet_Cost IS NULL) THEN
SET COST_VALUE_NEW = NEW.Packet_Cost;
ELSE
SET COST_VALUE_NEW = NEW.Packet_SMSCount;
END IF;
IF (COST_VALUE_NEW IS NOT NULL) THEN
CALL tcksms_packet_update_proc(NEW.Transaction_Id,NEW.PacketStatusType_Id,COST_VALUE_NEW,1);
ELSE
CALL tcksms_packet_update_proc(NEW.Transaction_Id,NEW.PacketStatusType_Id,0,1);
END IF;
ELSE
END IF;
END IF;
END
But i get this;
Error
SQL query:
CREATE TRIGGER `blog_after_insert` AFTER UPDATE ON `agent` FOR EACH ROW BEGIN DECLARE costvalue INTEGER default 0;
MySQL said: Documentation > #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near '' at line 5
That line is
I tried deleting spaces, made combinations of apostrophes (' and `), deleted and rewrited some lines manually but can't make it work, what is wrong with this code?
You need to use the delimiter command before and after the create trigger command, otherwise the semicolons terminating the commands within the trigger body will confuse mysql. See mysql's documentation on defining stored programs, which also has examples how to use the delimiter command.
I am trying to make make a trigger, that will fill column B with value from column A if column B was not explicitly set in insert query. (column B is set to allow NULL and to default to NULL value)
DELIMITER $$
CREATE TRIGGER trigger_name BEFORE INSERT ON my_table FOR EACH ROW
BEGIN
IF (NEW.valueB IS NULL) THEN SET NEW.valueB = NEW.valueA ;
END
$$
But I am getting this error (not very helpful).
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 4
When I tried to locate this problematic empty string '' making the query like one word per line, mysql marked the line with '=' character as problematic.
I double checked the query for any non-ascii characters.
I am using mysql version 5.5.37-0ubuntu0.12.10.1 through commandline (eg not phpmyadmin).
You need to close the IF with END IF
DELIMITER $$
CREATE TRIGGER trigger_name BEFORE INSERT ON my_table
FOR EACH ROW
BEGIN
IF NEW.valueB IS NULL THEN
SET NEW.valueB = NEW.valueA ;
END IF ;
END;$$
delimiter ;
Check the example here http://dev.mysql.com/doc/refman/5.5/en/trigger-syntax.html
You forgot to close the IF statement. Read the syntax here. I think the code below will work for you.
DELIMITER $$
CREATE TRIGGER trigger_name BEFORE INSERT ON my_table
FOR EACH ROW
BEGIN
IF (NEW.valueB IS NULL) THEN
SET NEW.valueB = NEW.valueA ;
END IF
END $$
DELIMITER
I want to check the existance of specific record in db table, if it's exist then update if not I want to add new record
I am using stored procedures to do so, First I make update stetement and want to check if it occurs and return 0 then there's no record affected by update statement and that means the record does not exist.
I make like this
DELIMITER //
CREATE PROCEDURE revokePrivilegeFromUsers(IN userId int(11), IN privilegeId int(11), IN deletedBy int(11))
BEGIN
DECLARE isExist int;
isExist = update `user_privileges` set `mode` ='d' ,`updated_by` = deletedBy, `date_time_assigned` = CURRENT_TIMESTAMP() where `user_id`= userId and `privilege_id`=privilegeId;
IF isExist == 0 THEN
insert into `user_privileges`(`user_id`,`privilege_id`,`mode`,`date_time_assigned`,`updated_by`)values (userId ,privilegeId ,'d',CURRENT_TIMESTAMP(),deletedBy );
END IF;
END //
DELIMITER ;
This error occur with me
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '= update `user_privileges` set `mode` ='d' ,`updated_by` = deletedBy, `date_time' at line 6
Is the way I am working is supported by mysql?
I solve the problem, I had 2 prblems
ROW_COUNT() is used to get the number of rows affected in insert, update or delete statements.
Equals comparison in stored procedure is = not ==
The correct stored procedure is
DELIMITER //
CREATE PROCEDURE revokePrivilegeFromUsers(IN userId int(11), IN privilegeId int(11), IN deletedBy int(11))
BEGIN
DECLARE count int default -1;
update `user_privileges` set `mode` ='d' ,`updated_by` = deletedBy, `date_time_assigned` = CURRENT_TIMESTAMP() where `user_id`= userId and `privilege_id`=privilegeId;
SELECT ROW_COUNT() into count ;
IF count = 0 THEN
insert into `user_privileges`(`user_id`,`privilege_id`,`mode`,`date_time_assigned`,`updated_by`)values (userId ,privilegeId ,'d',CURRENT_TIMESTAMP(),deletedBy );
END IF;
END //
DELIMITER ;
Use the INSERT IGNORE statement instead. I assume that your table has (user_id, privilege_id) as a unique key.
insert ignore into user_privileges (user_id,privilege_id,`mode,date_time_assigned,updated_by)
values (userId ,privilegeId ,'d',CURRENT_TIMESTAMP(),deletedBy )
on duplicate key update mode='d', date_time_assigned=now(),updated_by=deletedBy
I have very simple question but i did't get any simple code to exit from SP using Mysql.
Can anyone share with me how to do that?
CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
BEGIN
IF tablename IS NULL THEN
#Exit this stored procedure here
END IF;
#proceed the code
END;
CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
proc_label:BEGIN
IF tablename IS NULL THEN
LEAVE proc_label;
END IF;
#proceed the code
END;
If you want an "early exit" for a situation in which there was no error, then use the accepted answer posted by #piotrm. Most typically, however, you will be bailing due to an error condition (especially in a SQL procedure).
As of MySQL v5.5 you can throw an exception. Negating exception handlers, etc. that will achieve the same result, but in a cleaner, more precise manner.
Here's how:
DECLARE CUSTOM_EXCEPTION CONDITION FOR SQLSTATE '45000';
IF <Some Error Condition> THEN
SIGNAL CUSTOM_EXCEPTION
SET MESSAGE_TEXT = 'Your Custom Error Message';
END IF;
Note SQLSTATE '45000' equates to "Unhandled user-defined exception condition". By default, this will produce an error code of 1644 (which has that same meaning). Note that you can throw other condition codes or error codes if you want (plus additional details for exception handling).
For more on this subject, check out:
https://dev.mysql.com/doc/refman/5.5/en/signal.html
How to raise an error within a MySQL function
http://www.databasejournal.com/features/mysql/mysql-error-handling-using-the-signal-and-resignal-statements.html
Addendum
As I'm re-reading this post of mine, I realized I had something additional to add. Prior to MySQL v5.5, there was a way to emulate throwing an exception. It's not the same thing exactly, but this was the analogue: Create an error via calling a procedure which does not exist. Call the procedure by a name which is meaningful in order to get a useful means by which to determine what the problem was. When the error occurs, you'll get to see the line of failure (depending on your execution context).
For example:
CALL AttemptedToInsertSomethingInvalid;
Note that when you create a procedure, there is no validation performed on such things. So while in something like a compiled language, you could never call a function that wasn't there, in a script like this it will simply fail at runtime, which is exactly what is desired in this case!
To handle this situation in a portable way (ie will work on all databases because it doesn’t use MySQL label Kung fu), break the procedure up into logic parts, like this:
CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
BEGIN
IF tablename IS NOT NULL THEN
CALL SP_Reporting_2(tablename);
END IF;
END;
CREATE PROCEDURE SP_Reporting_2(IN tablename VARCHAR(20))
BEGIN
#proceed with code
END;
This works for me :
CREATE DEFINER=`root`#`%` PROCEDURE `save_package_as_template`( IN package_id int ,
IN bus_fun_temp_id int , OUT o_message VARCHAR (50) ,
OUT o_number INT )
BEGIN
DECLARE v_pkg_name varchar(50) ;
DECLARE v_pkg_temp_id int(10) ;
DECLARE v_workflow_count INT(10);
-- checking if workflow created for package
select count(*) INTO v_workflow_count from workflow w where w.package_id =
package_id ;
this_proc:BEGIN -- this_proc block start here
IF v_workflow_count = 0 THEN
select 'no work flow ' as 'workflow_status' ;
SET o_message ='Work flow is not created for this package.';
SET o_number = -2 ;
LEAVE this_proc;
END IF;
select 'work flow created ' as 'workflow_status' ;
-- To send some message
SET o_message ='SUCCESSFUL';
SET o_number = 1 ;
END ;-- this_proc block end here
END
Why not this:
CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
BEGIN
IF tablename IS NOT NULL THEN
#proceed the code
END IF;
# Do nothing otherwise
END;
MainLabel:BEGIN
IF (<condition>) IS NOT NULL THEN
LEAVE MainLabel;
END IF;
....code
i.e.
IF (#skipMe) IS NOT NULL THEN /* #skipMe returns Null if never set or set to NULL */
LEAVE MainLabel;
END IF;
I think this solution is handy if you can test the value of the error field later. This is also applicable by creating a temporary table and returning a list of errors.
DROP PROCEDURE IF EXISTS $procName;
DELIMITER //
CREATE PROCEDURE $procName($params)
BEGIN
DECLARE error INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET error = 1;
SELECT
$fields
FROM $tables
WHERE $where
ORDER BY $sorting LIMIT 1
INTO $vars;
IF error = 0 THEN
SELECT $vars;
ELSE
SELECT 1 AS error;
SET #error = 0;
END IF;
END//
CALL $procName($effp);