Is there a decent way to delay execution of mysql trigger?
WHILE #condition = 0
sleep for awhile
insert into some_table values(NEW.value1, NEW.value2);
Since MySQL 5.0.12, you can do this:
SELECT SLEEP(<seconds>);
The seconds parameter can be in a fraction of a second like .5.
DO SLEEP(<seconds>);
is better. There is no reason to just run SELECT statements inside triggers without needing the result set.
If you really want to do this you need to do it like here:
SET #nothing = (SELECT SLEEP(<seconds>));
But I recommend to use DO. And don't forget that a trigger is just a single statement per default. If you have more then 1 statement in your trigger you need to use BEGIN/END:
BEGIN
DO SLEEP(<seconds>);
UPDATE ...;
END
Related
So I have this trigger that I wrote for a MySQL environment, and which I now need to transfer to a SQL Server environment.
Being unfamiliar with Transact SQL, I have a little trouble translating from one to the other or creating an equivalent. Here is the simplified query:
CREATE TRIGGER <myTrigger> BEFORE INSERT ON <myTable>
IF NEW.<myColumnContainingBoolean> = TRUE THEN
SET NEW.<myColumnReferenceCode> = CONCAT(YEAR(NOW()),MONTH(NOW()),DAY(NOW()), 'indice');
ENDIF;
The goal is to add a reference number (today's date writted yyyymmdd + 'indice') according to the value of a boolean contained in the query, to summarize, if, at the time of the INSERT, the value of the boolean is on TRUE then we insert the code on this same line, otherwise we don't write a reference. Here is a maybe more explicit example :
Example
I have sincerely tried a lot of things, what seems to come closest to my request is this one (which, of course, does not work):
CREATE TRIGGER <myTrigger>
ON <myTable>
AFTER INSERT
AS
BEGIN
IF <myColumnContainingBoolean>
SET <myColumnReferenceCode> = CONCAT(YEAR(GETDATE()),MONTH(GETDATE()),DAY(GETDATE()), 'indice');
FROM inserted
END
GO
Ok, I guess we have to use a trigger (immense sigh).
Here's how you would do it in SQL Server:
CREATE TRIGGER <your schema>.<your table>_Insert ON <your schema>.<your table>
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO <your schema>.<your table> (<your other columns>,<myColumnReferenceCode>)
SELECT
<your other columns>
,CASE
WHEN <myColumnContainingBoolean> = 1 THEN FORMAT(GETDATE(),'yyyyMMdd') + 'indice'
ELSE <myColumnReferenceCode>
END
FROM
inserted
END
GO
If you're using an auto-incremented (IDENTITY) column, make sure to leave it off your insert list inside the trigger.
Other observations: You could probably just make <myColumnReferenceCode> a date and store GETDATE() and get the same functionality, but I don't know all of your circumstances.
I have the following function in mysql
CREATE FUNCTION `get_project_uuid`(project_kee varchar(400)) RETURNS varchar(50) CHARSET utf8
BEGIN
declare v_project_uuid varchar(50);
select project_uuid into v_project_uuid from projects where scope='PRJ' and kee=project_kee;
RETURN v_project_uuid;
END
When I run this function directly from the mysql command prompt, it runs in few milliseconds but when I use this function inside another select statements, executing that hosing select statement takes about 2-3 minutes.
select * from issues where project_uuid = get_project_uuid('Project1')
However when I take the select statement from the function and use it directly in the hosting select statement rather than the function call, it works in few milliseconds.
select * from issues where project_uuid = (
select project_uuid from projects
where scope='PRJ' and kee='Project1'
)
It seems quite unusual that using the function takes so much longer. Now I am forced not to use the function because of longer time. Did I miss anything?
When you call the get_project_uuid() function from the command line, it only called once thus it runs faster.
When you use this function inside a select statement (i.e., 2nd code section from your question), depending on your statement, this function might be called for each row of the issue table used in the outer select statement. Now if issue table has a lot of rows, it might take longer time to execute.
Finally, in case of the 3rd code block, it can be faster, because mysql would not run the inner select statement for every row of the issue table. This is done as part of optimization by using the same value from the inner select statement.
If you want to use the function and still want it faster you can declare the function as deterministic. A function that always generates the same output given the same input can be declared as deterministic. Now you have to decide whether this hold in your case or not. Mysql would not complain if you wrongly declare an nondeterministic function as deterministic. But it is you who would get wrong result by doing so.
Just wanted to ask if this Event Scheduler works, also if once ran, it will continue to run as long as mySQL is running as a service?
SET GLOBAL event_scheduler = ON;
CREATE EVENT deleteVistors
ON SCHEDULE EVERY 1 DAY STARTS'2013-08-13 04:00:00'
DO
DELETE FROM tblwhitelist WHERE description = 'Vistors';
Also would this need a delimiter? I'm still unsure to what it actually is!
Hope you can help!
http://dev.mysql.com/doc/refman/5.1/en/create-event.html
Not using ENDS means that the event continues executing indefinitely.
CREATE EVENT deleteVistors
ON SCHEDULE EVERY 1 DAY STARTS '2013-08-13 04:00:00'
-- !!! no *END*: will continue until you explicitly drop the event
DO
DELETE FROM tblwhitelist WHERE description = 'Vistors';
For the second question:
Also would this need a delimiter?
MySQL use the semi-colon as statement delimiter. For multi-line statements (BEGIN ... END, etc.) this could be confusing for your MySQL client as the ; might appears inside those multi-line statements.
Here, you have only one ; so you don't have to bother with that.
After Googling for awhile I didn't see an answer. Anyway I have a situation in a stored procedure where I do a set select like:
SET someVariable = (SELECT ...)
Anyway, due to some redundant records existing somewhere else in the system, this SELECT query used in the SET returns more than one row. I'm guessing this will cause breakage or badness? True, false?
Thanks.
True. When assigning to a variable, the query must return a single row, containing a single column. You can also do it with this syntax:
SELECT someColumn INTO myVariable ... LIMIT 1;
In a sql script that does sequential execution, is there a way one can introduce an IF THEN ELSE conditional to control the flow of query execution?
I happened to run into this http://www.bennadel.com/blog/1340-MySQL-Does-Not-Support-IF-ELSE-Statements-In-General-SQL-Work-Flow.htm
which says that the IF THEN ELSE will not work in a sql script.
Is there another way around?
Basically, I want to run a particular "select colName from table" command and check if colName corresponds to a particular value. If it does, proceed with the rest of the script. Else, halt execution.
Please advise.
I just wrap my SQL script in a procedure, where conditional code is allowed. If you'd rather not leave the statements lying around, you can drop the procedure when you're done. Here's an example:
delimiter //
create procedure insert_games()
begin
set #platform_id := (select id from platform where name = 'Nintendo DS');
-- Only insert rows if the platform was found
if #platform_id is not null then
insert into game(name, platform_id) values('New Super Mario Bros', #platform_id);
insert into game(name, platform_id) values('Mario Kart DS', #platform_id);
end if;
end;
//
delimiter ;
-- Execute the procedure
call insert_games();
-- Drop the procedure
drop procedure insert_games;
If you haven't used procedures, the "delimiter" keyword might need some explanation. The first line switches the delimiter to "//" so that we can include semi-colons in our procedure definition without MySQL attempting to interpret them yet. Once the procedure has been created, we switch the delimiter back to ";" so we can execute statements as usual.
After doing some research I think I may have found a way to work around this. I was looking for a way to verify if a script had already executed against a target database. This will be primarily for version control of my databases. I have a table created to keep track of the scripts that have been executed and wanted some flow inside my scripts to check that table first before execution. While I have not completely solved the problem yet I have created a simple script that basically does what I need, I just need to wrap the DDL into the selects based on the value of the variables.
step 1 - Setup a bit variable to hold the result
step 2 - do your select and set the variable if the result is found
step 3 - Do what you need to do on false result
step 4 - Do what you need to do on true result
Here is the example script
set #schemachangeid = 0;
select #schemachangeid := 1 from SchemaChangeLog where scriptname = '1_create_tables.sql';
select 'scriptalreadyran' from dual where #schemachangeid = 1;
select 'scriptnotran' from dual where #schemachangeid = 0;
I also recognize this is an old thread but maybe this will help someone out there trying to do this kind of thing outside of a stored procedure like me.