Running this procedure causes MySQL (or phpMyAdmin) to freeze. I have to stop MySQL with from XAMPP command, which freezes and "is not responding" about 20 seconds before stopping. I believe this is caused by the delimiter command, which on it's own begins the problems. I have tried using a different delimiter ("//") to no effect.
DELIMITER $
CREATE TRIGGER coroner AFTER INSERT ON events
FOR EACH ROW BEGIN
UPDATE teams WHERE id = NEW.victim SET live = live-1;
UPDATE teams WHERE id = NEW.shooter SET score = score+points;
END
$
DELIMITER ;
As it turns out, phpMyAdmin has a field marked "delimiter:" below the SQL query box. Using it rather than the command solves the problem. Further research explains that "DELIMITER" is not a SQL command, but a command generally implemented by all SQL ui's.
the update command should:
update teams set live = live-1 where id = new.victim;
update teams where id = new.shooter set score = score+points;
the where after the set clause
Related
My question is linked to the one below:
Table is specified twice, both as a target for 'UPDATE' and as a separate source for data in mysql
In my case, the trigger below works fine on my local setup (LAMPP on Ubuntu):
-- trigger to increment balance on posting of a new bill
DELIMITER
//
CREATE TRIGGER trig_increment_balance_new_bill AFTER INSERT ON
tbl_bill FOR EACH ROW
BEGIN
DECLARE
vBillAmount DOUBLE ;
SELECT NEW
.amount
INTO vBillAmount ;
UPDATE
tbl_client T
SET
balance = balance + vBillAmount
WHERE
id =(
SELECT
id
FROM
tbl_client C
WHERE NEW
.metreNo = C.metreNo
LIMIT 1
) ;
END ; //
DELIMITER
;
However, the error below occurs on my collaborator's setup (XAMPP on Windows) when they recreate the same code and test it.
SQLSTATE[HY000]: General error: 1093 Table 'T' is specified twice,
both as a target for 'UPDATE' and as a separate source for data
I thought it was related to strict mode, but I found strict mode is activated; 'STRICT_ALL_TABLES' in my case. Why would errors occur on his setup but not on mine? I know the solution provided in the link above may cure this error but the question is why the error is occurring selectively?
There's no need for the subquery, just put the criteria directly in the WHERE clause. You also don't need the vBillAmount variable.
CREATE TRIGGER trig_increment_balance_new_bill AFTER INSERT ON tbl_bill
FOR EACH ROW
UPDATE tbl_client c
SET c.balance = c.balance + NEW.amount
WHERE c.metreNo = NEW.metreNo
LIMT 1;
I have been at this for hours now, and I have tried everything I could find on stackoverflow and the internet. Nothing has worked. I have tried entering the code directly in the SQL prompt on phpmyadmin, as well as tried to create the event in the events tab.
For some odd reason, when giving it a second command, I get a syntax error. Each command on its own is accepted just fine. Together though? Syntax error.
Here's the code.
CREATE EVENT update_stats
ON SCHEDULE EVERY 15 MINUTE
ON COMPLETION PRESERVE ENABLE
DO
BEGIN
UPDATE stats JOIN temp_stats ON stats.unique_key = temp_stats.unique_key
SET stats.clicks = stats.clicks + temp_stats.clicks;
TRUNCATE temp_stats;
END
This yields a syntax error. I found a similar question on stackoverflow (see below) but none of the solutions worked. Yes, I tried setting and using a different delimiter. I even updated phpmyadmin to 4.4.1. Nothing works, just says I have a syntax error. I'm at my wits end here. MySQL 5.6.17.
phpmyadmin|How to create an event do 2 actions
I think this answer is missing an explanation as Jean-Francois was the correct answer but I didn't get it to work until I worked out what the "Delimiter" is.
When sending commands to SQL they are separated with a "Delimiter" the default is ";"
When I was making my event, inside the "CREATE EVENT" statement contains SQL queries inside the "BEGIN" and "END". SO MYSQL, parsing the query, runs into a ';' inside the BEGIN statement and correctly ends the statement there, saying "error in syntax near '' at line X" (the line it found the semi-colon on).
So to get around this you have to change the default delimiter for parsing, then run the query so you can include SQL statements inside your CREATE EVENT query with it ignoring the semi-colon and set the default delimiter back to a semi-colon:
DELIMITER $$
CREATE EVENT `snap_extcrs`
ON SCHEDULE
EVERY 1 DAY STARTS '2020-04-17 23:59:59'
ON COMPLETION PRESERVE
ENABLE
COMMENT ''
DO
BEGIN
INSERT INTO table (field, field2)
SELECT 1, 2 FROM table2
WHERE
date = DATE(NOW());
INSERT INTO table3 (field, field2)
SELECT 1, 2 FROM table2
WHERE
date = DATE(NOW());
END$$
DELIMITER ;
You forgot to put the END delimiter
DELIMITER #
CREATE EVENT update_stats
ON SCHEDULE
EVERY 15 MINUTE
ON COMPLETION PRESERVE ENABLE
DO BEGIN
UPDATE stats JOIN temp_stats ON stats.unique_key = temp_stats.unique_key
SET stats.clicks = stats.clicks + temp_stats.clicks;
TRUNCATE temp_stats;
END#
DELIMITER ;
I love triggers for one reason - they just work. I hate triggers for one reason - when they don't work, forget about trying to debug. O the sweet frustration.
Basically, I want to see THE update, delete, insert, etc query that was ran. I want to see that query ... somewhere, in my terminal or a log, exactly how and when MySQL executes it, and possibly any corresponding output/errors. Thoughts/hacks?
I'm trying to debug an update query with a few joins and what not. My queries are much more complex but for brevity here's an example.
DELIMITER |
CREATE TRIGGER ireallyhateyourightnow AFTER UPDATE ON watch_this_table
FOR EACH ROW BEGIN
IF (OLD.my_value != NEW.my_value) THEN
update
my_table
set
my_column = NEW.my_value;
END IF;
END|
DELIMITER ;
Here is some additional context that may help influence a suggestion or answer. Again, I'm less interested in semantics/syntax and more interested in seeing MySQL run the query but by all means, I'm open to anything at this point.
Strace does not work/show query.
Non-replicated environment BUT if the bin logs show trigger statements I will certainly set this up.
Does "show full processlist" show trigger execution and/or statements executed within (I never see them after running show full processlist as fast as perl can run it but I might just be missing it)?
General query log does not show these queries (certainly not the error log).
I'm not using aliases (anymore).
No syntax errors when creating the trigger.
The IF statement works.
When I insert the NEW values into a "test/temp" table and manually run the update query it works (I've even went so far as to actually inserting the whole update query)
I can't show you the query but as I just mentioned, it works when I run manually if that helps.
I've removed all erroneous characters, tabs, carriage returns, newlines, etc.
The MySQL socket would only show local connection/data but not MySQL internal workings, I think.
MyISAM so INNODB logs aren't an option
lsof didn't seem to show anything else to be of use.
I'm using MySQL 5.0.77 on CentOS 5.5.
There's an alternate way of testing it by having a temporary debug table. In the example here, they create it in an own debug database.
Step 1: Create a table
DROP TABLE IF EXISTS debug;
CREATE TABLE debug (
proc_id varchar(100) default NULL,
debug_output text,
line_id int(11) NOT NULL auto_increment,
PRIMARY KEY (line_id)
)
Step 2: Create debug SPs to fill the debug table
DELIMITER $$
DROP PROCEDURE IF EXISTS `debug_insert` $$
CREATE PROCEDURE `debug_insert`(in p_proc_id varchar(100),in p_debug_info text)
begin
insert into debug (proc_id,debug_output)
values (p_proc_id,p_debug_info);
end $$
DROP PROCEDURE IF EXISTS `debug_on` $$
CREATE PROCEDURE `debug_on`(in p_proc_id varchar(100))
begin
call debug_insert(p_proc_id,concat('Debug Started :',now()));
end $$
DROP PROCEDURE IF EXISTS `debug_off` $$
CREATE PROCEDURE `debug_off`(in p_proc_id varchar(100))
begin
call debug_insert(p_proc_id,concat('Debug Ended :',now()));
select debug_output from debug where proc_id = p_proc_id order by line_id;
delete from debug where proc_id = p_proc_id;
end $$
Step 3: Invoke the debug SPs in your trigger
Like this,
CREATE PROCEDURE test_debug()
begin
declare l_proc_id varchar(100) default 'test_debug';
call debug_on(l_proc_id);
call debug_insert(l_proc_id,'Testing Debug');
call debug_off(l_proc_id);
end $$
As a result the debug table would be filled as follows,
+------------------------------------+
| debug_output |
+------------------------------------+
| Debug Started :2006-03-24 16:10:33 |
| Testing Debug |
| Debug Ended :2006-03-24 16:10:33 |
+------------------------------------+
You can debug triggers using dbForge Studio for MySQL. Try trial version.
There is a detailed description of the trigger debugging process in the documentation: Debugging \ Debugging Stored Routines \ How To: Start Trigger Debugging.
MYSQL PROCEDURE => incron => tail -f 'mysql_dynamic.log'
A Stored Procedure can be invoked inside a trigger but must return nothing
CREATE PROCEDURE `DYN_LOG` (IN s VARCHAR(500))
BEGIN
SELECT s into outfile '/var/spool/incron/mysql_dynamic_spool/foo_file';
DO SLEEP(.1); // create a gap beetween multiple shuts
END
Now anywhere in a trigger you can invoke
CREATE TRIGGER `trig_name` BEFORE UPDATE ON `tb_name`
FOR EACH ROW
BEGIN
CALL DYN_LOG(concat_ws('\t',NEW.col1,NEW.col2));
...
// rest of the code
END
for Linux machines apt-get install incron (debian incron tutorial)
Create the folder in which mysql will inject foo_file
mkdir -m 777 /var/spool/incron/mysql_dynamic_spool
incrontab -e
and add following incron job
/var/spool/incron/mysql_dynamic_spool IN_CREATE /path/foo_file_procesor $#/$#
Create executable script "/path/foo_file_procesor"
#!/bin/sh
# // $1 is the foo_file absolute addres
body="$(cat $1)" #// read file content
rm $1
log=/var/log/mysql_dynamic.log #// message collector
echo "`date "+%Y-%m-%d %H:%M:%S"`\t== dyn_log ==\t$body">>$log
exit 0
Now watch the collector file
tail -f /var/log/mysql_dynamic.log
OK something weird is going on and I can't figure it out. I'm creating some triggers, but I get strange errors when trying to create them on the live DB. A sample query is this:
delimiter |
CREATE TRIGGER debug_upd_before BEFORE UPDATE ON properties_availability
FOR EACH ROW BEGIN
INSERT INTO debug_upd_before SET timestamp = NOW(), avID = OLD.avID, avPropertyID = OLD.avPropertyID,
avAvailableFrom = OLD.avAvailableFrom, avAvailableTo = OLD.avAvailableTo, avPrice = OLD.avPrice,
avIsAvailable = OLD.avIsAvailable;
END|
...
which executes fine localy. I'm using phpmyadmin, cause I don't have any other access to the online DB. I know I don't have full permissions and think that it might have something to do with that, but the error I get is:
You have an error in your SQL syntax;
check the manual that corresponds to
your MySQL server version for the
right syntax to use near 'delimiter |
not "you don't have permissions to do that" or something like that. The same happens when I try to execute something simpler like:
delimiter |
select 1|
select 2
The error I get is the same and I can't set a delimiter and the default doesn't work for me cause I have to use after the queries inside the triggers. I tried other symbols as delimiters, but the result is the same. Any ideas as to what the problem is and how to avoid it? Some of the triggers execute more than one query, if that makes a difference...
Thanks!
Try this statement (without delimiters) -
CREATE TRIGGER debug_upd_before BEFORE UPDATE ON properties_availability
FOR EACH ROW
INSERT INTO debug_upd_before SET
timestamp = now(),
avID = OLD.avID,
avPropertyID = OLD.avPropertyID,
avAvailableFrom = OLD.avAvailableFrom,
avAvailableTo = OLD.avAvailableTo,
avPrice = OLD.avPrice,
avIsAvailable = OLD.avIsAvailable;
The problem is that | is a bitwise or.
So you're using a reserved symbol as a delimiter.
Use $$ instead.
I'm having a rather strange problem with MySQL. Trying to create a procedure to update some fields in the database (the code is below).
The problem is with the line that is currently commented. It seems that if no SELECT statements get executed during the procedure MySQL query browser will return an error code of "-1, error executing SQL query".
I tried the same thing in HeidiSQL and the error was "cannot return result set". So I suppose the question is do I always have to select something in the procedure, or is there some other thing I missed.
The query works fine when the comment is removed.
DELIMITER /
DROP PROCEDURE IF EXISTS updateFavourites /
CREATE PROCEDURE updateFavourites(quota INT)
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE artist_id,releases INT;
DECLARE c_artist Cursor FOR
SELECT Artist.id_number,COUNT(Artist.id_number) FROM Artist
JOIN CD ON CD.is_fronted_by = Artist.id_number
GROUP BY Artist.id_number;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000'
SET done=1;
IF quota > 0 THEN
OPEN c_artist;
REPEAT
FETCH c_artist INTO artist_id,releases;
IF NOT done THEN
IF releases >= quota THEN
UPDATE CD SET CD.rating='favourite' WHERE CD.is_fronted_by = artist_id;
END IF;
END IF;
UNTIL done END REPEAT;
CLOSE c_artist;
-- SELECT 'Great success';
ELSE
SELECT CONCAT('\'quota\' must be greater than 0.',' Got (',quota,')');
END IF;
END /
DELIMITER ;
Here's the sql to create the tables and some data:
DROP TABLE IF EXISTS CD;
DROP TABLE IF EXISTS Artist;
CREATE TABLE Artist (
id_number INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
);
CREATE TABLE CD (
catalog_no INTEGER UNSIGNED AUTO_INCREMENT PRIMARY KEY,
is_fronted_by INT UNSIGNED,
rating ENUM ('favourite','top draw','good','so-so','poor','rubbish'),
CONSTRAINT fk_CD_Artist FOREIGN KEY (is_fronted_by) REFERENCES Artist(id_number) ON UPDATE CASCADE
);
INSERT INTO Artist VALUES(11,'Artist 1');
INSERT INTO Artist VALUES(10,'Artist 2');
INSERT INTO CD VALUES (7,11, 'top draw');
INSERT INTO CD VALUES (650,11,'good');
INSERT INTO CD VALUES (651,11,'good');
INSERT INTO CD VALUES (11,10,'favourite');
Query Browser is not for running scripts, just single query.
I tried your code by moving cursor into each query (except DELIMITER) and pressing Ctrl+Enter.
It created that stored procedure without problem. (just refresh schema on the left).
If you wish creating procedure, use menu "Script"->"Create stored procedure/function".
But better forget about QueryBrowser it is not supported at all (and actunally not useful).
If you have decent hardware and plenty resources, try Workbench 5.2 otherwise use SQLyog
Googling around, there are several reports of the same error, but little information to solve the problem. There's even a bug logged at mysql.com but it appears to have been abandoned without being resolved.
There's another StackOverflow question on the same error, but it's also unresolved.
All it means is that there is no result set from the query. Looking at the source code, it appears that sometimes an error status of MYX_SQL_ERROR is set when the query has no result set. Perhaps this is not an appropriate consequence?
I notice that when I use the mysql command-line client, it yields no error for calling a proc that returns no result set.
update: I tried to revive that MySQL bug report, and provide a good test case for them. They changed the bug from "no feedback" to "verified" -- so at least they acknowledge it's a bug in Query Browser:
[11 Dec 9:18] Sveta Smirnova
Bill,
thank you for the feedback. Verified
as described.
Although most likely this only be
fixed when MySQL Query Browser
functionality is part of MySQL
workbench.
I guess the workaround is to ignore the -1 error, or to test your stored procedures in the command-line mysql client, where the error does not occur.
The comment supposes the issue will disappear as the Query Browser functionality becomes part of MySQL Workbench. This is supposed to happen in MySQL Workbench 5.2. I'll download this beta and give it a try.
MySQL Workbench 5.2 is in Beta, but I would assume MySQL engineering can't predict when the Beta will become GA. Those kinds of predictions are hard enough under standard conditions, but there's a lot of extra uncertainty of MySQL's fate due to the unresolved Oracle acquisition.
update: Okay, I have tried MySQL Workbench 5.2.10 beta. I executed a stored procedure like this:
CREATE PROCEDURE FooProc(doquery SMALLINT)
BEGIN
IF doquery THEN
SELECT * FROM Foo;
END IF;
END
When I CALL FooProc(0) the response is no result set, and the status is simply "OK".
When I CALL FooProc(1) the response is the result of SELECT * FROM Foo as expected.
However, there's another bug related to calling procedures. Procedures may have multiple result sets, so it's hard to know when to close the statement when you execute a CALL query. The consequence is that MySQL Workbench 5.2 doesn't close the statement, and if you try to do another query (either CALL or SELECT) it gives you an error:
Commands out of sync; you can't run this command now.
MySQL doesn't support multiple concurrent open queries. So the last one must be closed before you can start a new one. But it isn't closing the CALL query. This bug is also logged at the MySQL site.
The bug about commands out of sync has been resolved. They say it's fixed in MySQL Workbench 5.2.11.
Try putting BEGIN and END blocks around the multiple statements in the IF block as such:
IF quota > 0 THEN
BEGIN
OPEN c_artist;
REPEAT
FETCH c_artist INTO artist_id,releases;
IF NOT done THEN
IF releases >= quota THEN
UPDATE CD SET CD.rating='favourite' WHERE CD.is_fronted_by = artist_id;
END IF;
END IF;
UNTIL done END REPEAT;
CLOSE c_artist;
END;
ELSE
SELECT CONCAT('\'quota\' must be greater than 0.',' Got (',quota,')');
END IF;