sql refer row on masive insert using a stored procedures - mysql - mysql

I have a table task, this table contains information of recurring tasks, fox example daily tasks, so I repeat each task because I want to know the result of each task over time
1/1/2014 Get Pizza OK
1/2/2014 Get Pizza OK
1/3/2014 Get Pizza Error
1/4/2014 Get Pizza OK
For this I made a stored procedure
DELIMITER $$
CREATE DEFINER=`db`#`%` PROCEDURE `SP_repeat_task`()
BEGIN
INSERT INTO Task
(
date_of_assignment,
Some fields
)
SELECT
DATE_ADD(tas.date_of_assignment, INTERVAL 1 DAY),
another fields
FROM Task tas
WHERE tas.date_of_assignment=CURRENT_DATE and many conditions
)
;
END
This procedure is invoked every day 5 minutes before midnight. And produces something like this
The problem is that I have to insert the id of the records added in another table
For example
When I add 4 tasks in insert-select statement i need add these to another table
In my case, there can be multiple records for each task.
I can easily obtain id_person in my select, but not how to use it in the next insert.
I cant change the structure of the tables, I have only my stored procedure to work
I read about mysqli_insert_id, but not how to use it in my case
EDIT
based in b.b3rn4rd answer
When i add the other field in cursor select
DECLARE records_to_clone_cursor CURSOR FOR
SELECT `field1`, `field2`, `field3` FROM `Task` WHERE ... ;
In FETCH return more rows because as there is a one to many relationship in my tables
so the query returns with old fields
DECLARE records_to_clone_cursor CURSOR FOR
SELECT `field1`, `field2` FROM `Task` WHERE ... ;
And i tried change the prepared statement for a classic Insert-Select
SET #NEW_ID = LAST_INSERT_ID();
INSERT INTO Another_table
(
id_task,
id_person
)
SELECT tas.id_task,
pe.id_person
FROM Task tas
INNER JOIN Person pe
ON pe.id_person = tas.id_assigned
WHERE tas.id_task= #NEW_ID;
-- EXECUTE insert_responables USING #NEW_ID, #Var_3;
But does nothing, first prepared works well, and Select-Inser work in nornal query.
that I can do?
EDIT 2
if I need to insert the values​​, but because they are different cause the cursor query returns more records and these are duplicated by the number of records in the field is_person

Related

MySQL stored procedure insert validation

I have two tables acceptances and turnovers. Let's just assume that these tables both have the columns id, and date only.
I need to be able to insert same dates across the 2 tables only up to 4 times.
For example: 5 users are trying to create a booking schedule.
3 of the 5 users create an acceptance schedule.
2 of the 5 users create a turnover schedule.
1 of these inserts should be rejected even in race conditions.
I have the following stored procedure:
BEGIN
DECLARE acceptanceDateEntryCount int;
DECLARE turnoverDateEntryCount int;
SELECT COUNT(date) FROM acceptances WHERE DATE(date) = DATE(insertDate) INTO acceptanceDateEntryCount;
SELECT COUNT(date) FROM turnovers WHERE DATE(date) = DATE(insertDate) INTO turnoverDateEntryCount;
IF((acceptanceDateEntryCount + turnoverDateEntryCount) < 4) THEN
INSERT INTO acceptances (date) VALUES (insertDate);
ELSE
SIGNAL SQLSTATE
'45030'
SET
MESSAGE_TEXT = 'Cannot create acceptance schedule. Max limit of 4 same date entries are found in acceptances table and turnovers table',
MYSQL_ERRNO = '45030';
END IF;
END
NOTE: This stored procedure is for creating an acceptance booking only. But there is another stored procedure which is just the same, but inserts into the turnovers table.
Is this stored procedure enough to make sure that even in race conditions where a lot of users try to create a booking schedule, if entries of the same date exists, the insert will be rejected if it has the same date.
Or should I just scrap this and use pessimistic locking to make sure that inserts on these tables do not run concurrently?
Tack FOR UPDATE on the end of each SELECT statement.
Also include
START TRANSACTION;
and
COMMIT;

mysql trigger for loop

