Use Trigger to copy data from a table to another (VTiger) - mysql

I'm sorry for such a newbie question, but I have two tables:
vtiger_assets
+-----------+---------+------+-----+---------+----------------+
| assetid | account | Stat | Key | Default | assetname |
+-----------+---------+------+-----+---------+----------------+
| 224 | int(11) | NO | PRI | NULL | |
| 225 | int(11) | NO | | NULL | |
| 226 | date | NO | | NULL | |
| 227 | date | NO | | NULL | |
| 228 | int(11) | NO | | NULL | |
| 229 | int(11) | NO | MUL | NULL | |
| 230 | int(11) | NO | MUL | NULL | |
+-----------+---------+------+-----+---------+----------------+
And vtiger_assetscf
+--------------+---------+
| assetid | cf_658 |
+--------------+---------+
| 224 | Value 1 |
| 225 | Value 2 |
| 226 | Value 3 |
| 227 | Value 2 |
| 228 | Value 3 |
| 229 | Value 1 |
| 230 | Value 3 |
+--------------+---------+
After one day of trying and errors using Trigger, INSERT and UPDATE I give up and decided to ask the experts...
A new row is added in both tables at the same time (with a new assetid automatically added)
I need to automatically import and update (populate) the values from cf_658 column at vtiger_assetcf table to the assetname column at vtiger_assets table.
I have tried:
create trigger 'ativos' after insert on vtiger_assetscf
for each row
begin
insert into vtiger_assets (assetid, assetname) values (new.assetid, new.cf_658);
end#
I have tried a combination of INSERT and UPDATE. No luck...
Can someone help me?

You have used single quotes around the name. That should cause a syntax error. Try this:
delimiter #
create trigger ativos after insert on vtiger_assetscf
for each row
begin
insert into vtiger_assets(assetid, assetname)
values (new.assetid, new.cf_658);
end; #

