Stored Procedure to check the existence of email in tables - sql

I am new to SQL stored procedures. I need to write a SQL to check a email exists in multiple tables. If a email contains in First Table it returns true and should not execute the rest. Like wise if not I need to check the second table and if i found return true. Finally if i found in last Table I need to return true and else i need to return false.
I am stuck in achieving this. I tried like this. Gives me syntax errors. Please share me a solution for this.
USE Users_UserDetials;
GO
CREATE PROCEDURE Users.GetUserPermissions
#userEmail nvarchar(50),
#areaId nvarchar(10),
#villageCode nvarchar(10)
AS
SET NOCOUNT ON;
IF EXISTS (SELECT 1 FROM Users.GlobalUsers AS GU
WHERE GU.UserEmail = #userEmail)
ELSE
IF EXISTS (SELECT 1 FROM Users.AreaSpecificUsers AS AU
WHERE AU.UserEmail = #userEmail)
ELSE
IF EXISTS (SELECT 1 FROM Users.VillageSpecificUsers AS VU
WHERE VU.UserEmail = #userEmail)
ELSE
'0'
GO

USE Users_UserDetials;
GO
CREATE PROCEDURE Users.GetUserPermissions
#userEmail nvarchar(50),
#areaId nvarchar(10),
#villageCode nvarchar(10)
AS
SET NOCOUNT ON;
IF EXISTS (SELECT 1 FROM Users.GlobalUsers AS GU
WHERE GU.UserEmail = #userEmail)
BEGIN
SELECT 1
END
ELSE
IF EXISTS (SELECT 1 FROM Users.AreaSpecificUsers AS AU
WHERE AU.UserEmail = #userEmail)
BEGIN
SELECT 1
END
ELSE
IF EXISTS (SELECT 1 FROM Users.VillageSpecificUsers AS VU
WHERE VU.UserEmail = #userEmail)
BEGIN
SELECT 1
END
ELSE
BEGIN
SELECT 0
END
END

Related

I want to add multiple select queries in stored procedure by using flag - how will I do this?

ALTER PROCEDURE [dbo].[UserManagement]
#flag int
AS
BEGIN
IF #flag = 1
BEGIN
SELECT
Formatid, Formatdetail, dispformat
FROM
loy_Formatdetail with (nolock)
WHERE
isactive = '1'
AND memberstatus = 'Member'
ORDER BY
FormatDetail
END
END

SQL Table Valued Function in Select Statement

SQL is not my best thing but I have been trying to optimize this stored procedure. It had multiple scalar-valued functions that I tried to change to table-valued functions because I read in many places that it's a more efficient way of doing it. And now I have them made but not real sure how to implement or if I maybe just didn't create them correctly.
This is the function I'm calling.
Alter FUNCTION [IsNotSenateActivityTableValue]
(
#ActivityCode int,
#BillId int,
#TextToDisplay varchar(max)
)
returns #T table(result varchar(max))
as
begin
DECLARE #result varchar(max);
declare #countcodes int;
declare #ishousebill int;
select #ishousebill = count(billid)
from BillMaster
where BillID = #BillID and Chamber = 'H'
If (#ishousebill = 0)
begin
SELECT #countcodes = count([ActivityCode])
FROM [HouseCoreData].[dbo].[ActivityCode]
where ActivityDescription not like '%(H)%' and ActivityType = 'S'
and [ActivityCode] = #ActivityCode
if (#countcodes = 0)
begin
set #result = 'test'
end
else
begin
set #result = 'test2'
end
end
else
begin
set #result = #TextToDisplay
end
RETURN
END
And this is how I was trying to call them like this. I would prefer just being able to put them in the top but really anything that works would be good.
SELECT distinct
ActionDates.result as ActionDate
,ActivityDescriptions.result as ActivityDescription
FROM BillWebReporting.vwBillDetailWithSubjectIndex as vw
left outer join [BillWebReporting].[HasHouseSummary] as HasSummary on vw.BillID = HasSummary.BillID
outer APPLY dbo.IsNotSenateActivityDateTableValue(ActivityCode,vw.BillID,[ActionDate]) ActionDates
OUTER APPLY dbo.IsNotSenateActivityTableValue(ActivityCode,vw.BillID,[ActivityDescription]) as ActivityDescriptions
Getting a count just to see if at least one row exists is very expensive. You should use EXISTS instead, which can potentially short circuit without materializing the entire count.
Here is a more efficient way using an inline table-valued function instead of a multi-statement table-valued function.
ALTER FUNCTION dbo.[IsNotSenateActivityTableValue] -- always use schema prefix!
(
#ActivityCode int,
#BillId int,
#TextToDisplay varchar(max)
)
RETURNS TABLE
AS
RETURN (SELECT result = CASE WHEN EXISTS
(SELECT 1 FROM dbo.BillMaster
WHERE BillID = #BillID AND Chamber = 'H'
) THEN #TextToDisplay ELSE CASE WHEN EXISTS
(SELECT 1 FROM [HouseCoreData].[dbo].[ActivityCode]
where ActivityDescription not like '%(H)%'
and ActivityType = 'S'
and [ActivityCode] = #ActivityCode
) THEN 'test2' ELSE 'test' END
END);
GO
Of course it could also just be a scalar UDF...
ALTER FUNCTION dbo.[IsNotSenateActivityScalar] -- always use schema prefix!
(
#ActivityCode int,
#BillId int,
#TextToDisplay varchar(max)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #result VARCHAR(MAX);
SELECT #result = CASE WHEN EXISTS
(SELECT 1 FROM dbo.BillMaster
WHERE BillID = #BillID AND Chamber = 'H'
) THEN #TextToDisplay ELSE CASE WHEN EXISTS
(SELECT 1 FROM [HouseCoreData].[dbo].[ActivityCode]
where ActivityDescription not like '%(H)%'
and ActivityType = 'S'
and [ActivityCode] = #ActivityCode
) THEN 'test2' ELSE 'test' END
END;
RETURN (#result);
END
GO
Table-valued functions return a table, in which, like any other table, rows have to be inserted.
Instead of doing set #result = ....., do:
INSERT INTO #T (result) VALUES ( ..... )
EDIT: As a side note, I don't really understand the reason for this function to be table-valued. You are essentially returning one value.
First of all UDFs generally are very non-performant. I am not sure about MySQL, but in Sql Server a UDF is recompiled every time (FOR EACH ROW OF OUTPUT) it is executed, except for what are called inline UDFs, which only have a single select statement, which is folded into the SQL of the outer query it is included in... and so is only compiled once.
MySQL does have inline table-valued functions, use it instead... in SQL Server, the syntax would be:
CREATE FUNCTION IsNotSenateActivityTableValue
(
#ActivityCode int,
#BillId int,
#TextToDisplay varchar(max)
)
RETURNS TABLE
AS
RETURN
(
Select case
When y.bilCnt + z.actCnt = 0 Then 'test'
when y.bilCnt = 0 then 'test2'
else #TextToDisplay end result
From (Select Count(billId) bilCnt
From BillMaster
Where BillID = #BillID
And Chamber = 'H') y
Full Join
(Select count([ActivityCode]) actCnt
From [HouseCoreData].[dbo].[ActivityCode]
Where ActivityDescription not like '%(H)%'
And ActivityType = 'S'
And [ActivityCode] = #ActivityCode) z
)
GO

Execute a Stored Procedure with parameters from a SELECT

I have an SP which needs to be executed as many times as i find rows in a temporary table (Just like insertion using a select statement)
My table #OutMessageQIDs has id column (with say 10 rows)
The SP HL7_InsertComponentLog requires 5 parameters as following
EXEC [HL7_InsertComponentLog] --#iPraID,#iComponentID,#vComponentType,'Send',id
SELECT #iPrcID,#iComponentID,#vComponentType,'Send',id
FROM #OutMessageQIDs
Can i do it without using Cursor or Loop kind of thing?
EDIT 1: a little more explanation - #OutMessageQIDs is a temporary table storing the ids of items Queued in a QueueTable (in an SP). and the SP HL7_InsertComponentLog logs the Queue-ed items. Depending upon #vComponentType, it logs different type of data.
EDIT 2: SP is as :
Create Procedure [dbo].[HL7_InsertComponentLog]
#IPracID [int],
#iComponentID [bigint],
#vComponentType varchar(50),
#vStatus varchar(200),
#iOutMessageQueueID [bigint]
AS
select* from hl7_outmessagelog
IF #vStatus != 'Success'
BEGIN
SELECT -1
END
ELSE IF #vComponentType = 'LabOrder' OR #vComponentType = 'ProcedureOrder' OR #vComponentType = 'RadiologyOrder'
BEGIN
SELECT -1
END
ELSE IF #vComponentType = 'LabResult' OR #vComponentType = 'ProcedureResult'
BEGIN
INSERT INTO OrderResult_Addendum (iOrderDetailID,IUserID,DateTime_Stamp,iType,VchComments,iOrderID,iPracID,vAction,bAcknowledge)
SELECT NULL,0,dTimeStamp,NULL,NULL,#iComponentID,#iPracID,#vStatus,0
FROM HL7_OutMessageQueue Q
WHERE Q.iOutQueueID = #iOutMessageQueueID and iPracID = #iPracID
END
ELSE IF #vComponentType = 'RadiologyResult'
BEGIN
INSERT INTO OrderResult_Addendum (iOrderDetailID,IUserID,DateTime_Stamp,iType,VchComments,iOrderID,iPracID,vAction,bAcknowledge)
SELECT iOrderDetailID,0,Q.dTimeStamp,NULL,NULL,#iComponentID,#iPracID,#vStatus ,0
FROM HL7_OutMessageQueue Q
INNER JOIN OrderResultDetails det ON Q.iComponentID = det.iOrderID
WHERE Q.iOutQueueID = #iOutMessageQueueID and Q.iPracID = #iPracID
END
ELSE IF #vComponentType = 'ClinicalNotes'
BEGIN
INSERT INTO Note_provider_encounter(iReportID,iUserID,iComponentID,dEncounterDate,vaction)
SELECT #iComponentID,0,0,dTimeStamp,#vStatus
FROM HL7_OutMessageLog Where iOutMessageLogID = #iOutMessageQueueID and iPracID = #iPracID
END
ELSE IF #vComponentType = 'PatientDemo'
BEGIN
DECLARE #IPatID int
DECLARE #IUserID int
SELECT #IPatID = iPatID,#IUserID = iUserID
FROM HL7_OutMessageQueue Q
WHERE Q.iOutQueueID = #iOutMessageQueueID and iPracID = #iPracID
EXEC [dbo].[InsertPatientLog] #IPracID,#IPatID,#vStatus,#IUserID
END
No you can't EXEC a stored procedure for each row in a table without using a loop of some kind.
What does your stored procedure do? It may be possible to extract the logic from that and perform it in a set based manner against the whole table.
e.g. Just use
INSERT INTO ComponentLog
SELECT #iPrcID,#iComponentID,#vComponentType,'Send',id
FROM #OutMessageQIDs
instead of calling the stored procedure for each row.

SQL: Query timeout expired

I have a simple query for update table (30 columns and about 150 000 rows).
For example:
UPDATE tblSomeTable set F3 = #F3 where F1 = #F1
This query will affected about 2500 rows.
The tblSomeTable has a trigger:
ALTER TRIGGER [dbo].[trg_tblSomeTable]
ON [dbo].[tblSomeTable]
AFTER INSERT,DELETE,UPDATE
AS
BEGIN
declare #operationType nvarchar(1)
declare #createDate datetime
declare #UpdatedColumnsMask varbinary(500) = COLUMNS_UPDATED()
-- detect operation type
if not exists(select top 1 * from inserted)
begin
-- delete
SET #operationType = 'D'
SELECT #createDate = dbo.uf_DateWithCompTimeZone(CompanyId) FROM deleted
end
else if not exists(select top 1 * from deleted)
begin
-- insert
SET #operationType = 'I'
SELECT #createDate = dbo..uf_DateWithCompTimeZone(CompanyId) FROM inserted
end
else
begin
-- update
SET #operationType = 'U'
SELECT #createDate = dbo..uf_DateWithCompTimeZone(CompanyId) FROM inserted
end
-- log data to tmp table
INSERT INTO tbl1
SELECT
#createDate,
#operationType,
#status,
#updatedColumnsMask,
d.F1,
i.F1,
d.F2,
i.F2,
d.F3,
i.F3,
d.F4,
i.F4,
d.F5,
i.F5,
...
FROM (Select 1 as temp) t
LEFT JOIN inserted i on 1=1
LEFT JOIN deleted d on 1=1
END
And if I execute the update query I have a timeout.
How can I optimize a logic to avoid timeout?
Thank you.
This query:
SELECT *
FROM (
SELECT 1 AS temp
) t
LEFT JOIN
INSERTED i
ON 1 = 1
LEFT JOIN
DELETED d
ON 1 = 1
will yield 2500 ^ 2 = 6250000 records from a cartesian product of INSERTED and DELETED (that is all possible combinations of all records in both tables), which will be inserted into tbl1.
Is that what you wanted to do?
Most probably, you want to join the tables on their PRIMARY KEY:
INSERT
INTO tbl1
SELECT #createDate,
#operationType,
#status,
#updatedColumnsMask,
d.F1,
i.F1,
d.F2,
i.F2,
d.F3,
i.F3,
d.F4,
i.F4,
d.F5,
i.F5,
...
FROM INSERTED i
FULL JOIN
DELETED d
ON i.id = d.id
This will treat update to the PK as deleting a record and inserting another, with a new PK.
Thanks Quassnoi, It's a good idea with "FULL JOIN". It is helped me.
Also I try to update table in portions (1000 items in one time) to make my code works faster because for some companyId I need to update more than 160 000 rows.
Instead of old code:
UPDATE tblSomeTable set someVal = #someVal where companyId = #companyId
I use below one:
declare #rc integer = 0
declare #parts integer = 0
declare #index integer = 0
declare #portionSize int = 1000
-- select Ids for update
declare #tempIds table (id int)
insert into #tempIds
select id from tblSomeTable where companyId = #companyId
-- calculate amount of iterations
set #rc=##rowcount
set #parts = #rc / #portionSize + 1
-- update table in portions
WHILE (#parts > #index)
begin
UPDATE TOP (#portionSize) t
SET someVal = #someVal
FROM tblSomeTable t
JOIN #tempIds t1 on t1.id = t.id
WHERE companyId = #companyId
delete top (#portionSize) from #tempIds
set #index += 1
end
What do you think about this? Does it make sense? If yes, how to choose correct portion size?
Or simple update also good solution? I just want to avoid locks in the future.
Thanks

SQL IF ELSE with output params stored proc help

I have a stored proc (SS2008) that takes a couple int ids and needs to look up if they exist in a table before adding a record. I have an int output param I would like to return and set its value based on what occrured. I have this so far, but it always returns 1. Can someone point me in the right direction?
BEGIN TRY
IF EXISTS
(
SELECT * FROM tbMap WHERE (cId= #CId)
)
SET #result = -1; -- This C User is already mapped
ELSE IF EXISTS
(
SELECT * FROM tbMap WHERE (dId = #DId)
)
SET #result = -2; -- This D User is already mapped
ELSE
INSERT INTO tbMap (
Login
, Email
, UserName
, CId
, DId)
SELECT
#UserName
, usr.EmailAddress
, usr.UserName
, #CId
, #DId
FROM tbUser usr WHERE usr.iUserID = #DId
SET #result = 1;
RETURN
END TRY
What am I missing? Thanks for any tips.
Cheers,
~ck in San Diego
Put the multiple statements for the last ELSE in a BEGIN/END block otherwise the last SET is always executed.
ELSE
BEGIN
INSERT INTO tbMap (
Login
, Email
, UserName
, CId
, DId)
SELECT
#UserName
, usr.EmailAddress
, usr.UserName
, #CId
, #DId
FROM tbUser usr WHERE usr.iUserID = #DId
SET #result = 1;
RETURN
END
END TRY
Have you tried using SELECT #result instead of SET? Also, I'm assuming the calling code has the #result parameter marked as Output?