This part of MySQL stored procedure works but is very slow. Is there any way to optimize it?
IF (p_regid >0 AND p_submittedqueId>0 AND p_saveresponse=True) then
if not exists(select * from responseok where regid=p_regid AND QID =p_submittedqueId and TestId=p_TestId) AND (p_COption!='' or p_responsetext!='') then
insert into responseok (regid,TestId,QID,Response,ResponseText,timestamp)
select p_regid,p_testId,p_submittedqueId,p_COption,p_responsetext,now(3);
elseif (p_responsetext ='' AND p_COption='') then
insert into responsehistory (regid,TestId,QID,timestamp)
select p_regid,p_testId,p_submittedqueId,now(3);
delete from responseok where regid =p_regid and QID =p_submittedQueId AND TestId=p_TestId;
else
insert into responsehistory (regid,TestId,QID,timestamp)
select p_regid,p_testId,p_submittedqueId,now(3);
delete from responseok where regid =p_regid and QID =p_submittedQueId AND TestId=p_TestId;
insert into responseok (regid,TestId,QID,Response,ResponseText,timestamp)
select p_regid,p_testId,p_submittedqueId,p_COption,p_responsetext,now(3);
end if;
end if;
If I change the code to following, will it return the same results?
IF (p_regid >0 AND p_submittedqueId>0 AND p_saveresponse=True AND p_COption!='' or p_responsetext!='') then
if not exists(select * from responseok where regid=p_regid AND QID =p_submittedqueId and TestId=p_TestId) then
insert into responseok (regid,TestId,QID,Response,ResponseText,timestamp)
select p_regid,p_testId,p_submittedqueId,p_COption,p_responsetext,now(3);
else
insert into responsehistory (regid,TestId,QID,timestamp)
select p_regid,p_testId,p_submittedqueId,now(3);
delete from responseok where regid =p_regid and QID =p_submittedQueId AND TestId=p_TestId;
end if;
else
insert into responsehistory (regid,TestId,QID,timestamp)
select p_regid,p_testId,p_submittedqueId,now(3);
delete from responseok where regid =p_regid and QID =p_submittedQueId AND TestId=p_TestId;
insert into responseok (regid,TestId,QID,Response,ResponseText,timestamp)
select p_regid,p_testId,p_submittedqueId,p_COption,p_responsetext,now(3);
end if;
Will it improve the performance?
Will it be faster if I change the logic "if not exists" to something like "select 1 into some_var"?
The "if not exists" line is likely the culprit, it has to check an entire table to ensure each record does not match your criteria. Ensure that each column in that where clause (regid, QID, and TestId) each have indexes on them. This should allow the DB engine to filter out records that don't match much faster. Or you could consider trying to refactor so that you are only searching on a single indexed field.
Related
SET #Count = '2';
SELECT CASE #Count
WHEN 1 THEN INSERT INTO customer (First_Name) VALUES (John)
WHEN 2 THEN INSERT INTO customer (First_Name) VALUES (Mary)
ELSE INSERT INTO customer (First_Name) VALUES (Ray)
END;
--this is a mysql case expression. Can I use it to execute other mysql statements like this? Actually want to execute a block of statements depending on the value of #count
You can move the logic within a single statement:
insert into customer(firstname)
select case #Count
when 1 then 'John'
when 2 then 'Mary'
else 'Ray'
end
Alternatively, you want a case statement rather than a case expression:
case #Count
when 1 then insert into customer(firstname) values('John');
when 2 then insert into customer(firstname) values('Mary');
else insert into customer(firstname) values('Ray');
end case;
while creating a procedure in MYSQL i am facing a problem as, condition runs 'IF' statement and runs 'ELSE' statements too. just because an insert statement inside 'IF'.
insert into Userverified (UserID, Mobile, PIN,uname,unameid)
select NextUserID(),Mobile,PIN,null,null from UserNotVerified where Mobile=p_Mobile;
always results--- "result 00" ---why?
if i remove this
insert into Userverified (UserID, Mobile, PIN,uname,unameid)
select NextUserID(),Mobile,PIN,null,null from UserNotVerified where Mobile=p_Mobile;
works fine.
im using PhpMyAdmin and new with MYsql.
code attached here as---
CREATE procedure test
(
p_Mobile varchar(13),
p_LastOTP varchar(6)
)
begin
if ((select count(*) from UserVerified where mobile=p_Mobile)=0)
then
insert into Userverified (UserID, Mobile, PIN,uname,unameid)
select NextUserID(),Mobile,PIN,null,null from UserNotVerified where Mobile=p_Mobile;
if((select count(*) from uwallet where mobile=p_Mobile)=0)
then
insert into UserWallet (WalletID,Mobile,JoinAmount,WinAmount,ReferAmount,TotalAmount,DateModified)
select nextwalletid(),p_Mobile,0,0,0,0,now();
end if;
select 1 as result;
else
select '00' as result;
end if;
end;
I have [ReconcileUserInformationComputed] trigger on Userinformation table
Userinformation table has below rows
[ID] ,[CompanyID] ,[Status] ,[FirstName] ,[LastName]
UserinformationComputed table has below rows
[id] ,[CompanyID] ,[law_id] ,[Status] ,[FirstName] ,[LastName]
Below is my trigger
USE [einvoice]
GO
/****** Object: Trigger [dbo].[ReconcileUserInformationComputed] Script Date: 08/27/2014 10:53:08 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[ReconcileUserInformationComputed] ON [dbo].[UserInformation] AFTER INSERT,DELETE,UPDATE
AS
IF ##ROWCOUNT = 0 -- exit trigger when zero records affected
BEGIN
RETURN
END
SET NOCOUNT ON;
IF EXISTS (SELECT * FROM INSERTED)
BEGIN
IF EXISTS (SELECT * FROM DELETED)
BEGIN
--UPDATE
UPDATE [dbo].[UserInformationComputed]
SET -- use new values from inserted
CompanyID = (SELECT CompanyID from inserted),
law_id = (SELECT ID FROM inserted),
Status = (SELECT Status FROM inserted),
FirstName = (SELECT FirstName FROM inserted),
LastName = (SELECT LastName FROM inserted),
WHERE -- use original values from deleted
law_id = (SELECT ID FROM deleted)
END
ELSE
BEGIN
--INSERT
INSERT INTO [dbo].[UserInformationComputed] (CompanyID,law_id,Status,FirstName,LastName)
SELECT CompanyID,id,Status,FirstName,LastName) FROM inserted
END
END
ELSE IF EXISTS(SELECT * FROM DELETED)
BEGIN
--DELETE
DELETE FROM [dbo].[UserInformationComputed]
WHERE law_id = (SELECT id FROM deleted)
END
when try to update multiple users on Userinformation am getting
below error
Msg 512, Level 16, State 1, Procedure ReconcileUserInformationComputed, Line 16
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
I made the changes as per the answer it worked for the above trigger but same changes didnt work for another trigger
ALTER TRIGGER [dbo].[ReconcileCrossRefComputed] ON [dbo].[CrossRef] AFTER INSERT, UPDATE, DELETE
AS
IF ##ROWCOUNT = 0 -- exit trigger when zero records affected
BEGIN
RETURN
END
SET NOCOUNT ON;
IF EXISTS (SELECT * FROM INSERTED)
BEGIN
IF EXISTS (SELECT * FROM DELETED)
BEGIN
--UPDATE
UPDATE [dbo].[CrossRefComputed]
SET -- use new values from inserted
SenderId = inserted.SenderId,
ReceiverId = inserted.ReceiverId,
ForeignRef = inserted.ForeignRef,
PolicyID = inserted.PolicyID,
From inserted
WHERE -- use original values from deleted
[CrossRefComputed].SenderId = inserted.SenderId
AND [CrossRefComputed].ReceiverId = inserted.ReceiverId
END
ELSE
BEGIN
--INSERT
INSERT INTO [dbo].[CrossRefComputed] (SenderId, ReceiverId, ForeignRef, PolicyID)
SELECT SenderId, ReceiverId, Effective, PolicyID FROM inserted
END
END
ELSE IF EXISTS(SELECT * FROM DELETED)
BEGIN
--DELETE
DELETE FROM [dbo].[CrossRefComputed]
WHERE SenderId in (SELECT SenderId FROM deleted)
AND ReceiverId in (SELECT ReceiverId FROM deleted)
END
COuld anyone please help me how to fix the procedure to handle updating multiple records?
Be aware that an UPDATE or a DELETE can affect more than one record and your trigger will have to deal with them at once, in this case your "inserted" or "deleted" table will have more than one record.
You will have to use a join in your DML. Something like this:
UPDATE [dbo].[UserInformationComputed]
SET
CompanyID = inserted.CompanyID,
law_id = inserted.ID,
Status = inserted.Status,
FirstName = inserted.FirstName,
LastName = inserted.LastName
from inserted
WHERE
UserInformationComputed.law_id = inserted.ID
I haven't perfectly understood your UPDATE logic, so you'll have to adapt my code.
In your DELETE command you may have just to change "=" to "in":
DELETE FROM [dbo].[UserInformationComputed]
WHERE law_id in (SELECT id FROM deleted)
Take a look at this:
http://msdn.microsoft.com/en-us/library/ms190752.aspx
How would I end an if statement upon being satisfied but then execute the else if otherwise in a stored procedure?
I have tried putting an end if after the if statement:
IF EXISTS (SELECT * FROM `db`.`tbl` WHERE email = "email#domain.com") END IF;
ELSE INSERT INTO `db`.`tbl` (email) VALUES ("email#domain.com"); END IF;
But this didn't work.
Why not use an ignore insert?
INSERT IGNORE INTO `db`.`tbl` SET `email`= 'email#domain.com';
You would have to create a unique index on email.
Check here for some reference.
If this is for inserting if the row does not already exists, you shoul use this:
INSERT INTO `table` (value1, value2)
SELECT 'stuff for value1', 'stuff for value2' FROM `table`
WHERE NOT EXISTS (
SELECT * FROM `table`
WHERE value1='stuff for value1' AND value2='stuff for value2'
);
I need a constraint for a mysql-table. The table has the fields 'id', 'ref', 'from' and 'to'. The constraint schould guarantee that there are no datasets with the same 'ref' and a time overlapping (fields 'from' and 'to').
In sql: The following statement should always return '0'.
select count(*)
from `TABLE` d1 inner join `TABLE` d2 on
d1.`ref` = d2.`ref` and d1.`id` <> d2.`id` and
d1.`to` >= d2.`from` and d1.`from`<=d2.`to`
Is there a way to handle this with constrains?
Now I have the following triggers. Thanks for your help!
DELIMITER $$
USE `devtestplandb`$$
CREATE
TRIGGER `db`.`trig1`
BEFORE INSERT ON `db`.`TABLE`
FOR EACH ROW
BEGIN
SET #CNT = (
select count(*)
from `TABLE` d
where d.`ref` = NEW.`ref` and
d.`to` >= NEW.`from` and
d.`from` <= NEW.`to`);
IF #CNT != 0 THEN
CALL error_001();
END IF;
END$$
CREATE
TRIGGER `db`.`trig2`
BEFORE UPDATE ON `db`.`TABLE`
FOR EACH ROW
BEGIN
SET #CNT = (
select count(*)
from `TABLE` d
where d.`ref` = NEW.`ref` and
d.`ID` <> NEW.`ID` and
d.`to` >= NEW.`from` and
d.`from` <= NEW.`to`);
IF #CNT != 0 THEN
CALL error_002();
END IF;
END$$
"Is there a way to handle this with constrains?"
Yes, SQL Standard 2011 supports this kind of scenarios in readable declarative manner:
unique constraint definition
<without overlap specification> ::=
<application time period name> WITHOUT OVERLAPS
In your example:
CREATE TABLE tab (
id INT AUTO_INCREMENT PRIMARY KEY,
ref VARCHAR(100),
from_date DATE,
end_date DATE,
PERIOD FOR ref_period(from_date, end_date),
UNIQUE (ref, ref_period WITHOUT OVERLAPS)
);
And sample inserts:
INSERT INTO tab(ref, from_date, end_date) VALUES ('a', '2020-01-01','2020-03-01');
-- OK
INSERT INTO tab(ref, from_date, end_date) VALUES ('a', '2020-03-01','2020-05-01');
-- OK
INSERT INTO tab(ref, from_date, end_date) VALUES ('a', '2020-04-01','2020-07-01')
-- Duplicate entry 'a-2020-07-01-2020-04-01' for key 'ref
SELECT * FROM tab;
db<>fiddle demo - Maria DB 10.5