How to shorten SQL script - sql

According to my code below, I was using cursor to get all information in WInstance table. However, my query may have a problem with performance due to cursor. Is there any way to use nested-select instead of cursor? Please share me your idea.
My business here is to get only 1 of the same ItemID, SequenceID, TaskStatus, ListID, WebID, SiteID.
Technically, there are lots of the same ItemID, SequenceID, TaskStatus, ListID, WebID, SiteID in the joining tables of WInstance and WProgress with AssignTask = 'Assign task'. Therefore, I used distinct and cursorto loop through to get only the top 1 with order by.
Here is my code:
CREATE PROCEDURE dbo.CustomTasksHistory
(
#Username NVARCHAR(255)
)
AS
DECLARE #TempTableStatus TABLE
(
ItemID INT ,
SequenceID INT ,
TaskStatus NVARCHAR(25) ,
ListID UNIQUEIDENTIFIER ,
WebID UNIQUEIDENTIFIER ,
SiteID UNIQUEIDENTIFIER
);
DECLARE #ItemID INT;
DECLARE #SequenceID INT;
DECLARE #ListID UNIQUEIDENTIFIER;
DECLARE #WebID UNIQUEIDENTIFIER;
DECLARE #SiteID UNIQUEIDENTIFIER;
DECLARE #AssignTask VARCHAR(25);
SET #AssignTask = 'Assign task';
-- Select final TaskStatus of each ItemID with its SequenceID --
DECLARE cursor_ItemID CURSOR FAST_FORWARD READ_ONLY FOR
SELECT DISTINCT
WI.ItemID ,
WP.SequenceID ,
WI.ListID ,
WI.WebID ,
WI.SiteID
FROM dbo.WInstance WI
INNER JOIN dbo.WProgress WP ON WI.InstanceID = WP.InstanceID
WHERE WP.CurrentActivityTitle = #AssignTask;
OPEN cursor_ItemID;
FETCH NEXT FROM cursor_ItemID INTO #ItemID, #SequenceID, #ListID, #WebID, #SiteID;
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO #TempTableStatus
( ItemID ,
SequenceID ,
TaskStatus ,
ListID ,
WebID ,
SiteID
)
SELECT TOP 1
WI.ItemID ,
WP.SequenceID ,
CASE WHEN WP.ActivityComplete = 0
THEN 'Not Started'
ELSE 'Completed'
END AS 'TaskStatus' ,
WI.ListID ,
WI.WebID ,
WI.SiteID
FROM dbo.WInstance WI
INNER JOIN dbo.WProgress WP ON WI.InstanceID = WP.InstanceID
WHERE WP.CurrentActivityTitle = #AssignTask
AND WI.ItemID = #ItemID
AND WP.SequenceID = #SequenceID
AND WI.ListID = #ListID
AND WI.WebID = #WebID
AND WI.SiteID = #SiteID
ORDER BY TimeStamp DESC;
FETCH NEXT FROM cursor_ItemID INTO #ItemID, #SequenceID, #ListID, #WebID, #SiteID;
END;
CLOSE cursor_ItemID;
DEALLOCATE cursor_ItemID;
SELECT *
FROM #TempTableStatus;

You don't need to use cursor. Replace it with below query
SELECT ItemID, SequenceID, TaskStatus, ListID, WebID, SiteID
FROM
(
SELECT RN = ROW_NUMBER() OVER (PARTITION BY WP.CurrentActivityTitle,
WI.ItemID, WP.SequenceID,
WI.ListID, WI.WebID, WI.SiteID
ORDER BY TimeStamp DESC),
WI.ItemID ,
WP.SequenceID ,
CASE WHEN WP.ActivityComplete = 0
THEN 'Not Started'
ELSE 'Completed'
END AS 'TaskStatus' ,
WI.ListID ,
WI.WebID ,
WI.SiteID
FROM dbo.WInstance WI
INNER JOIN dbo.WProgress WP ON WI.InstanceID = WP.InstanceID
WHERE WP.CurrentActivityTitle = #AssignTask
) D
WHERE RN = 1;

Related

