I have three tables a test_cases table, a schedule table, an aggregate_summary table
test_cases
caseID | file_name
--------+-------------------------
1 | Test 1
2 | Test 2
3 | Test 3
schedule
| scheduleID | caseID | schedule_time
+------------+--------+---------------------
| 1 | 1 | 2016-02-29 02:15:00
| 2 | 2 | 2016-02-29 12:00:00
| 3 | 3 | 2016-02-27 12:00:00
| 4 | 2 | 2016-02-25 07:26:00
| 5 | 1 | 2016-02-26 07:37:00
| 6 | 2 | 2016-02-27 07:39:00
| 7 | 2 | 2016-02-28 07:25:00
| 8 | 1 | 2016-02-29 08:38:00
| 9 | 2 | 2016-02-29 07:08:00
aggregate_summary which has start_time and file name and other fields
I want to create a trigger so after a test is scheduled it puts the schedule_time into start_time (on aggregate_summary table) and puts file_name(from test_cases) into file_name field on aggregate_summary table.
I cannot get the syntax right:
CREATE TRIGGER OnScheduleInsert AFTER INSERT ON schedule FOR EACH ROW BEGIN INSERT INTO aggregate_summary (start_time) VALUES(NEW.schedule_time)
UPDATE aggregate_summary SET file_name=(SELECT file_name FROM test_cases WHERE NEW.caseID=test_cases.caseID) END;
To execute queries in the body of the trigger they must be separated by semicolons. In order to have your MySQL client not interpret the semicolon as the end of the CREATE TRIGGER statement, you might first need to change the delimiter to something other than a semicolon, then change it back afterwards.
DELIMITER //
CREATE TRIGGER OnScheduleInsert
AFTER INSERT ON schedule
FOR EACH ROW
BEGIN
INSERT INTO aggregate_summary (start_time) VALUES(NEW.schedule_time);
UPDATE aggregate_summary SET file_name=(SELECT file_name FROM test_cases WHERE NEW.caseID=test_cases.caseID);
END//
DELIMITER ;
I don't think the body of the trigger quite does what you want it to but I'm afraid I'm not really clear what the desired behaviour of the trigger is. Still, at least it's now syntactically valid.
Related
I have been working on a table to get the end timestamp of a play (nowPlaying) event based on the following conditions:
If there is a browseSearch between nowPlaying and browseFind, then the case is ignored.
browseFind would be the starting point for each of the nowPlaying event.
There could be any number of other events between a browseFind and nowPlaying.
What I have done is tried to partition the query and add another column with Start, Break, Skip and end as shown in table below:
The events are ordered by timestamp event_ts
+------+--------------+-------+---------------------+
| id | page_type | p_t | event_ts |
+------+--------------+-------+---------------------+
| 1 | browseFind | Start | 2021-01-01 06:00:00 |
| 1 | browseSearch | break | 2021-01-01 06:00:10 |
| 1 | browseFind | Start | 2021-01-01 06:01:00 |
| 1 | x-ray | skip | 2021-01-01 06:01:30 |
| 1 | browseSearch | break | 2021-01-01 06:02:00 |
| 1 | nowPlaying | end | 2021-01-01 06:03:00 |
| 1 | browseFind | Start | 2021-01-01 06:10:00 |
| 1 | abc | skip | 2021-01-01 06:11:00 |
| 1 | abc | skip | 2021-01-01 06:12:00 |
| 1 | nowPlaying | end | 2021-01-01 06:12:00 |
+------+--------------+-------+---------------------+
The only valid timestamp would be the last one 2021-01-01 06:12:00 because rest have break in between their Start and End. Also if there is no end and a start follows, then the loop will reset.
I saw a bunch of post on SO, but it was not done in SQL, but rather programmatically.
How can I use the p_t column to write a SQL that will look at events between the start and end if it exists and get the valid timestamp of end
My Query:
select id,
page_type,
case when page_type in ('browseFind') then 'Start'
when page_type in ('browseSearch') then 'break'
when page_type not in ('browseFind','nowPlaying') then 'skip'
when page_type in ('nowPlaying') then 'end'
end as p_t,
event_ts
from steps
order by event_ts;
Queries for DDL:
create table steps (id int, page_type varchar(100), event_ts timestamp);
insert into steps values (1,'browseFind','2021-01-01 6:00:00');
insert into steps values (1,'browseSearch','2021-01-01 6:00:10');
insert into steps values (1,'browseFind','2021-01-01 6:01:00');
insert into steps values (1,'x-ray','2021-01-01 6:01:30');
insert into steps values (1,'browseSearch','2021-01-01 6:02:00');
insert into steps values (1,'nowPlaying','2021-01-01 6:03:00');
insert into steps values (1,'browseFind','2021-01-01 6:10:00');
insert into steps values (1,'abc','2021-01-01 6:11:00');
insert into steps values (1,'abc','2021-01-01 6:12:00');
insert into steps values (1,'nowPlaying','2021-01-01 6:12:00');
Do you need in this:
WITH
cte AS ( SELECT id, page_type, event_ts,
LAG(page_type) OVER (PARTITION BY id ORDER BY event_ts) lag_page_type
FROM steps
WHERE page_type IN ('browseFind', 'browseSearch', 'nowPlaying') )
SELECT id, page_type, event_ts
FROM cte
WHERE page_type = 'nowPlaying'
AND lag_page_type = 'browseFind';
fiddle
i am new to this and want some help.i have table with name "abc" with following entries
+------+--------+------+
| Id | Name | City |
+------+--------+------+
| 101 | john | abc |
| 102 | Miller | cbz |
+------+--------+------+
and another table "xyz"
+------+--------+------+
| Id | Name | City |
+------+--------+------+
| 102 | Miller | cbz |
+------+--------+------+
i applied trigger on table "abc" which will update the table "xyz" with recently inserted values and will delete all previous entries...
for example, when i fire insert query on "abc" table i get ,"abc" as follow
insert into abc Values(103,'Joseph','xyz');
i get output for table "abc" as,
+------+--------+------+
| Id | Name | City |
+------+--------+------+
| 101 | john | abc |
| 102 | Miller | cbz |
| 103 | Joseph | xyz |
+------+--------+------+
and table "xyz" as,
+------+--------+------+
| Id | Name | City |
+------+--------+------+
| 103 | Joseph | xyz |
+------+--------+------+
now my question is how to acheive this using only one table(i dont want to use two table as this is not my requirement).
like following ..
insert into xyz values(104,'Ridhit','pqr');
+------+--------+------+
| Id | Name | City |
+------+--------+------+
| 104 | Ridhit | pqr |
+------+--------+------+
Please help.Trigger i used is
DELIMITER !!
create trigger OnlyOne BEFORE INSERT on abc
for each row
BEGIN
DECLARE a1 INT;
Select count(1) INTO a1 from xyz;
IF a1>0 THEN
delete from xyz limit 1;
insert into xyz(Id,Name,City) values (new.Id,new.Name,new.City);
ELSE
insert into xyz(Id,Name,City) values (new.Id,new.Name,new.City);
END IF;
END;
!!
DELIMITER ;
Do this on application level, but you better make sure you use transactions. You probably don't want to have an empty table, when the operation crashes in the middle.
You may also consider to have following approach.
Instead of deleting/updating whenever an insert occurs, add a column like created with default value of current timestamp to your table so that it looks something like this:
CREATE TABLE abc(
id int auto_increment primary key,
name varchar(50),
city varchar(50),
created timestamp default current_timestamp
);
To get the latest entry you just do
SELECT * FROM abc ORDER BY created DESC LIMIT 1;
Or you put this in a view
CREATE VIEW just_latest_entry_from_abc AS
SELECT * FROM abc ORDER BY created DESC LIMIT 1;
Then you just do
SELECT * FROM just_latest_entry_from_abc;
When table size matters, create a cronjob or a scheduled event to delete older entries on a regular basis.
I'm currently working with a client that wants their database to duplicate info into a second table in a different format when it is initially inserted.
Basically like the following:
Table 1
| ID | NAME | EMAIL | password |
--------------------------------------
| 1 | david | x#x.co | asx234 |
| 2 | anthony | y#x.co | 24gss3 |
| 3 | jillian | z#x.co | hdfg5d |
Every time a row gets inserted into table 1 they also want to take that information from table 1 and add it to Table 2
Table 2
| ID | NAME | EMAIL | password | signature | level | lastenter | register_date |
-----------------------------------------------------------------------------------------------
| 1 | david | x#x.co | asx234 | text | 3 | 0000-00-00 | Date of insert |
| 2 | anthony | y#x.co | 24gss3 | text | 3 | 0000-00-00 | Date of insert |
| 3 | jillian | z#x.co | hdfg5d | text | 3 | 0000-00-00 | Date of insert |
How do I set up a trigger to insert the data into Table 2 whenever a row is inserted into table 1?
Thanks!
Some thoughts below, but the trigger would look something like this:
DELIMITER $$
DROP TRIGGER IF EXISTS trgMyNewTrigger $$
CREATE TRIGGER trgMyNewTrigger AFTER INSERT ON Table1
FOR EACH ROW
BEGIN
INSERT into Table2 (ID,NAME,EMAIL,`password`,signature,`level`,lastenter,register_date) VALUES (
new.ID, new.NAME, new.EMAIL, new.password, 'text', 3, '0000-00-00', CURDATE() );
END $$
DELIMITER ;
This is not a great solution. Triggers in general can cause some nasty issues and limit your capabilities down the road. It would be better to reconsider the design of the table to be inclusive of the data you need, have the application perform the extra step or use some sort of ETL process to get the data at set intervals.
I will all assume the clear text passwords are for the example.
I have created 2 tables abc and xyz. Both table are having the same data as shown below.
Table abc:
+------+-------+--------+
| roll | name | status |
+------+-------+--------+
| 1 | john | I |
| 1 | ken | I |
| 1 | abel | I |
| 2 | aston | I |
| 2 | ron | I |
+------+-------+--------+
Table xyz:
+-------+-------+---------+
| roll1 | name1 | status1 |
+-------+-------+---------+
| 1 | john | I |
| 1 | ken | I |
| 1 | abel | I |
| 2 | aston | I |
| 2 | ron | I |
+-------+-------+---------+
The status in both tables can be updated to 'D' or 'E'. Suppose in table abc, if the status of John become 'D' then I need to take John's roll (that is 1) and update all the status in xyz to 'D' where roll1 = 1.
Similarly, suppose if the status of ron changed to 'E' in xyz table, then aston and ron status should be 'E' in table abc.
This need to be achieved using update triggers. I have created 2 update trigger for both the tables. The trigger used are
DELIMITER $$
DROP TRIGGER /*!50032 IF EXISTS */ `test2`.`abc_trigg`$$
create trigger `test2`.`abc_trigg` BEFORE UPDATE on `test2`.`abc`
for each row BEGIN
IF #__disable_trigger is null THEN
SET #__disable_trigger = 1;
if new.status = 'D' then
update xyz set status1='D' where roll1 = new.roll;
elseif new.status = 'E' then
update xyz set status1='E' where roll1 = new.roll;
end if;
end if;
end;
$$
DELIMITER ;
DELIMITER $$
DROP TRIGGER /*!50032 IF EXISTS */ `test2`.`xyz_trigg`$$
create trigger `test2`.`xyz_trigg` BEFORE UPDATE on `test2`.`xyz`
for each row BEGIN
IF #__disable_trigger is null THEN
SET #__disable_trigger = 1;
if new.status1 = 'D' then
update abc set status='D' where roll = new.roll1;
elseif new.status1 = 'E' then
update abc set status='E' where roll = new.roll1;
end if;
end if;
end;
$$
DELIMITER ;
But these triggers are not correct and I am not getting the expected output. Kindly guide me to fix the issue and help me to get the relevant output?
I have a database in MySQL. Here is SQL query to create it http://paste.org.ru/?xzctqi
Here is main table books. All I need to do is when I add some book, I choose publisher ID for it. After adding books, I need loop through all records in this table and increment column publisher_books_amount for all rows, which has same publisher as in currently added row.
+----+-------+--------+------------------------+-----------+
| id | title | author | publisher_books_amount | publisher |
+----+-------+--------+------------------------+-----------+
| 1 | Book1 | 1 | 0 | 1 |
| 2 | Book2 | 2 | 0 | 1 |
| 3 | Book3 | 1 | 0 | 2 |
| 4 | Book4 | 3 | 0 | 3 |
| 5 | Book1 | 3 | 0 | 1 |
+----+-------+--------+------------------------+-----------+
I've created trigger
DROP TRIGGER IF EXISTS `insert_trigger`;
DELIMITER |
CREATE TRIGGER `insert_trigger` AFTER INSERT ON books
FOR EACH ROW
BEGIN
UPDATE books SET publisher_books_amount = (publisher_books_amount + 1)
WHERE publisher = NEW.publisher;
END;
|
DELIMITER ;
But when I'm trying to add book, MySQL provides me with an error.
Can't update table 'books' in stored function/trigger because it is
already used by statement which invoked this stored function/trigger.
Don't ask me why do I have denormalized DB. I just need structure described above.
BTW I need to create same triggers after deleting and updating rows. If there are some problems with that, could you help me with it too?
Sincerely, Dmitriy.
Update inside a loop is not allowed, because it goes to infinite loop.
Try your triiger without update,with only set value this=this.