Not too familiar with the coding inside events, but the goal is:
select fid from table_%id% where...
"insert into resulttable (id, fid) values (%id, %fid)
Then create an event to do this every hour
I'd like to do this without creating a procedure, but might need to.
This is as close as I can get:
DECLARE cur_orgs CURSOR FOR SELECT orgId FROM organizations;
OPEN cur_orgs;
Reading_Orgs: LOOP
FETCH cur_orgs INTO _org_id;
DECLARE cur_fids CURSOR FOR SELECT fid FROM organization_+'_org_id';
OPEN cur_fids;
Reading_fids: LOOP
FETCH cur_fids INTO _fid_id;
insert into queue(orgId, fid) values (_org_id, _fid_id);
END LOOP;
CLOSE cur_fids;
insert into queue(orgId) values (_org_id);
END LOOP;
CLOSE cur_orgs;
Several comments:
MySQL does not use +
for string concatenation; that's a string concatenation operator only in Microsoft SQL Server and Microsoft Access, as far as I know.
You can't make a table name from an expression like organization_+'_org_id'
anyway. Table names are identifiers, not strings. Identifiers must be fixed in the query at the time it is parsed.
You wrote in a comment that your separate tables are there for a legal requirement, so I won't give you grief over designing the database this way.
I tested the following with MySQL 8.2.0:
CREATE EVENT myevent
ON SCHEDULE AT current_timestamp + INTERVAL 1 MINUTE
DO
BEGIN
DECLARE org_id BIGINT UNSIGNED;
DECLARE cur_orgs CURSOR FOR SELECT orgId FROM organizations;
OPEN cur_orgs;
Reading_Orgs: LOOP
FETCH cur_orgs INTO org_id;
SET @org_id = org_id;
SET @sql = CONCAT(
'INSERT INTO queue(orgId, fid)
SELECT ?, fid FROM organization_', @org_id);
PREPARE stmt FROM @sql;
EXECUTE stmt USING @org_id;
DEALLOCATE PREPARE stmt;
INSERT INTO queue(orgId) VALUES (@org_id);
END LOOP;
CLOSE cur_orgs;
END
Things to notice:
I used INSERT...SELECT
. This is because cursors in MySQL don't support dynamic SQL.
String concatenation of the query string is done with CONCAT()
, not +
.
PREPARE and EXECUTE only work with user variables (the type with the @
sigil), but cursors only work to fetch into declared local variables, so I had to copy org_id
to @org_id
. These are two different types of variables in MySQL.
Be careful about the potential SQL injection risk. I assume the org_id
variable has a numeric type, so there's no way it can contain risky characters. If org_id
is a string instead of a number, then this code has an SQL injection vulnerability, because the value of an org id could cause the prepared statement to do something you don't intend.
The result:
mysql> show tables;
+------------------+
| Tables_in_test |
+------------------+
| organization_123 |
| organization_456 |
| organizations |
| queue |
+------------------+
mysql> select * from organizations;
+-------+
| orgId |
+-------+
| 123 |
| 456 |
+-------+
mysql> select * from organization_123;
+------+
| fid |
+------+
| 123 |
+------+
mysql> select * from organization_456;
+------+
| fid |
+------+
| 456 |
+------+
... I wait a minute for the event to execute ...
mysql> select * from queue;
+-------+------+
| orgId | fid |
+-------+------+
| 123 | 123 |
| 123 | NULL |
| 456 | 456 |
| 456 | NULL |
+-------+------+
I don't know what your purpose is of inserting rows in the queue table in this fashion, but I'll trust you that it makes sense for your application. This answer is only meant to show the syntax for your looping routine, not the wisdom of designing your database as it is.
To be honest, I find MySQL stored routines so awkward to use, that I would recommend coding your events in some client language outside the database. It would be easier to develop and debug in practically any other language other than the MySQL stored routine language.