I hope you have already solved your problem. If not, I may have some questions to clarify:
1.- What do you mean with
A new row is added in both tables at the same time[...]
Is it that you use one call to the DB in which you insert both rows? Because I guess you are doing two queries on one call. One that inserts into vtiger_assets and then one that inserts into vtiger_assetscf
If it is the case, maybe you are triggering the ativostrigger before you have the row from wich to copy the data.
2.- With
with a new assetid automatically added
I supose you have your auto_incrementproperty enabled for the assetid column, but this makes me wonder, why do you have separate tables if one just copy data recently sent?
Maybe you could send one query only to vtiger_assets and have a trigger in that table (not into vtiger_assetscf) that creates a new row into vtiger_assetscf (but now I think maybe your tables are not completely shown here....)
3.- Finally: Is your assetid a key column? (if you're using auto_increment, I bet it is). If it's the case, I think the error you get is that you try to insert a row in a table with a duplicate value (the assetid).
Maybe try this instead:
create trigger `ativos` after insert on `vtiger_assetscf`
for each row
begin
update `vtiger_assets` SET `assetname` = new.`cf_658` WHERE `assetid` = NEW.`assetid`;
end#
I know It's been a while, but still...

Related

MySQL increase the old value by the new value when inserting new records by "on duplicate key update"

I've created a new table like this:
+------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| first | varchar(100) | NO | PRI | NULL | |
| last | varchar(400) | NO | PRI | NULL | |
| source | varchar(100) | NO | | NULL | |
| count | int | YES | | 1 | |
+------------+--------------+------+-----+---------+-------+
And I try to insert multiple records to this table using this:
insert into my_table(first,last,source,count) values ('a','b','c',50),('a','b','c',20),('d','e','f',30) on duplicate key update count = count + 1;
After insert, this is the content of the table:
+------------+-----------+--------+-------+
| first | last | source | count |
+------------+-----------+--------+-------+
| a | b | c | 2 |
| d | e | f | 1 |
+------------+-----------+--------+-------+
However, I'd like the count to be updated by the numbers provided in the values of the new records (i.e., 50, 20, and 30 in the provided example). So, the table should look like this:
+------------+-----------+--------+-------+
| first | last | source | count |
+------------+-----------+--------+-------+
| a | b | c | 70 |
| d | e | f | 30 |
+------------+-----------+--------+-------+
Is it possible to achieve this using "on duplicate key update" in MySQL? Or is there any other efficient way to achieve this? The table will be very large (with millions of rows).
VALUES() is the method to use, as GMB mentioned, if you are on a mysql version older than 8.0.19. However, it was deprecated as of 8.0.20, if you are using mysql 8.0.19 or newer its recommended to give an alias to the rows being inserted, and then refer to the values of the inserts by the alias like this:
insert into my_table (first, last, source, count)
values ('a','b','c',50), ('a','b','c',20), ('d','e','f',30) as newRow
on duplicate key update count = count + newRow.count;
More information can be found here: https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html
Consider the VALUES() syntax, that you can use in the on duplicate key clause to refer to the column value that would otherwise have been inserted:
insert into my_table(first, last, source, count)
values ('a','b','c',50), ('a','b','c',20), ('d','e','f',30)
on duplicate key update count = count + VALUES(count);
Note: first, last and source are MySQL keywords. I would not recommend using them as column names.

mysql: new keyword not recognized on trigger creation

Working on mysql.5.7
Here is my bugs table
MySQL [jira_statistics]> describe bugs;
+---------------------------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------------------------+--------------+------+-----+---------+-------+
| issue_key | varchar(45) | NO | PRI | NULL | |
| release_name | varchar(45) | YES | MUL | NULL | |
| issue_summary | varchar(200) | YES | | NULL | |
| story_points | int(11) | NO | | 0 | |
| qa_reopened | float | NO | | 0 | |
| done_reopened | float | NO | | 0 | |
This table is updated by periodic calls to LOAD DATA LOCAL INFILE bugs <file.csv>
Whenever this update takes place (which may either update existing lines and/or insert new ones) I want another table that has some yielded statistics to be updated via the following trigger
create trigger update_bugs_stats after insert on `jira_statistics`.`bugs` for each row
begin
delimiter ;
-- STORY POINTS -------------------------
SELECT AVG(story_points) INTO #avg_bugs_storypoints FROM `jira_statistics`.`bugs` WHERE release_name = new.release_name;
SELECT MAX(story_points) INTO #max_bugs_storypoints FROM `jira_statistics`.`bugs` WHERE release_name = new.release_name;
SELECT MIN(story_points) INTO #min_bugs_storypoints FROM `jira_statistics`.`bugs` WHERE release_name = new.release_name;
INSERT INTO storypoints_stats (release_name, avg_bugs_storypoints, max_bugs_storypoints, min_bugs_storypoints)
VALUES (relName, #avg_bugs_storypoints, #max_bugs_storypoints, #min_bugs_storypoints)
ON DUPLICATE KEY UPDATE
relName=new.release_name,
avg_bugs_storypoints=#avg_bugs_storypoints,
max_bugs_storypoints=#max_bugs_storypoints,
min_bugs_storypoints=#min_bugs_storypoints;
However this gives me the following error whenever trying to create the trigger:
Unknown column new.release_name in where clause.
Why isn't the new keyword bein recognized?
Because new is reserved as a system word
Ref: https://dev.mysql.com/doc/refman/8.0/en/keywords.html
Please modify
new.release_name ==> `new`.`release_name`
etc..
Τhe error was more stupid than I thought;
I was working directly on sql query editor and not on the triggers tab of mysql workbench so it did not parse correctly the new keyword`.

MySQL: Strange behavior of UPDATE query (ERROR 1062 Duplicate entry)

I have a MySQL database the stores news articles with the publications date (just day information), the source, and category. Based on these I want to generate a table that holds the article counts w.r.t. to these 3 parameters.
Since for some combinations of these 3 parameters there might be no article, a simple GROUP BY won't do. I therefore first generate a table news_article_counts with all possible combinations of the 3 parameters, and an default article_count of 0 -- like this:
SELECT * FROM news_article_counts;
+--------------+------------+----------+---------------+
| published_at | source | category | article_count |
+------------- +------------+----------+---------------+
| 2016-08-05 | 1826089206 | 0 | 0 |
| 2016-08-05 | 1826089206 | 1 | 0 |
| 2016-08-05 | 1826089206 | 2 | 0 |
| 2016-08-05 | 1826089206 | 3 | 0 |
| 2016-08-05 | 1826089206 | 4 | 0 |
| ... | ... | ... | ... |
+--------------+------------+----------+---------------+
For testing, I now created a temporary table tmp as the GROUP BY result from the original news article table:
SELECT * FROM tmp LIMIT 6;
+--------------+------------+----------+-----+
| published_at | source | category | cnt |
+--------------+------------+----------+-----+
| 2016-08-05 | 1826089206 | 3 | 1 |
| 2003-09-19 | 1826089206 | 4 | 1 |
| 2005-08-08 | 1826089206 | 3 | 1 |
| 2008-07-22 | 1826089206 | 4 | 1 |
| 2008-11-26 | 1826089206 | 8 | 1 |
| ... | ... | ... | ... |
+--------------+------------+----------+-----+
Given these two tables, the following query works as expected:
SELECT * FROM news_article_counts c, tmp t
WHERE c.published_at = t.published_at AND c.source = t.source AND c.category = t.category;
But now I need to update the article_count of table news_article_counts with the values in table tmp where the 3 parameters match up. For this I'm using the following query (I've tried different ways but with the same results):
UPDATE
news_article_counts c
INNER JOIN
tmp t
ON
c.published_at = t.published_at AND
c.source = t.source AND
c.category = t.category
SET
c.article_count = t.cnt;
Executing this query yields this error:
ERROR 1062 (23000): Duplicate entry '2018-04-07 14:46:17-1826089206-1' for key 'uniqueIndex'
uniqueIndex is a joint index over published_at, source, category of table news_article_counts. But this shouldn't be a problem since I do not -- as far as I can tell -- update any of those 3 values, only article_count.
What confuses me most is that in the error it mentions the timestamp I executed the query (here: 2018-04-07 14:46:17). I have no absolutely idea where this comes into play. In fact, some rows in news_article_counts now have 2018-04-07 14:46:17 as value for published_at. While this explains the error, I cannot see why published_at gets overwritten with the current timestamp. There is no ON UPDATE CURRENT_TIMESTAMP on this column; see:
CREATE TABLE IF NOT EXISTS `test`.`news_article_counts` (
`published_at` TIMESTAMP NOT NULL,
`source` INT UNSIGNED NOT NULL,
`category` INT UNSIGNED NOT NULL,
`article_count` INT UNSIGNED NOT NULL DEFAULT 0,
UNIQUE INDEX `uniqueIndex` (`published_at` ASC, `source` ASC, `category` ASC))
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8mb4;
What am I missing here?
UPDATE 1: I actually checked the table definition of news_article_counts in the database. And there's indeed the following:
mysql> SHOW COLUMNS FROM news_article_counts;
+---------------+------------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------------------+------+-----+-------------------+-----------------------------+
| published_at | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| source | int(10) unsigned | NO | | NULL | |
| category | int(10) unsigned | NO | | NULL | |
| article_count | int(10) unsigned | NO | | 0 | |
+---------------+------------------+------+-----+-------------------+-----------------------------+
But why is on update CURRENT_TIMESTAMP set. I double and triple-checked my CREATE TABLE statement. I removed the joint index, I added an artificial primary key (auto_increment). Nothing help. I've even tried to explicitly remove these attributes from published_at with:
ALTER TABLE `news_article_counts` CHANGE `published_at` `published_at` TIMESTAMP NOT NULL;
Nothing seems to work for me.
It looks like you have the explicit_defaults_for_timestamp system variable disabled. One of the effects of this is:
The first TIMESTAMP column in a table, if not explicitly declared with the NULL attribute or an explicit DEFAULT or ON UPDATE attribute, is automatically declared with the DEFAULT CURRENT_TIMESTAMP and ON UPDATE CURRENT_TIMESTAMP attributes.
You could try enabling this system variable, but that could potentially impact other applications. I think it only takes effect when you're actually creating a table, so it shouldn't affect any existing tables.
If you don't to make a system-level change like this, you could add an explicit DEFAULT attribute to the published_at column of this table, then it won't automatically add ON UPDATE.

How can I make MySQL automatically delete records of a table when date of deletion is specified in each record?

I have made the following table in MySQL:
mysql> use test;
Database changed
mysql> desc NeoTec_test;
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| Product_Key | varchar(10) | NO | PRI | NULL | |
| Validation | date | YES | | NULL | |
| Expiry | date | YES | | NULL | |
+-------------+-------------+------+-----+---------+-------+
3 rows in set (0.03 sec)
mysql> select * from NeoTec_test;
+-------------+------------+------------+
| Product_Key | Validation | Expiry |
+-------------+------------+------------+
| GF427DHH5 | 2017-11-16 | 2017-11-17 |
| GFHJV75HG | 2017-11-16 | 2017-11-18 |
| GFJYFRTV5 | 2017-11-16 | 2017-11-20 |
+-------------+------------+------------+
3 rows in set (0.00 sec)
Now coming to the point, I need some help with a part of my project. I want MySQL to automatically delete the Product keys that have expired, i.e., I want to get the product keys deleted automatically on their expiry dates given under the "Expiry" Column of the table. How can I do so? I am a total newbie to MySQL events so I would appreciate the full code... Thank you! :-)
Earlier research I did was not fruitful, but I did found this, which was half helpful...:
How to delete a MySQL record after a certain time
You can use event scheduler to perform the task like below:
DELIMITER //
CREATE EVENT eventName
ON SCHEDULE EVERY 1 WEEK
STARTS 'Some Date to start'
ENDS 'End date If any'
DO
BEGIN
DELETE FROM NeoTec_test WHERE NOW() > Expiry
END//
DELIMITER ;
Thete is no functionality in mysql to automatically delete a record. You need to trigger the deletion either through a scheduler (mysql's as shown in the question you found, or an external scheduler such as cron), or via a database trigger.
The latter one is probably an overkill.
I would use a scheduler set to a convenient interval based on your business requirements to clean up the table.

on duplicate key update result affecting all the rows of the table

I have a table of this structure:
mysql> desc securities;
+-----------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------+-------+
| sym | varchar(19) | NO | PRI | | |
| bqn | int(11) | YES | | NULL | |
| sqn | int(11) | YES | | NULL | |
| tqn | int(11) | YES | | NULL | |
+-----------------+-------------+------+-----+---------+-------+
4 rows in set (0.01 sec)
I am trying to do a select and an update within the same query, so the reason I have chosen
insert into securities (sym, bqn, sqn , tqn) values('ANK', 50,0,1577798)
on duplicate key update bqn=bqn+50 , sqn=sqn+0 , tqn=tqn+1577798;
When I ran the above I observed it is in fact changing the values for all the other rows also.
Is this behaviour expected? I am using MySQL Database.
Your fiddle is missing the key, and the INSERT statement in the right panel (where it does not belong in the first place) is using different column names … *sigh*
Define the symbol column as PRIMARY KEY – and use the VALUES() syntax to get the values to add in the ON UPDATE part, so that you don’t have to repeat them every single time:
insert into securities
(symbol, buyerquan, sellerquan , totaltradedquan)
values('BANKBARODA', 73, 0, 4290270)
on duplicate key update
buyerquan=buyerquan+VALUES(buyerquan),
sellerquan=sellerquan+VALUES(sellerquan),
totaltradedquan=totaltradedquan+VALUES(totaltradedquan);
Works perfectly fine, result values are as to be expect from the input: http://sqlfiddle.com/#!2/21638f/1