I have a table, Transactions1, with 3 Columns
ID,NetProfit and RunningTotal
I'm trying to create a trigger that automatically updates the RunningTotal on new entry as shown below:
ID NetProfit RunningTotal
1 100 100
2 50 150
3 200 350
I have tried the following code but can't seem to get it to work:
CREATE TRIGGER RTTrigger BEFORE INSERT ON Transactions1
FOR EACH ROW
set #RT1 := 0;
update Transactions1
set RunningTotal = (#RT1 := #RT1 + 'NetProfit')
order by ID;
I get the error:
Not allowed to return a resultset from a trigger
I have to mention that i'm new to Mysql and PhPMyAdmin:-)
Thanx in advance
Related
Hi Can any one please help me with a procedure for inserting 7 million records for 7 years (million records each year) in loop in MYSQL,
I need to insert in a batch of 500,000 for each batch .
Data is there in table "Archive_data", need to insert in "Stg_table"
Archive data has yearly sales, i want to write a loop in MYSQL looping on Year and insert in a batch of 500K each
i tried
insert into SDL_Stg_Bill_Details
select SDL_Id, Rec_Is_Processed, concat(Bill_Header_Key,'_',Row_Num), Bill_Header_Key,Row_Num from (
SELECT SDL_Id, Rec_Is_Processed, Bill_Details_Key, Bill_Header_Key,
ROW_NUMBER() OVER(partition by Bill_Header_Key order by SDL_Id ) Row_Num
FROM PANTALOONS_SOLUS_PROD.SDL_Stg_Bill_Details_Archive
where EXTRACT(YEAR_MONTH FROM Bill_Date) in ('201406',
'201407',
'201408',
'201409',
'201410') ff
i am getting lock wait time out exceeded error if i am trying 7 M records
at once
Thanks in advance
Not sure if this is what you want, but I hope with some tweaks it might help you:
DELIMITER $
CREATE PROCEDURE CopyDataInBatch()
BEGIN
DECLARE x INT;
DECLARE y INT;
SET x = 1;
SET y = x + 10000;
the_loop : LOOP
IF x > 1000000 THEN /* Use the number of rows you wanted to copy*/
LEAVE the_loop;
END IF;
INSERT INTO table_in_which_copying (col_name_1, col_name_2)
SELECT (col_name_1, col_name_2) FROM table_from_which_copying
ORDER BY (col_name_1)
LIMIT x, y;
SET x = x + 10000;
SET y = y + 10000;
SELECT "Copied 10000 rows"; /* Only for testing... better remove it(?)*/
END LOOP;
END $
DELIMITER ;
I have a table called cycle, that has the following structure:
id
starts_at
ends_at
the id is not unique, so its registered:
id starts_at ends_at cycle_year cycle_number
120 jan-01-2017 jan-05-2017 2017 1
120 jan-06-2017 jan-11-2017 2017 2
120 jan-12-2017 jan-18-2017 2017 3
What I need to do, its to create a view like this:
id starts_at ends_at how_far_it_is_from_newest
120 jan-01-2017 jan-05-2017 2
120 jan-06-2017 jan-11-2017 1
120 jan-12-2017 jan-18-2017 0
Any ideas?
I have created this one, but it has a problem:
SET #counter = -1;
SELECT
*,
concat(year, LPAD(number, 3, '0')) as 'cycle_ref', // eg. 2017001
(#counter:=#counter + 1) as counter
FROM
cycle
where
id = 120
ORDER by
cycle_ref DESC
;
it return correctly, but if I take off the id=120, it will count regardless the id.
id starts_at ends_at how_far_it_is_from_newest
120 jan-12-2017 jan-18-2017 0
77 jan-16-2017 jan-28-2017 1 <-- wrong:should be 0
120 jan-06-2017 jan-11-2017 2 <-- wrong:should be 1
120 jan-01-2017 jan-05-2017 3 <-- wrong:should be 2
This worked to me:
DROP FUNCTION IF EXISTS initCycleIndex;
DELIMITER $$
CREATE FUNCTION initCycleIndex() returns INT
BEGIN
SET #counter:=-1;
RETURN(#counter);
END $$
DELIMITER ;
DROP FUNCTION IF EXISTS getCycleIndex;
DELIMITER $$
CREATE FUNCTION getCycleIndex() RETURNS INT
DETERMINISTIC
BEGIN
SET #counter:= #counter + 1;
return (#counter);
END $$
DELIMITER ;
CREATE OR REPLACE VIEW vw_cycle_indexed as
SELECT
c.*,
concat(c.year, LPAD(c.number, 3, '0')) as 'cycle_ref',
getCycleIndex() as 'index'
FROM
cycle c
JOIN (select initCycleIndex()) r
ORDER by
cycle_ref DESC
;
#SELECT * FROM vw_cycle_indexed where id = 178;
Multiple problems to address here.
To initialize your variables you don't need functions. Just do it in a subquery (or in separate SET statements).
Biggest problem: You haven't defined an order to determine what's the newest entry. Your "how far it is from newest" might change every once in a while.
All you have implemented is a row counter. Of course it continues counting, regardless if the id is totally different. You have to have another variable that holds the value of the previous row. You can do so, by assigning the value of the current row to a variable after you've checked the value of the variable. The order in the select part is therefore very important.
The IF() function is quite simple, when the previous row id is different from the current row, return 0, otherwise the incremented row counter. And that's why it's also important to first order by id in the ORDER clause.
Have a try with this one:
SELECT
c.*,
concat(year, LPAD(number, 3, '0')) as 'cycle_ref',
#counter := IF(#prevID != id, 0, #counter + 1),
#prevID := id
FROM
cycle c
, (SELECT #counter := -1, #prevID := NULL) var_init_subquery
ORDER by
id, ends_at DESC, cycle_ref
;
Only downside is, you can't use this statement in a VIEW, because variables aren't allowed there. I will try your approach with the functions, though. It might be a neat workaround.
i have the following table
employee(id, pay-todate)
month_pay(employee_id(fk), hourly_pay_rate, hours_worked)
How would i go about creating a trigger that inserts
the total of(hourly_pay_rate x hours_worked) into pay-todate
whenever a new row is added to month_pay?
I also need to subtract 10% if the pay-todate is 10 000 or greater
delimiter |
CREATE TRIGGER insert_pay_trigger BEFORE INSERT ON month_pay
FOR EACH ROW BEGIN
insert into employee (id, `pay-todate`)
select NEW.employee_id,
case when NEW.hourly_pay_rate * NEW.hours_worked >= 100000
then NEW.hourly_pay_rate * NEW.hours_worked * 0.9
else NEW.hourly_pay_rate * NEW.hours_worked
end;
END
|
delimiter ;
I'm building some application, which is connected to mysql database.
In mysql in let say table test I have an Integer field called myId.
With my first insert to the myId value "1" is added, with my second insert i'm adding value "20".
Now my question is: is there any possibility, that to the first value "1" after second insert will be auto added "0".
So i will have:
|myId|
10
20
And if a add "300", so to the two first inserts will be added next 0 ?
|myId|
100
200
300
Just do it when you select data
set #max:=(select max(length(myId)) from your_table);
SELECT myId * power(10, (#max - length(myId))) from table;
unverified:
delimiter |
CREATE TRIGGER upd_entries AFTER INSERT ON your_table
FOR EACH ROW
BEGIN
update your_table
set myId = myId * power(10, ((select * from (select max(length(myId)) from your_table)) - length(myId)));
END;
|
delimiter ;
I've read that this can be done without issue using MyISAM as it is the default behavior , but I'm using InnoDB so need a trigger for such.
The two PK fields are batch and lineItem. If a record is deleted I want the numbering to start from the largest integer for batch. Not fill in the holes.
This is to set up a testing environment for a legacy system. So the schema is the way it is, I thought I'd mention that to avoid any discussion about whether it is good or not.
Edit: I want something like the following insert statement as a trigger
INSERT INTO payroll(`batch`,`lineItem`)
(select 'T105',t1.lineItem + 1 from payroll as t1 where batch = 'T105' order by lineItem desc limit 1);
But where 'T105' (the batch id) is hard coded I want the trigger to pick that up from the insert.
So I want to be able to say something like:
INSERT INTO payroll(`batch`)VALUES('T001','T001','T001', 'T002', 'T002', 'T002');
and I would expect to see in the table:
batch lineItem
T001 1
T001 2
T001 3
T002 1
T002 2
T002 3
Getting further:
In trying to implement this I've come up with:
DELIMITER $$
CREATE TRIGGER `co05_test`.`ins_lineItem`
BEFORE INSERT ON `co05_test`.`my_table`
FOR EACH ROW
BEGIN
select lineItem + 1 into #newLineItem from my_table where batch = NEW.batch order by lineItem desc limit 1;
set NEW.lineItem = #newLineItem;
END$$
However when I try...
INSERT INTO `co05_test`.`my_table`(`batch`)VALUES('T001');
I get this error: Column 'lineItem' cannot be null
Which is defined as not being nullable but I though the trigger should set the value!
Solution which I used:
-- Trigger DDL Statements
DELIMITER $$
USE `co05_test`$$
CREATE TRIGGER `co05_test`.`ins_lineItem`
BEFORE INSERT ON `co05_test`.`my_table`
FOR EACH ROW
BEGIN
select count(*) into #batchCount from my_table where batch = NEW.batch;
select lineItem + 1 into #newLineItem from my_table where batch = NEW.batch order by lineItem desc limit 1;
if #batchCount > 0 then
set NEW.lineItem = #newLineItem;
else
set NEW.lineItem = 1;
end if;
END;
$$
Have you tried declaring the variable instead?
DELIMITER $$
CREATE TRIGGER `co05_test`.`ins_lineItem`
BEFORE INSERT ON `co05_test`.`my_table`
FOR EACH ROW
BEGIN
DECLARE newLineItem INT;
SELECT
lineItem + 1 into newLineItem
FROM my_table
WHERE batch = NEW.batch
ORDER BY lineItem DESC
LIMIT 1;
SET NEW.lineItem = newLineItem;
END$$