Getting Status Count for an item with many statuses

Lets say I have the following table variable:
DECLARE #DevicesAndStatuses TABLE (Id BIGINT,[Status] INT);
DECLARE #myId BIGINT;
SET #myId = 1;
Inside above table I can have thousands of Ids(Id can be repeated) and statuses ranging between 1-50. What is the most efficient way of getting the count of all the statuses for a particular Id?
The traditional method which I have is as follows:
SELECT
(SELECT COUNT(*) FROM #DevicesAndStatuses WHERE Id = #myId AND [Status] = 1) AS Status1,
(SELECT COUNT(*) FROM #DevicesAndStatuses WHERE Id = #myId AND [Status] = 2) AS Status2,
(SELECT COUNT(*) FROM #DevicesAndStatuses WHERE Id = #myId AND [Status] = 3) AS Status3,
(SELECT COUNT(*) FROM #DevicesAndStatuses WHERE Id = #myId AND [Status] = 4) AS Status4,
...
(SELECT COUNT(*) FROM #DevicesAndStatuses WHERE Id = #myId AND [Status] = 50) AS Status50,
FROM #DevicesAndStatuses WHERE Id = #myId
Are there potentially any better solution for getting the count of all the statuses [1-50] for a particular id?
Final result should be a single row containing 50 columns showing the count() of every status as Status1,Status2,...,Status50.*
My first suggestion is to use a group by:
SELECT status, count(*)
FROM #DevicesAndStatuses
WHERE Id = #myId
GROUP BY status;
The simplest way to get the information you want, but in multiple rows.
If you want multiple columns, then use conditional aggregation:
SELECT SUM(CASE WHEN [Status] = 1 THEN 1 ELSE 0 END) AS Status1,
SUM(CASE WHEN [Status] = 2 THEN 1 ELSE 0 END) AS Status2,
SUM(CASE WHEN [Status] = 3 THEN 1 ELSE 0 END) AS Status3,
SUM(CASE WHEN [Status] = 4 THEN 1 ELSE 0 END) AS Status4,
. . .
FROM #DevicesAndStatuses
WHERE Id = #myId
Sure:
SELECT Status, COUNT(*)
FROM #DevicesAndStatuses
WHERE Id = #myId
GROUP BY Status
This returns all Status values for Id = #myId, and their count - in one simple statement
You'll need to use a Dynamic Pivot Query to achieve this:
I've done it using a generic example but poke me if you need a more specific version. You'll need to use a Temp Table instead of a Table Variable though.
The STUFF command is there to remove the , from the beginning of the strings.
CREATE TABLE #Items
(
Item INT IDENTITY(1,1),
[Status] INT
)
INSERT #Items
(Status)
VALUES
(1),(1),(1),(1),(1),(1),(1),(2),(2),(2),(2),(3),(3),(4),(4),(4),(4),(4),(4),(4),(4),(5);
DECLARE #StatusList NVARCHAR(MAX) = N'',
#SumSelector NVARCHAR(MAX) = N''
SELECT #StatusList = CONCAT(#StatusList, N',', QUOTENAME(s.Status)),
#SumSelector = CONCAT(#SumSelector, N',', N'SUM(', QUOTENAME(s.Status), N') AS Status_', s.Status)
FROM (SELECT DISTINCT [Status] FROM #Items) AS s
SELECT #StatusList = STUFF(#StatusList, 1, 1, N''),
#SumSelector = STUFF(#SumSelector, 1, 1, N'')
DECLARE #StatusPivotQuery NVARCHAR(MAX) = CONCAT(N'
SELECT ', #SumSelector, N'
FROM #Items AS s
PIVOT
(
COUNT(s.[Status])
FOR s.[Status] IN(', #StatusList, N')
) AS pvt ')
EXEC sys.sp_executesql #StatusPivotQuery
DROP TABLE #Items
Here you go
SELECT MAX(id) AS Id, status, COUNT(*)
FROM #DevicesAndStatuses
WHERE Id = #myId
GROUP BY status;
or
SELECT id AS Id, status, COUNT(*)
FROM #DevicesAndStatuses
WHERE Id = #myId
GROUP BY id,status;

SQl Server Performance

I have database with more than 30 tables and more than 270k records in one table (the most important table) and create view get data from this table and other tables,
When I run the code below on my machine it takes less than 4 sec to get data from the view.
select * from view
My problem is that,
When I run the same script of database on another machine and run the same query from the view it takes a very long time.
Code for view
SELECT
dbo.UserSite.UserId,
dbo.UserSite.Name,
dbo.Site.RootPageURL,
dbo.PDFDocument.DocumentId,
dbo.RunDocumentVerificationResult.Status,
dbo.UserSite.UserSiteId,
dbo.Systemcode.Value,
dbo.RunDocumentVerificationResult.PageNumber,
dbo.RunDocumentVerificationResult.TestNameID,
dbo.RunDocumentVerificationResult.VerificationResultID,
dbo.TaskRun.VerificationEndDate,
dbo.TaskRun.RunId,
dbo.RunDocument.IsTagged,
dbo.RunDocument.IsProtected,
dbo.RunDocument.IsCorrupted
FROM
dbo.UserSite
INNER JOIN dbo.Site ON dbo.UserSite.SiteId = dbo.Site.SiteId
INNER JOIN dbo.TaskUserSites ON dbo.UserSite.UserSiteId = dbo.TaskUserSites.UserSiteId
INNER JOIN dbo.Task ON dbo.TaskUserSites.TaskId = dbo.Task.TaskId
INNER JOIN dbo.TaskRun ON dbo.Task.TaskId = dbo.TaskRun.TaskId
INNER JOIN dbo.RunDocument ON dbo.TaskRun.RunId = dbo.RunDocument.RunId
INNER JOIN dbo.PDFDocument ON dbo.PDFDocument.DocumentId = dbo.RunDocument.DocumentId
INNER JOIN dbo.RunDocumentVerificationResult ON dbo.RunDocument.RunDocumentId = dbo.RunDocumentVerificationResult.RunDocumentID
INNER JOIN dbo.Systemcode ON dbo.RunDocumentVerificationResult.Status = dbo.Systemcode.ID
EstimatedTime
Procdure Code is
ALTER proc [dbo].[status]
as
begin
begin transaction
declare #usersiteid bigint
declare #runid bigint
declare #TestedFiles int
declare #TaggedFiles int
declare #UnTaggedFiles int
declare #PassedFiles int
declare #FaildFiles int
declare #Name varchar(500)
declare #VerificationEndDate datetime
declare #RootPageURL varchar (1024)
declare #status table ( Name varchar(1000) , Urlrootpage varchar(2000) ,Testedfile int , TaggedFiles int , Untaggedfile int ,passedfiles int , faildfiles int,VerificationEndDate datetime,rootpageurl varchar(1024) )
declare #domain table (name varchar(1000) , urlrootpage varchar (2000) )
if (1=2)
begin
select 'n' Name ,'r' Urlrootpage ,1 Testedfile ,1 TaggedFiles ,0 Untaggedfile ,0 passedfiles ,0 faildfiles,GETDATE() VerificationEndDate ,'r' rootpageurl where 1=2
end
create table #status ( Name varchar(1000) , Urlrootpage varchar(2000) ,Testedfile int , TaggedFiles int , Untaggedfile int ,passedfiles int , faildfiles int,VerificationEndDate datetime,rootpageurl varchar(1024) )
set #usersiteid = (select min (UserSiteId) from vw)
set #runid = (select max (runid) from vw where usersiteid = #usersiteid)
while #usersiteid is not null
begin
set #TestedFiles = (select (count ( distinct documentid )) from vw where UserSiteId=#usersiteid and runid=#runid )
set #TaggedFiles = (select (count ( distinct documentid )) from vw where istagged=1 and UserSiteId=#usersiteid and runid=#runid)
set #UnTaggedFiles =(select (count ( distinct documentid )) from vw where istagged=0 and UserSiteId=#usersiteid and runid=#runid)
set #PassedFiles =(select (count ( distinct documentid )) from vw where Status<>1 and DocumentId not in (select DocumentId from vw where status =1) and UserSiteId=#usersiteid and runid=#runid)
set #FaildFiles = ( select (count ( distinct documentid )) from vw where Status=1 and UserSiteId=#usersiteid and runid=#runid)
set #Name = (select distinct name from vw where UserSiteId=#usersiteid)
set #rootPageUrl = (select distinct RootPageURL from vw where UserSiteId=#usersiteid)
set #VerificationEndDate = (select max(distinct VerificationEndDate) from vw where UserSiteId=#usersiteid and RunId=#runid)
insert into #status ( Name, Urlrootpage , Testedfile , TaggedFiles , Untaggedfile ,passedfiles , faildfiles ,VerificationEndDate ) values
(#Name,#RootPageURL,#TestedFiles,#TaggedFiles ,#UnTaggedFiles,#PassedFiles,#FaildFiles,#VerificationEndDate)
set #usersiteid = (select min (UserSiteId) from vw where UserSiteId > #usersiteid)
set #runid = (select max (runid) from vw where usersiteid = #usersiteid)
end
insert into #domain select UserSite.Name , Site.RootPageURL from UserSite inner join Site on UserSite.SiteId=Site.SiteId where UserSiteId not in (select UserSiteId from vw)
insert into #status select name,urlrootpage,0,0,0,0,0,null,0 from #domain
select Name,Urlrootpage,Testedfile,TaggedFiles,Untaggedfile, passedfiles,faildfiles from #status
end
If (##Error <> 0) -- Check if any error
Begin
rollback transaction
End
else
commit transaction
return
I would do a little test to find out if it is actually, as suggested, the network bandwidth that causes your query to be slow, or, better said, to look like it's slow. Append a limit-statement to your query and run it, like LIMIT 10. So while the whole query will execute, only the 10 first rows will be sent, and if the network is your bottleneck, it should now be very fast. If it is still that slow, your machine's sql server probably has very little memory to use, so it can't fit the whole result in, and your local sql server is probably configured to use more memory, so it executes faster. In this case, giving your sql server more memory should fix the problem. This should be no problem at all, since, as already mentioned in the comments, your database is actually very small, so the currently used memory will be very small too.
If your network connection turns out to be the bottleneck, you need to decide if, and why, you need all the results to be sent at once. I can't really help you on that one, since I don't know what the application is supposed to do with the data. But probably you should either do some aggegration in the database, or only send a small part of the data over the network.

Replace Cursor Next number assignment Operation with Set based equivalent

Good day all,
I have the following cursor query and would like to replace it with a set based query to address performance issues.
DECLARE #EmpIDM CHAR(21);
DECLARE #EmpName CHAR(21);
DECLARE #EMPCatID INT;
DECLARE Assign_Emp SCROLL CURSOR
FOR
SELECT DISTINCT EMP
, EMPNAME
FROM HR_EMPLOYEES
SET NOCOUNT ON
OPEN Assign_Emp;
FETCH NEXT
FROM Assign_Emp
INTO #EmpIDM
, #EmpName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #EMPCatID = (
SELECT TOP 1 CategoryID
FROM Categories
)
UPDATE Categories
SET CategoryID = (CategoryID + 1) /*Increment Category ID for next Insert*/
INSERT INTO Table1 (
EmpNumber
, EmployeeName
, EmployeeCategoryID
)
VALUES (
#EmpIDM
, #EmpName
, #EMPCatID
)
FETCH NEXT
FROM Assign_Emp
INTO #EmpIDM
, #EmpName
END
CLOSE Assign_Emp;
CLOSE Assign_Emp;
SET NOCOUNT OFF
My challenge is adapting the following code segment into a set based operation
SET #EMPCatID = (
SELECT TOP 1 CategoryID
FROM Categories
)
UPDATE Categories
SET CategoryID = (CategoryID + 1) /*Increment Category ID for next Insert*/
I humbly appreciate any insight on how I can achieve this.
Many Thanks,
Re-write using temp. table with identity column:
declare #offset int
select #offset = isnull(max(CategoryID),0) from Categories
create table #data (
EmpNumber CHAR(21),
EmployeeName CHAR(21),
EmployeeCategoryID int identity
)
INSERT INTO #data (
EmpNumber
, EmployeeName)
SELECT DISTINCT EmpIDM
, EmpName
FROM HR_EMPLOYEES
insert into Table1 (
EmpNumber
, EmployeeName
, EmployeeCategoryID
) select
EmpNumber
, EmployeeName
, EmployeeCategoryID + #offset
from #data
update Categories
set CategoryID = (select max(EmployeeCategoryID) from #data) + #offset

Filtering a CTE in a Stored Procedure

I need to filter cte data by procedure parameters- in fact if #agentid is null gives me all data else filter data by #agentid . I tried many ways , I used case in cte and get erros , I used if in ( if #status after cte ) and I get errors to , I used if in cte and get errors
This procedure is for pagination and filter data and in works fine .
USE [HN_PRODUCTION]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[grid_data_pagination]
#status int = null
, #offset int = 0
, #limit int = 2
, #agentid int = null
, #start_date date = null
, #end_date date = null
AS
BEGIN
IF #status is null
BEGIN
with cte as
(
Select FilePath , ReceptionLocalTime , AgentID , FileDuration , PhoneNumber , Indice , Status , ROW_NUMBER() over ( order by ID ) as RowNumber
from dbo.V1_594
)
select FilePath as مسیر ,ReceptionLocalTime as زمان , FileDuration as مدت , PhoneNumber as تلفن , Indice as اندیس , Status as وضعیت
from cte
where cte.RowNumber > #limit * #offset and cte.RowNumber <= #limit * ( #offset + 1 )
END
ELSE
BEGIN
with cte as
(
Select FilePath , ReceptionLocalTime , FileDuration , PhoneNumber , Indice , Status , ROW_NUMBER() over ( order by ID ) as RowNumber
from dbo.V1_594
WHERE Status = #status
)
select FilePath as مسیر ,ReceptionLocalTime as زمان , FileDuration as مدت , PhoneNumber as تلفن , Indice as اندیس
from cte
where cte.RowNumber > #limit * #offset and cte.RowNumber <= #limit * ( #offset + 1 ) ;
END
END
I would be helpful to include the errors you get, but perhaps this will help.
If I understand the problem correctly, you want to filter out the values of the CTE?
You don't need the IF statement for status. You can do that all in the where clause
ALTER PROCEDURE [dbo].[grid_data_pagination]
#status int = null
, #offset int = 0
, #limit int = 2
, #agentid int = null
, #start_date date = null
, #end_date date = null
AS
BEGIN
with cte as
(
Select FilePath, ReceptionLocalTime, AgentID, FileDuration, PhoneNumber, Indice, Status, ROW_NUMBER() over ( order by ID ) as RowNumber
from dbo.V1_594
WHERE (#agentid IS NULL OR AgentId = #agentid)
AND (#status IS NULL OR Status = #status)
)
select FilePath as مسیر ,ReceptionLocalTime as زمان , FileDuration as مدت , PhoneNumber as تلفن , Indice as اندیس
from cte
where cte.RowNumber > #limit * #offset and cte.RowNumber <= #limit * ( #offset + 1 ) ;
END
Hope that helps

Optimizing T-SQL Insert -- temptable, CTEs, WHILE loops

I have a situation where I need to process and finally insert 1000s of records from a temptable into a database table. Before each insert, I need to ensure that conditions are met and right after each insert, I need to update a second table in my database. My problem is that currently, it takes approximately 25 minutes to run the query and I would like to drastically cut that time so my application can be more responsive. How can I go about doing this please?
DECLARE #rowcounter as INTEGER
CREATE TABLE #temporary_phonetable
(
rownumber int not null identity(1,1),
record_no BIGINT,
phone_name BIGINT,
phone_number Varchar(25) not null ,
responsemessage Varchar(200) not null ,
messagepriority Varchar(14) not null ,
phone_id BIGINT,
AD_show BIGINT,
power_show Varchar(400),
service_provider VARCHAR(30),
Phone_flag VARCHAR(30),
questionMessage BIGINT,
PRIMARY KEY (phone_id, phone_number, rownumber)
,UNIQUE (questionMessage, record_no, rownumber)
)
--GET PHONE DATA
--if phone numbers are sent in from the client, then we want to process those instead
IF ( ( ( #listofphones IS NULL OR LEN(#listofphones) <1) AND LEN(#peoplegroups) >0) )
BEGIN
--NO PHONENUMBER BUT THERE ARE GROUPS AVAILABLE
INSERT INTO #temporary_phonetable(phone_name, phone_number, messagepriority, phone_id, AD_show, power_show, responsemessage)
SELECT n.phone_name, n.phone_number,u.messagepriority, n.phone_id , u.AD_show, u.power_show , CASE #includegreetings WHEN 1 THEN LTRIM(RTRIM(phone_name)) + #responsemessages
ELSE #responsemessages END as text_message
FROM user u WITH(NOLOCK)
INNER JOIN Phonenumbers n WITH(NOLOCK) ON n.user_no = u.user_no
INNER JOIN PeopleGroupRelations g ON g.phone_id=n.phone_id
INNER JOIN ( Select items FROM Split(#peoplegroups, #listofphonesdelimiter)) gg ON g.group_no = gg.items
WHERE n.user_no=#userid
AND n.status=''active''
SET #rowcounter = ##ROWCOUNT
END
ELSE IF ( LEN(#listofphones) >1 AND LEN(#peoplegroups) >0)
BEGIN
--PHONENUMBER AND GROUPS
INSERT INTO #temporary_phonetable(phone_name, phone_number, messagepriority, phone_id, AD_show, power_show, responsemessage)
SELECT n.phone_name, n.phone_number,u.messagepriority, n.phone_id , u.AD_show, u.power_show , CASE #includegreetings WHEN 1 THEN LTRIM(RTRIM(phone_name)) + #responsemessages
ELSE #responsemessages END as text_message
FROM Split(#listofphones, ''|'') s
INNER JOIN PhoneNumbers n WITH(NOLOCK) ON n.phone_number = s.items
INNER JOIN User u WITH(NOLOCK) ON n.user_no =u.user_no
INNER JOIN PeoplegroupRelations g ON g.phone_id=n.phone_id
INNER JOIN ( Select items FROM Split(#peoplegroups, #listofphonesdelimiter)) gg ON g.group_no = gg.items
WHERE n.user_no=#userid
AND n.status=''active''
SET #rowcounter = ##ROWCOUNT
END
ELSE IF ( LEN(#listofphones) >1 AND LEN(#peoplegroups) >0)
BEGIN
--PHONENUMBER AND NO GROUPS
INSERT INTO #temporary_phonetable(phone_name, phone_number, messagepriority, phone_id, AD_show, power_show, responsemessage)
SELECT n.phone_name, n.phone_number,u.messagepriority, n.phone_id , u.AD_show, u.power_show , CASE #includegreetings WHEN 1 THEN LTRIM(RTRIM(phone_name)) + #responsemessages
ELSE #responsemessages END as text_message
FROM Split(#listofphones, ''|'') s
INNER JOIN PhoneNumbers n WITH(NOLOCK) ON n.phone_number = s.items
INNER JOIN User u WITH(NOLOCK) ON n.user_no =u.user_no
INNER JOIN PeopleGroupRelations g ON g.phone_id=n.phone_id
INNER JOIN ( Select items FROM Split(#peoplegroups, #listofphonesdelimiter)) gg ON g.group_no = gg.items
WHERE n.user_no=#userid
AND n.status=''active''
SET #rowcounter = ##ROWCOUNT
END
ELSE
BEGIN
-- NO PHONENUMBER NO GROUP --- IE. SEND TO ALL PHONE NUMBERS
INSERT INTO #temporary_phonetable(phone_name, phone_number, messagepriority, phone_id, AD_show, power_show,responsemessage)
SELECT n.phone_name, n.phone_number,u.messagepriority, n.phone_id , u.AD_show, u.power_show , CASE #includegreetings WHEN 1 THEN LTRIM(RTRIM(phone_name)) + #responsemessages
ELSE #responsemessages END as text_message
FROM User u
INNER JOIN PhoneNumbers n ON n.user_no = u.user_no
WHERE
n.status=''active''
AND n.user_no=#userid
SET #rowcounter = ##ROWCOUNT
END
IF( #rowcounter>0)
BEGIN
DECLARE #service_provider as Varchar(30)
DECLARE #PhoneType as Varchar(30)
IF (LOWER(RTRIM(LTRIM(#sendresponseswhen))) ='now')
BEGIN
SET #dateresponsessent = GETDATE()
END
DECLARE #rownumber int
DECLARE #power_show BIT
DECLARE #AD_show BIT
set #rownumber = 0
WHILE #rownumber < #rowcounter
BEGIN
set #rownumber = #rownumber + 1
-- THE VARIABLES
DECLARE #record_no as BIGINT
DECLARE #phone_name VARCHAR(30)
DECLARE #messagepriority as INTEGER
DECLARE #phone_number VARCHAR(30)
DECLARE #phone_id BIGINT
DECLARE #questionMessage BIGINT
SELECT
#phone_name = n.phone_name, #phone_number =n.phone_number, #messagepriority =n.messagepriority, #phone_id=n.phone_id ,
#AD_show=n.AD_show, #power_show=n.power_show
FROM
#temporary_phonetable n WITH(NOLOCK)
WHERE n.rownumber = #rownumber
SET #record_no = AddMessageToQueue(#phone_number, #responsemessages, #dateresponsessent, #savednames, #userid, un.messagepriority, #responsetype,
un.AD_show, un.power_show, #service_provider, #PhoneType)
If(#questionid > 0)
BEGIN
SET #questionMessage = AddQuestionMessage(#questionid,#phone_id, #record_no, DATEADD(d, 30, GETDATE()) )
END
UPDATE #temporary_phonetable SET record_no = #record_no, questionMessage=#questionMessage WHERE phone_number = #phone_number AND rownumber = #rownumber
END
IF( #power_show >0)
BEGIN
SET #responsemessages = #responsemessages + dbo.returnPoweredBy()
END
IF( #AD_show > 0)
BEGIN
SELECT #responsemessages = #responsemessages + CASE
WHEN (LEN(#responsemessages) + 14)< 160 THEN dbo.returnAD(#responsemessages)
ELSE '''' END
END
RETURN #rowcounter
END
I believe this is the place where the bulk of the issue resides.
WHILE #rownumber < #rowcounter
BEGIN
set #rownumber = #rownumber + 1
-- THE VARIABLES
DECLARE #record_no as BIGINT
DECLARE #phone_name VARCHAR(30)
DECLARE #messagepriority as INTEGER
DECLARE #phone_number VARCHAR(30)
DECLARE #phone_id BIGINT
DECLARE #questionMessage BIGINT
SELECT
#phone_name = n.phone_name, #phone_number =n.phone_number, #messagepriority =n.messagepriority, #phone_id=n.phone_id ,
#AD_show=n.AD_show, #power_show=n.power_show
FROM
#temporary_phonetable n WITH(NOLOCK)
WHERE n.rownumber = #rownumber
SET #record_no = AddMessageToQueue(#phone_number, #responsemessages, #dateresponsessent, #savednames, #userid, un.messagepriority, #responsetype,
un.AD_show, un.power_show, #service_provider, #PhoneType)
If(#questionid > 0)
BEGIN
SET #questionMessage = AddQuestionMessage(#questionid,#phone_id, #record_no, DATEADD(d, 30, GETDATE()) )
END
UPDATE #temporary_phonetable SET record_no = #record_no, questionMessage=#questionMessage WHERE phone_number = #phone_number AND rownumber = #rownumber
END
Add a unique constraint to rownumber in your temp table. Rewrite the WHILE as a CTE. Use APPLY to call the functions.
You also might want to consider using a table variable rather than a temporary table. You won't be writing to the tempdb and as table variables are created in memory they're faster.
This article has a nice comparison.