I have been trying to create a Trigger, however my attempts have been unsuccessful. I seem to be getting an error (#1064), which I have no solution for. Can somebody explain or demonstrate any faults in the syntax.
Let me specify:
I have delivery_id as primary key in delivery table,
I also have delivery_id as a foreign key in entry_log table.
By comparing both id's(if true), will return a text referring to the output of the bit (either 0 or 1)
DELIMITER //
DROP TRIGGER IF EXISTS entry_trigger//
CREATE TRIGGER entry_trigger BEFORE INSERT ON entry_log
FOR EACH ROW
BEGIN
DECLARE #xentry VARCHAR(45)
DECLARE #inta bit
SET #inta = SELECT allowed
FROM delivery
WHERE delivery.delivery_id = entry_log.delivery_id;
CASE
when #inta = 0 then #xentry = 'Acces Denied'
when #inta = 1 then #xentry = 'Acces Allowed'
END CASE
INSERT INTO entry_log(entry_time,access_allowed) VALUES(now(),#xentry);
END
//
This is assuming that you use MySQL. In the body of the trigger you use
WHERE delivery.delivery_id = entry_log.delivery_id;
I think you want to compare to the entry_log entry that the trigger is running on, right? In that case you must use this syntax:
WHERE delivery.delivery_id = NEW.delivery_id;
see here for more examples.
UPDATE
I see that also you try to do an INSERT INTO entry_log within the TRIGGER. This will of course not work, because you would create an infinite recursive loop. Within the
body of the trigger you can do unrelated table access, but not into the table you are inserting. You can change the values to be inserted by the trigger by setting NEW.xyz = whatever
UPDATE 2
I doubt, that your CASE statement is correct. At least it must end with END CASE. You can use IF here, since you don't have many cases to address. If you must use CASE this post might help you: MYSQL Trigger set datetime value using case statement
UPDATE 3
I am not sure, but I think you need brackets around the variable setting statement. try this trigger definition:
DELIMITER //
DROP TRIGGER IF EXISTS entry_trigger//
CREATE TRIGGER entry_trigger BEFORE INSERT ON entry_log
FOR EACH ROW
BEGIN
SET #inta = (SELECT allowed
FROM delivery
WHERE delivery.delivery_id = NEW.delivery_id);
SET NEW.access_allowed = #inta;
SET NEW.entry_time = NOW();
END
//
Note, that this is written out of my head, so beware of syntax errors in my script.
Related
I have a special requirement where I need to automatically update a 'modifiedDate' column's datetime value to NOW(), IF:
Value provided is null
Value provided is the same as what it was before the update
BUT
If value provided is any other date string, then update column with value.
So, I've setup this trigger, but something's now quite right with it:
CREATE TRIGGER `tr_users_updateModDateOnUpdate` BEFORE UPDATE ON `tbl_users`
FOR EACH ROW IF (OLD.date_modified <> NEW.date_modified) THEN
SET NEW.date_modified = IFNULL(NEW.date_modified, NOW());
ELSE
SET NEW.date_modified = NOW();
END IF
I can't see what's wrong with it... , but I'm getting strange behavior when testing with my web application.. So trying to see if the problem is with my trigger, or my php code...
Can anyone tell me if my Trigger code seems okay for my requirements above? Thanks a million!
Pat
Your trigger contains an IF statement, so it needs at BEGIN/END block. Also, the conditions do not seem to do what you want. Finally, you need to set the DELIMITER.
I think that this does what you want:
delimiter //
create trigger tr_users_update_mod_date_on_update
before update on tbl_users
for each row
begin
if new.date_modified is null or old.date_modified = new.date_modified then
set new.date_modified = now();
end if;
end;
//
delimiter ;
I was trying to create trigger which can update value of column user_count of table user_details using value of u_count of table user_info.
CREATE TRIGGER `test`
AFTER INSERT ON `user_details` FOR EACH ROW
BEGIN
DECLARE default_user_count int(11);
SELECT u_count INTO #default_user_count FROM
user_info WHERE user_info.id= user_details.id_c;
IF user_details.user_count= 0
THEN UPDATE user_details SET
user_count = default_user_count
WHERE user_details.id_c = user_info.id;
END IF;
END
Trigger saved successfully but when i tried to insert value in both table it is preventing to insert record into user_details means no row inserted in 2 this table, if we delete trigger then its working.
Can anyone let me know wrong with this trigger?
THanks,
M.
It's not really clear what you're trying to accomplish, but it seems like it's something like what we have below.
There are numerous errors in and ambiguities in your trigger.
Confusion on variables -- DECLARE default_user_count INT(11); does not declare the user-defined variable #default_user_count. It declares the program variable default_user_count. The # prefix references an entirely different variable scope and namespace.
SELECT and UPDATE from the table which invoked the trigger doesn't usually make sense (SELECT) or is completely invalid (UPDATE).
With in a trigger, you are operating FOR EACH ROW -- that is, for each row included in the statement that invoked the trigger. Inside an INSERT trigger, the NEW values for the row are in a pseudo-table/pseudo-row accessible via the alias NEW. For UPDATE triggers, there are NEW and OLD row values, and for DELETE triggers, just OLD.
AFTER INSERT doesn't seem to make sense. I think you're looking for BEFORE INSERT -- that is, while processing an INSERT INTO ... query, before the newly-inserted row actually gets written into the table, modify its values accordingly. The resulting row contains the original values except where the trigger has modified them.
SELECT ... INTO a variable is a practice you should not get into the habit of, because it can bite you in a way a scalar subquery can't, by leaving a variable unexpectedly unaltered instead of setting it to NULL as would be expected. In this case, it would have made no difference, but it's still a caution worth mentioning... and in this case, I've eliminated that intermediate variable altogether, so the subquery is the only option.
If you are trying to set a value in this table using a value found in another table, all you need to do is SET NEW.column_name equal to the value you want used in the row instead of the value provided with the insert statement.
CREATE TRIGGER `test`
BEFORE INSERT ON `user_details` FOR EACH ROW
BEGIN
IF NEW.user_count = 0 /* maybe also >> */ OR NEW.user_count IS NULL /* << this */ THEN
SET NEW.user_count = (SELECT ui.u_count
FROM user_info ui
WHERE ui.id = NEW.id_c);
END IF;
END
Again, it's unclear how the two tables are connected based on the content of the original question, but this appears to do what you're trying to accomplish.
Trying to get a trigger to work that refuses to I think it has to be setup as a procedure for it to work which I've never worked with before could anyone tell me how I would go about this? The trigger doesn't show errors when adding but just doesn't do anything
** It now does work apart from changing processed to 0)
UPDATE product
INNER JOIN ebaylinked ON ebaylinked.ebay_ID = product.eBay_ID
SET product.product_stock = product.product_stock - NEW.QuantitySold,NEW.Processed=0
WHERE product.eBay_ID = NEW.ebay_ID and NEW.Processed = 1
First of all, find a more descriptive name for your trigger ;).
Now for the actual problem, your references to the columns in ebaylinked in your trigger code are pretty much mostly wrong. To use the values in the record you just updated, you need to use the pseudorecord NEW, which is a single record containing the current row of the table as it will be after the update completes. References like ebaylinked.QuantitySold are ambiguous, as they do not specify which row of data is the correct one.
Also, you cannot refer to other rows in the triggering table. Your clauses SET ... ebaylinked.Processed=0 ... WHERE ... ebaylinked.Processed = 1 are thus both redundant and wrong, since the only row of ebaylinked your row trigger can see is the current one.
Your trigger code should thus be something like
CREATE TRIGGER `ebaylinked_update_product`
AFTER UPDATE ON `ebaylinked`
FOR EACH ROW
UPDATE product
SET product.product_stock = product.product_stock - NEW.QuantitySold
WHERE product.eBay_ID = NEW.ebay_ID;
Note I'm ignoring the processed column since it does nothing useful (provided the triggering insert is wrapped in a transaction), but if you absolutely must use it, you would change your trigger to before row as follows:
DELIMITER //
CREATE TRIGGER `ebaylinked_update_product`
BEFORE UPDATE ON `ebaylinked`
FOR EACH ROW
BEGIN
IF NEW.processed = 1 THEN
UPDATE product
SET product.product_stock = product.product_stock - NEW.QuantitySold
WHERE product.eBay_ID = NEW.ebay_ID;
SET NEW.processed = 0;
END IF;
END;
//
DELIMITER ;
Note the space between DELIMITER and whatever follows it. This directive is necessary in some clients when the trigger body contains multiple statements terminated by semicolons.
Hope that helps.
PS: You could do this with the trigger calling a stored procedure, but for something this simple I think it would add more complexity than it would be worth.
What is ebaylinked? You should be getting an error when you define the trigger.
If you want to update the table defined by the trigger, then you should use a BEFORE UPDATE trigger. So, I think you intend:
DELIMITER $$
CREATE TRIGGER `Update` BEFORE UPDATE ON `ebaylinked`
FOR EACH ROW
BEGIN
UPDATE product p
SET p.product_stock = p.product_stock - new.QuantitySold
WHERE p.eBay_ID = new.ebay_ID AND new.Processed = 1;
SET new.Processed = 0;
END; $$
DELIMTER ;
Is it possible to set a column to its default value (or any specified value) on update when no value is specifically given in the statement? I was thinking that a trigger might accomplish this. Something like
IF ISNULL(NEW.column) THEN
NEW.column = value
END IF;
didn't work.
MySQL has function called DEFAULT(), which gets the default value from specified column.
UPDATE tbl SET col = DEFAULT(col);
MySQL Reference
UPDATE:
#JanTraenkner As far as I can tell, this is not possible. You can however make sure in your application code, that all columns are mentioned in your update statement and for those that do not have a value your use NULL as value. Then your trigger code is almost right, you just need to change it to
IF (NEW.column IS NULL) THEN
SET NEW.column = value
END IF;
Original answer:
I understood your question like, "set column to default value, if I don't specify the column in an update statement (which updates other columns from that table)".
To check with ISNULL() or col IS NULL doesn't work here, because when you don't specify it in the update statement it simply isn't there. There's nothing to check for.
I wrote this little example script which makes it work like I understood the question.
drop table if exists defvalue;
create table defvalue (id int auto_increment primary key, abc varchar(255) default 'default');
insert into defvalue (id) values (null);
insert into defvalue (id, abc) values (null, 'not_default_value');
insert into defvalue (id, abc) values (null, 'another_not_default_value');
drop trigger if exists t_defval;
delimiter $$
create trigger t_defval before update on defvalue
for each row
begin
set #my_def_value = (select default(abc) from defvalue limit 1);
if (new.abc = old.abc) then
set new.abc = #my_def_value;
end if;
end $$
delimiter ;
select * from defvalue;
update defvalue set id = 99 where id = 1;
select * from defvalue;
update defvalue set id = 98 where id = 2;
select * from defvalue;
I also had to save the default value of the column in a variable first because the function needs to know from which table. Unfortunately one can't specify that as parameter, not even as default(tablename.column).
All in all, please note, that this is rather a proof of concept. I'd recommend to solve this on application layer, not database layer. Having a trigger for this seems a bit dirty for me.
So this should be a fairly straight forward trigger, but my MySQL isn't great, so it's undoubtably a failure on my part.
It's not updating the stats table at all, even though it should be;
DROP TRIGGER countryUpdate;
DELIMITER //
CREATE TRIGGER countryUpdate AFTER INSERT ON stats
FOR EACH ROW BEGIN
DECLARE NewIP varchar(16);
DECLARE NewCountry varchar(80);
SET NewIP = inet_aton(new.vis_ip);
SET NewCountry = (SELECT country FROM iptocountry WHERE lower_bound <= NewIP AND upper_bound >= NewIP)
UPDATE stats
SET Country = NewCountry
END //
DELIMITER;
Well, first off, your UPDATE—if it works at all—is changing all rows in the stats table, and its doing that for each row inserted. That really doesn't make much sense. At minimum, you want to add a where clause to only hit the one row you've just inserted.
Apparently, though, that can't work at all in MySQL, because "a stored function or trigger cannot modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger." (Look under “Restrictions for Stored Functions”)
So, instead, you need to use a a before insert trigger, and do a SET new.country = NewCountry to fix the row up before its ever inserted.