I'm trying to do some mysql trigger coding. I fail every time I meet loops.
CREATE TRIGGER `after_insert` AFTER INSERT ON `table_users`
FOR EACH ROW BEGIN
INSERT INTO table_user_plan (user_id, plan_id) VALUES
(NEW.id, (SELECT id FROM table_plans))
;
END
Here trigger is successfully created, but I get error
#1242 - Subquery returns more than 1 row
I understand this cannot work, because there are more than one row in table_plans... but how can I handle this if I want to add multiple rows or how can I make a loop and firstly select plans then insert into table_users?
Thanks in advanced
To insert multiple rows based on a SELECT you would use the INSERT ... SELECT FROM ... syntax. In this case, you would use something like
INSERT INTO table_user_plan
SELECT NEW.id AS user_id, tp.id AS plan_id
FROM table_plans tp;
(I think that should work, although I've never actually tried to use NEW in this context.)

How to automatic truncate table in MySQL every 3 months?

I have a PHP/MySQL project having 15 tables. One of table name tbl_user_log, where all user log will saved. I want to empty or truncate this table in every 3 month.How could I do this using trigger or any solution is applicable.
You can set a cronjob to a certain route of your project to perform following sql:
DELETE FROM tbl_user_log
See this website: http://setcronjob.com
Or you can simply use mysql EVENTs.
It may helps you
declare #tbl nvarchar(max)='table_name'
if (
(select create_date FROM
sys.tables where name=#tbl)
<= (SELECT DATEADD(month,-3, GETDATE()))
begin
truncate table #tbl
end
else
select 'table creation date is not more than 3 months'
better you can put this in a procedure and u can directly pass table name as input and can wrk efficently

SQL check if existing row, if not insert and return it

I'm having a problem with my sql query. I need to insert a data that needs to be checked first if it is existing or not. If the data is existing the sql query must return it, if not insert and return it. I already google it but the result is not quite suitable to my problem. I already read this.
Check if a row exists, otherwise insert
How to 'insert if not exists' in MySQL?
Here is a query that' I'm thinking.
INSERT INTO #tablename(#field, #conditional_field, #field, #conditional_field)
VALUES(
"value of field"
(SQL QUERY THAT CHECK IF THERE IS AN EXISTING DATA, IF NOT INSERT THE DATA and RETURN IT, IF YES return it),
"value of feild",
(SQL QUERY THAT CHECK IF THERE IS AN EXISTING DATA, IF NOT INSERT THE DATA and RETURN IT, IF YES return it)
);
Please take note that the conditional field is a required field so it can't be NULL.
Your tag set is quite weird, I'm unsure you require all the technologies listed but as long as Firebird is concerned there's UPDATE OR INSERT (link) construction.
The code could be like
UPDATE OR INSERT INTO aTable
VALUES (...)
MATCHING (ID, SomeColumn)
RETURNING ID, SomeColumn
Note that this will only work for PK match, no complex logic available. If that's not an option, you could use EXECUTE BLOCK which has all the power of stored procedures but is executed as usual query. And you'll get into concurrent update error if two clients execute updates at one time.
You could split it out into 2 steps
1. run a select statement to retrieve the rows that match your valus. select count (*) will give you the number of rows
2. If zero rows found, then run the insert to add the new values.
Alternatively, you could create a unique index form all your columns. If you try to insert a row where all the values exist, an error will be returned. You could then run a select statement to get the ID for this existing row. Otherwise, the insert will work.
You can check with if exists(select count(*) from #tablename) to see if there is data, but with insert into you need to insert data for all columns, so if there is only #field missing, you cant insert values with insert into, you will need to update the table and go with a little different method. And im not sure, why do you check every row? You know for every row what is missing? Are you comparing with some other table?
You can achieve it using MySQL stored procedure
Sample MySQL stored procedure
CREATE TABLE MyTable
(`ID` int, `ConditionField` varchar(10))
;
INSERT INTO MyTable
(`ID`, `ConditionField`)
VALUES
(1, 'Condition1'),
(1, 'Condition2')
;
CREATE PROCEDURE simpleproc (IN identifier INT,ConditionData varchar(10))
BEGIN
IF (SELECT ID FROM MyTable WHERE `ConditionField`=ConditionData) THEN
BEGIN
SELECT * FROM MyTable WHERE `ConditionField`=ConditionData;
END;
ELSE
BEGIN
INSERT INTO MyTable VALUES (identifier,ConditionData);
SELECT * FROM MyTable WHERE `ConditionField`=ConditionData;
END;
END IF;
END//
To Call stored procedure
CALL simpleproc(3,'Condition3');
DEMO

Mysql Loop through selected column and execute Insert query in the loop

I'm trying to loop over selected slugs and execute little complicated INSERT INTO SELECT query.
slugs[iteration] usage is not a correct mysql syntax. But I have to access fetched slugs one by one inside the query. How Could I achieve that ?
DELIMITER $$
CREATE PROCEDURE create_sitemap_from_slugs()
BEGIN
SELECT `slug` INTO slugs FROM slug_table;
SELECT COUNT(*) INTO count FROM slug_table;
SET iteration = 0;
START TRANSACTION;
WHILE iteration < count DO
INSERT INTO line_combinations
SELECT REPLACE(`line`, '{a}', slugs[iteration]) AS `line`
FROM line_combinations
WHERE `line` LIKE CONCAT('%/', '{a}', '%');
SET iteration = iteration + 1;
END WHILE;
COMMIT;
END
$$
DELIMITER ;
Btw, I don't want to use any external programming language to make this, this procedure will be working for billions of rows. I read Loops in SQL is not a good way due to performance concerns.
If you suggest another way I would accept this also.
I asked another detailed question but couldn't get an answer. if you would like to check that also : https://stackoverflow.com/questions/35320494/fetch-placeholders-from-table-and-place-into-generated-line-combination-pattern
So for each line with {a} you need to insert COUNT(*) from slug_table times values filled with slug value.
It seems you can do that just in one INSERT from SELECT
INSERT INTO line_combinations
(SELECT REPLACE(lc.line, '{a}', st.slug) AS `line`
FROM line_combinations lc, slug_table st
WHERE lc.line LIKE CONCAT('%/', '{a}', '%');
UPDATE:
You can create a temp table line_combinations2 and insert all the records
FROM line_combinations
WHERE line LIKE CONCAT('%/', '{a}', '%')
into the temp table. Then just use the temp table in the INSERT instead of original one