I am working on online trading project.
I insert one row on table t1 (innoDB engine) and there is one trigger on after insert event.
In trigger, i fetch data using select statement in same table like "SELECT * FROM t1 WHERE ID = NEW.ID".
It works perfectly 2-3 months. but now it gives Deadlock issue.
what is reason behind it ?
is it possible while multiple thread access same operation on same table at a time ?
do you want the id that you have inserted before ?
you can try something like this
INSERT INTO table1 (title,userid) VALUES ('test', 1);
SET #last_id_in_table1 = LAST_INSERT_ID();
Related
I am a complete newbie to MySql so please be gentle.
Is there an equivalent of the RETURNING clause in Oracle or the Inserted'/'Deleted tables in SQL Server in MySQL? What I want to do is the following:
Delete a set of rows from table A
Insert the deleted set of rows into table B.
Please help!
Thanks
Unfortunately, you can't do both insertion and deletion in one query, but you can do it all in one transaction if you are using a transactional store engine (like InnoDB). Moreover, RETURNING is supported by Oracle and PostgreSQL but not by MySQL and therefore you need to write separate delete and insert statements.
Using a transaction however, will guarantee that only the successfully copied data will be deleted from tableA. Consider the following:
begin transaction;
insert into tableB select * from tableA where 'your_condition_here';
delete from tableA where 'your_condition_here';
commit;
Why not insert the rows to be deleted from table A in table B and then delete the rows from table A? you can achieve that like this:
insert into tableB select * from tableA where condition;
and then
delete from tableA where condition.
I have a multi thread program (In this case in Qt) which every thread at a specific time, writes 500 records in a MySQL table (I call that as A_tbl) and also there is a trigger that inserts some values to other tables (I call them as B_tbl) and after that by some select queries in the trigger, I get the IDs of those inserted records in B_tbl.
But these select queries lead to this error:
Deadlock found when trying to get lock; try restarting transaction QMYSQL3: Unable to execute statement
This is my trigger:
CREATE DEFINER=`root`#`localhost` TRIGGER `IpAn`.`A_tbl_BEFORE_INSERT` BEFORE INSERT ON `A_tbl` FOR EACH ROW
BEGIN
INSERT IGNORE INTO source_names (source_name) VALUES (NEW.source_name);
INSERT IGNORE INTO locations (loc1,loc2) VALUES (loc1,loc2);
SET #source_names_id = (select id from source_names USE INDEX (PRIMARY) where source_name=NEW.source_name);
SET #locations_id = (select id from locations USE INDEX (PRIMARY) where loc1=NEW.loc1 and loc2=NEW.loc2);
...
END
If I change the threads to one, the error will not occur.
How can I solve this?
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.)
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
Looking for some help on mysql triggers and using multiple statements.
What I am trying to achieve is BEFORE an insert I want to copy records from active table ->history table and then delete them, THEN do the insert. The code works perfectly for the copying of the records from active->history. But the Trigger bonks as soon as I put the delete in ie. it will still move the records but will NOT delete the old rows.
Thoughts/ideas?
CREATE
DEFINER = 'root'#'%'
TRIGGER tradesfinder.On_Checkin_active_Insert
BEFORE INSERT
ON tradesfinder.user_checkin_active
FOR EACH ROW
BEGIN
INSERT INTO user_checkin_history
SELECT *
FROM user_checkin_active
WHERE user_id = new.user_id;
DELETE FROM user_checkin_active
WHERE user_id = new.user_id;
END
Thanks in advance.
C
I think you need an update if the id exists not delete and then insert. Try this:
INSERT INTO `user_checkin_active` (user_id, b, c)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE b =new.b, c = new.c;
I think the trigger syntax as shown above will not work as expected. Instead of triggering a select *, it would be better to work with the new row. So instead of "insert into user_checkin_history select *..." you would instead want to have the trigger to have soemthing to the effect of "insert into user_checkin_history (a,b,c,d) values (new.a,new.b,new.c,new.d)" which then inserts ONLY the contents of the new row.
Otherwise, you end up picking up ALL rowsx for the given user EACH time the user inserts something. That may not be what you intended.