Friday, March 30, 2012
Help optimising a stored proc
the first list contains primary key numbers, and the second values to
update.
When the list gets over about 200 items, I am getting intermittent
Timout errors.
Currently just over 500,000 records in the table.
Is there a way to optimise the performace of the update? Or is theer an
easier way if the input can be provided in a single list
e.g 2245=1,2257=2,3367=2 instead of
2245,2257,3367 and 1,2,2
Thanks!
CREATE Procedure dbo.UpdateResults
@.RegistrationIDs Varchar(8000),
@.Results Varchar(4000)
AS
UPDATE tblRegistrations
SET Result
= (SELECT A.Value FROM dbo.Split(@.Results,',') A
JOIN dbo.Split(@.RegistrationIDs,',') B ON A.id = B.id
WHERE RegistrationID=B.Value )
WHERE EXISTS (SELECT *
FROM dbo.Split(@.Results,',') A
JOIN dbo.Split(@.RegistrationIDs,',') B ON A.id = B.id
WHERE RegistrationID=B.Value)
CREATE FUNCTION dbo.Split
(
@.List varchar(8000),
@.SplitOn nvarchar(5)
)
RETURNS @.RtnValue table
(
Id int identity(1,1),
Value nvarchar(150)
)
AS
BEGIN
While (Charindex(@.SplitOn,@.List)>0)
Begin
Insert Into @.RtnValue (value)
Select
Value =
ltrim(rtrim(Substring(@.List,1,Charindex(
@.SplitOn,@.List)-1)))
Set @.List =
Substring(@.List,Charindex(@.SplitOn,@.List
)+len(@.SplitOn),len(@.List))
End
Insert Into @.RtnValue (Value)
Select Value = ltrim(rtrim(@.List))
Return
ENDI would try using temporary tables instead of table variables. I have seen
some strange stuff happen when trying to join two table variables together,
or joining a table-valued function together with a real base table.
Move the logic of the dbo.split funtion inside the stored procedure, take
the input csv strings and write them into a temporary table, then process
from that temp table.
"hals_left" wrote:
> Hi I have the following procedure that accepts two CSV lists of values,
> the first list contains primary key numbers, and the second values to
> update.
> When the list gets over about 200 items, I am getting intermittent
> Timout errors.
> Currently just over 500,000 records in the table.
> Is there a way to optimise the performace of the update? Or is theer an
> easier way if the input can be provided in a single list
> e.g 2245=1,2257=2,3367=2 instead of
> 2245,2257,3367 and 1,2,2
> Thanks!
>
> CREATE Procedure dbo.UpdateResults
> @.RegistrationIDs Varchar(8000),
> @.Results Varchar(4000)
> AS
> UPDATE tblRegistrations
> SET Result
> = (SELECT A.Value FROM dbo.Split(@.Results,',') A
> JOIN dbo.Split(@.RegistrationIDs,',') B ON A.id = B.id
> WHERE RegistrationID=B.Value )
> WHERE EXISTS (SELECT *
> FROM dbo.Split(@.Results,',') A
> JOIN dbo.Split(@.RegistrationIDs,',') B ON A.id = B.id
> WHERE RegistrationID=B.Value)
>
> CREATE FUNCTION dbo.Split
> (
> @.List varchar(8000),
> @.SplitOn nvarchar(5)
> )
> RETURNS @.RtnValue table
> (
> Id int identity(1,1),
> Value nvarchar(150)
> )
> AS
> BEGIN
> While (Charindex(@.SplitOn,@.List)>0)
> Begin
> Insert Into @.RtnValue (value)
> Select
> Value =
> ltrim(rtrim(Substring(@.List,1,Charindex(
@.SplitOn,@.List)-1)))
> Set @.List =
> Substring(@.List,Charindex(@.SplitOn,@.List
)+len(@.SplitOn),len(@.List))
> End
> Insert Into @.RtnValue (Value)
> Select Value = ltrim(rtrim(@.List))
> Return
> END
>|||Hi There,
What Mark suggested is right but you may like to try this .
UPDATE T1
SET Result = A.Value
>From FROM dbo.Split(@.Results,',') A
JOIN dbo.Split(@.RegistrationIDs,',') B ON A.id = B.id
Join tblRegistrations T1 On T1.RegistrationID=B.Value
and remove the split function If possible .
With Warm regards
Jatinder Singh
Mark Williams wrote:
> I would try using temporary tables instead of table variables. I have seen
> some strange stuff happen when trying to join two table variables together
,
> or joining a table-valued function together with a real base table.
> Move the logic of the dbo.split funtion inside the stored procedure, take
> the input csv strings and write them into a temporary table, then process
> from that temp table.
> --
> "hals_left" wrote:
>|||Thanks Jatinder, that works nice on a small test and is much simpler
SQL.
I'l test in on the real database and see how it compares to the
original
I dont really see how can I remove the split function, unless I pass
the data 1 record at a time in a loop ...
Monday, February 27, 2012
Help me with SP OrderBy
'ELP B4 I jump out of LondonBridge
**********************************
SELECT * FROM #TempTable WHERE ID > 0 AND ID < 6 AND EmployerID = 54 AND Job_no = 40
ORDER BY NULL
****************************************
try :
SELECT @.MYSTATEMENT = ' SELECT * FROM #TempTableWHERE
ID > '+ convert(varchar(20),@.FirstRec) +'
AND
ID < '+convert(varchar(20),@.LastRec) +'
AND EmployerID = '+ convert(varchar(20),@.EmployerID)+'
AND Job_no = '+convert(varchar(20),@.Job_no)+'ORDER BY ' +
CASE WHEN @.WhichColumn= 'name' AND @.sortby= 'asc'
THEN 'name'
ELSE 'NULL'
END
+
CASE WHEN @.WhichColumn='name' AND @.sortby='DESC'
THEN ' desc'
ELSE ''
ENDEXEC (@.myStatement)
ORDER BY ' +
CASE WHEN @.WhichColumn= 'name' AND @.sortby= 'asc' THEN 'name ASC'
WHEN @.WhichColumn = 'name' AND @.sortby = 'desc' THEN 'name desc'
ELSE 'NULL'
END
also do a print @.myStatement before you execute the statement to see how its building up.
hth|||Hi this is the output, it is still showing null
SELECT * FROM #TempTable
WHERE
ID > 0
AND
ID < 6
AND EmployerID = 54
AND Job_no = 40
ORDER BY NULL
(5 row(s) affected)|||what value are you passing to the parameter @.WhichColumn ?|||I have done a print on @.whichColumn, it is giving me the right value which is 'NAME'
So the problem must be from the case statement, but I can't figure it out
Thanks|||
declare @.MYSTATEMENT varchar(500), @.WhichColumn varchar(100), @.sortby varchar(100)
set @.sortby = 'desc'
set @.WhichColumn = 'name'
SELECT @.MYSTATEMENT = ' SELECT * FROM #TempTable WHERE ID > 6 AND ID < 10 ORDER BY ' +CASE WHEN @.WhichColumn= 'name' AND @.sortby= 'asc' THEN 'name ASC'
WHEN @.WhichColumn = 'name' AND @.sortby = 'desc' THEN 'name desc'
ELSE 'NULL'
ENDprint @.mystatement
i just did this in my QA and it worked fine for me. so double check your code.
hth