Batch delete operation procedure not working - c#

I have a stored procedure which looks like following:
alter procedure [dbo].[zsp_deleteEndedItems]
(
#ItemIDList nvarchar(max)
)
as
delete from
SearchedUserItems
WHERE EXISTS (SELECT 1 FROM dbo.SplitStringProduction(#ItemIDList,',') S1 WHERE ItemID=S1.val)
The parameter IDList is passed like following:
124125125,125125125...etc etc
And the split string function look like following:
ALTER FUNCTION [dbo].[SplitStringProduction]
(
#string nvarchar(max),
#delimiter nvarchar(5)
) RETURNS #t TABLE
(
val nvarchar(500)
)
AS
BEGIN
declare #xml xml
set #xml = N'<root><r>' + replace(#string,#delimiter,'</r><r>') + '</r></root>'
insert into #t(val)
select
r.value('.','varchar(500)') as item
from #xml.nodes('//root/r') as records(r)
RETURN
END
This is supposed to delete all items from table "SearcheduserItems" under the IDs:
124125125 and 125125125
But for some reason after I do a select to check it out:
select * from SearchedUserItems
where itemid in('124125125','125125125')
The records are still there...
What am I doing wrong here? Can someone help me out?

As mentioned in the comments, a different option would be to use a table type parameter. This makes a couple of assumptions (some commented), however, should get you on the right path:
CREATE TYPE dbo.IDList AS TABLE (ItemID int NOT NULL); --Assumed int datatype;
GO
ALTER PROC dbo.zsp_deleteEndedItems #ItemIDList dbo.IDList READONLY AS
DELETE SUI
FROM dbo.SearchedUserItems SUI
JOIN #ItemIDList IDL ON SUI.ItemID = IDL.ItemID;
GO
--Example of usage
DECLARE #ItemList dbo.IDList;
INSERT INTO #ItemList
VALUES(123456),(123457),(123458);
EXEC dbo.zsp_deleteEndedItems #ItemList;
GO
In regards to the question of an inline table value function, one such example is the below, which I quickly wrote up, that provides a tally table of the next 1000 numbers:
CREATE FUNCTION dbo.NextThousand (#Start int)
RETURNS TABLE
AS RETURN
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)
)
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 + #Start AS I
FROM N N1 --10
CROSS JOIN N N2 --100
CROSS JOIN N N3; --1,000
GO
The important thing about an iTVF is that it has only one statement, and that is the RETURN statement. Declaring the table as a return type variable, inserting data into it, and returning that variable turns it into a multi-line TVF; which perform far slower.

Related

SQL While loop or c# linq foreach?

I have a credit card payment process stored procedure written in SQL. This is using SQL while to loop through half million payment records. This is horribly slow, because i have to loop through another set of data for each of these payment records and update bunch of tables accordingly. That means while loop inside while loop in sql.
I have to re-write this in c# to improve the performance. We are using LINQ & Entity framework. Can anybody please suggest me if this is going to help or not?
Thanks
Updating my question with modified stored procedure. I have replaced the references to my tables and removed some part of the code. But let me know if this is not clear.
CREATE PROCEDURE [dbo].[USP_ProcessPayments]
(
#UserKey int
)
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #TempUserPayments
(
-- with Columns declared
)
INSERT INTO #TempUserPayments
SELECT DISTINCT up.*, ROW_NUMBER() OVER(ORDER BY up.UserKey DESC, up.DateReceived) AS RN --generate row number
FROM UserPayment up
where up.UserKey = #UserKey
CREATE INDEX UP_1 on #TempUserPayments (RN);
DECLARE #LOOPCOUNTER INT, #ROWCOUNTER INT, #REQUESTEDAMOUNT MONEY, #UPDATEDREQUESTEDAMOUNT MONEY, #AMOUNT MONEY,
#AMOUNTNOTAPPLIED MONEY, #APPLIEDAMOUNT MONEY, #SYSTEMKEY INT, #LOOPCOUNTER_PR INT, #ROWCOUNTER_PR INT, #IS_UPDATE BIT
SELECT #ROWCOUNTER = COUNT(*) from #TempUserPayments;
SET #LOOPCOUNTER = 1
WHILE (#LOOPCOUNTER <= #ROWCOUNTER)
BEGIN
SELECT *,
ROW_NUMBER() OVER (ORDER BY mp.Month DESC, mp.PayPriority) AS RN_PR
INTO #TempPR
FROM Requests pr
INNER JOIN Premium mp ON mp.PremiumKey = pr.PremiumKey
--Joing couple of other tables here
ORDER BY mp.[Month] DESC, mp.PayPriority
CREATE INDEX PR_1 on #TempPR (RN_PR);
SELECT #SYSTEMKEY = SystemKey FROM #TempUserPayments WHERE RN = #LOOPCOUNTER;
SELECT #ROWCOUNTER_PR = COUNT(*) from #TempPR;
SET #LOOPCOUNTER_PR = 1
WHILE (#LOOPCOUNTER_PR <= #ROWCOUNTER_PR)
BEGIN
SET #IS_UPDATE = 0;
IF(#APPLIEDAMOUNT IS NULL OR (#REQUESTEDAMOUNT <> #APPLIEDAMOUNT AND #APPLIEDAMOUNT < #REQUESTEDAMOUNT))
BEGIN
IF(#SYSTEMKEY = 1 OR #SYSTEMKEY = 3)
BEGIN
--Check all the conditions here
SET #IS_UPDATE = 1;
END
IF(#IS_UPDATE = 1)
BEGIN
--Update bunch of requets tables ---
INSERT INTO userpaid
(
--Column names --
)
VALUES
(
--Values --
)
END
END
-- END
SET #LOOPCOUNTER_PR = #LOOPCOUNTER_PR + 1;
END
SET #LOOPCOUNTER = #LOOPCOUNTER + 1;
DROP TABLE #TempPR;
END
DROP TABLE #TempUserPayments;
END

SQL Server : using table function in stored procedure

I have function for combobox.
ALTER FUNCTION [FN.USERNew]
(
#USER_ID INT
)
RETURNS TABLE
AS
RETURN
(
Select [USER_NAME] , username_Id From USER
WHERE USER_ID=#USER_ID
)
GO
I try to use above function in my stored procedure like below.
However, I get an error
Cannot Find either column"dbo" or the user -defined function or aggregate "dbo.FN.USERNew", or name is ambigous."
ALTER PROCEDURE DBO.[MY_STORED_PROCEDURE]
(
#USER_ID INT,
#PRODUCT_ID INT
)
AS
BEGIN
SELECT
PRODUCT_ID,
PRODUCT_NAME
DBO.FN.USERNew(USER_ID) AS PROBLEMHERE
FROM PRODUCT_TABLE
WHERE PRODUCT_ID=#PRODUCT_ID
END
So why i can not use my function in my stored procedure ?
You have to continue to quote the name using [] or "" because . is used to separate name parts:
ALTER PROCEDURE DBO.[MY_STORED_PROCEDURE]
(
#USER_ID INT,
#PRODUCT_ID INT
)
AS
BEGIN
SELECT
PRODUCT_ID,
PRODUCT_NAME
DBO.[FN.USERNew](USER_ID) AS PROBLEMHERE
FROM PRODUCT_TABLE
WHERE PRODUCT_ID=#PRODUCT_ID
END
See Database Identifiers.
However, this is a table valued function - which would more normally be used in the FROM clause (possibly via APPLY) - I'm not sure that SQL Server will let you use it in the SELECT clause since it can return multiple columns and rows. I think you may want:
ALTER PROCEDURE DBO.[MY_STORED_PROCEDURE]
(
#USER_ID INT,
#PRODUCT_ID INT
)
AS
BEGIN
SELECT
PRODUCT_ID,
PRODUCT_NAME
ft.* AS PROBLEMHERE
FROM PRODUCT_TABLE pt
CROSS APPLY DBO.[FN.USERNew](pt.USER_ID) ft
WHERE pt.PRODUCT_ID=#PRODUCT_ID
END

Count on condition SQL Server

I have a table which contains some commercial Short text such as 'PVT, LTD' etc as in figure.
Secondly we have a new title received from another side every time such as 'Taha Zubair' and 'Taha PVT Ltd'.
Now i need to find just that if title contains a keyword, after scanning from database i need to return count only. If count is zero (0) means that title is simple as 'Taha Zubair' else return > 1 if title is some thing like that 'Taha PVT Ltd' or 'Taha Trust'
Image: http://social.msdn.microsoft.com/Forums/getfile/195838
Furthermore i need to do it some thing like that it would be adjust in stored Procedure, using whole query in programming application(Inline query) would affect the performance.
if you have any question ask it without any hesitation........
as function
Create Function F_GetNonIndividual(#SearchStr nVarchar(100)) Returns int
as -- use Select dbo.F_GetNonIndividual('Abc Solutions PVT LTD')
begin
Declare #Result int
Select #Result = Count(*)
from NonIndividualTitle
where #SearchStr Like ('%'+NonIndivTitle+'%')
Return #Result
end
as procedure
Create Procedure P_GetNonIndividual(#SearchStr nVarchar(100))
as -- use EXEC P_GetNonIndividual 'Abc Solutions PVT LTD'
begin
Select Count(*)
from NonIndividualTitle
where #SearchStr Like ('%'+NonIndivTitle+'%')
end
as procedure with out param
Create Procedure P_GetNonIndividualOut(#SearchStr nVarchar(100), #OutValue int out)
as
begin
Select #OutValue=Count(*)
from NonIndividualTitle
where #SearchStr Like ('%'+NonIndivTitle+'%')
end
with query example
Declare #OutValue int
exec P_GetNonIndividualOut 'Abc Solutions PVT LTD',#OutValue out
print #OutValue

Working with arrays in SQL Server

I have a int array of ID's (a lot of checkboxes I can choose from) which I want to get in one database call though a stored procedure.
Is there a way to work with an array of these ID's in SQL Server? I believe it should be something with splitting the array and then loop it (in sql). I just don't know how?
SQL Server 2008
There are many ways to do this:
Pass in a varchar parameter of the values separated by commas and parse that out (not very efficient, but for a small amount of data, not too bad except for the parsing bit)
Pass in XML and use the built in XML functions (SQL Server 2005+ has better support for this than earlier versions)
Use table value parameters (SQL Server 2008+)
Since you are using SQL Server 2008, use table value parameters.
EDIT: Example below
As #Oded mentioned, table valued parameters is the best option.
However, if for some reason you can't use these (perhaps your calling framework's limitations), you can use the following to perform the split to table:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[SplitToTable]
(
#List varchar(max), #Delim varchar(1)
)
RETURNS TABLE
AS
RETURN
(
WITH csvtbl(Start, [Stop]) AS (
SELECT Start = convert(bigint, 1), [Stop] =
charindex(#Delim COLLATE Slovenian_BIN2, #list + #Delim)
UNION ALL
SELECT Start = [Stop] + 1, [Stop] = charindex(#Delim
COLLATE Slovenian_BIN2, #list + #Delim, [Stop] + 1)
FROM csvtbl
WHERE ([Stop] > 0)
)
SELECT substring(#list, Start, CASE WHEN [Stop] > 0 THEN [Stop] -
Start ELSE 0 END) AS Value
FROM csvtbl
WHERE ([Stop] > 0)
)
You need to be aware of the default recursion depth of 100. If this isn't enough, increase it by adding the following to your outer calling query:
OPTION (MAXRECURSION 1000) -- or 0 for unlimited
EXAMPLE
SELECT *
FROM MyTable as t
WHERE t.ID IN (
SELECT *
FROM dbo.SplitToTable('1,2,12,34,101', ',')
)
It can be used on joins, etc., too.
I think you need something like...
Declare #query as varchar(500)
Declare #valuesList as varchar(100)
set #valuesList = '1,2,3'
set #query = 'select * From tableName where id in ( ' + #valuesList + ')'
exec(#query)
TO REVERSE THE PROCESS
DECLARE #t TABLE
(
ID int
)
INSERT INTO #t
VALUES (1), (3), (5), (7), (9)
SELECT STUFF(
(
SELECT ',' + CAST(t.ID AS VARCHAR(10))
FROM #t t
FOR XML PATH('')
), 1, 1, '') AS CSV
Courtesy SQLAuthority.

SQL Server (2008) Pass ArrayList or String to SP for IN()

I was wondering how I can pass either an ArrayList, List<int> or StringBuilder comma delimited list to a stored procedure such that I find a list of IDs using IN():
#myList varchar(50)
SELECT *
FROM tbl
WHERE Id IN (#myList)
In C# I am currently building the list as a string which is comma delimeted; however when using nvarchar(50) for example, as the type for the param in the stored procedure - I get an error as it can't convert '1,2,3' to int which it expects between the IN().
Any ideas? Much appreciated.
Pete
You could use a User Defined function such as
CREATE function [dbo].[csl_to_table] ( #list nvarchar(MAX) )
RETURNS #list_table TABLE ([id] INT)
AS
BEGIN
DECLARE #index INT,
#start_index INT,
#id INT
SELECT #index = 1
SELECT #start_index = 1
WHILE #index <= DATALENGTH(#list)
BEGIN
IF SUBSTRING(#list,#index,1) = ','
BEGIN
SELECT #id = CAST(SUBSTRING(#list, #start_index, #index - #start_index ) AS INT)
INSERT #list_table ([id]) VALUES (#id)
SELECT #start_index = #index + 1
END
SELECT #index = #index + 1
END
SELECT #id = CAST(SUBSTRING(#list, #start_index, #index - #start_index ) AS INT)
INSERT #list_table ([id]) VALUES (#id)
RETURN
END
Which accepts an nvarchar comma separated list of ids and returns a table of those ids as ints. You can then join on the returned table in your stored procedure like so -
DECLARE #passed_in_ids TABLE (id INT)
INSERT INTO #passed_in_ids (id)
SELECT
id
FROM
[dbo].[csl_to_table] (#your_passed_in_csl)
SELECT *
FROM
myTable
INNER JOIN
#passed_in_ids ids
ON
myTable.id = ids.id
In SQL 2008 there are table-valued-parameters, that make a friendly alternative to parsing CSV; see here for an example.
Otherwise, another option is xml - the xml data type in SQL Server allows you to read this pretty easily (although it takes more transfer bytes).

Categories

Resources