I have a stored procedure that will delete from ausers table based on an ID I pass in. If I was to delete multiple users or a range of the IDs, is there a way i can do this?
The IDs are Ints.
You have to create one function which is used to split string and you can pass parameter with separated comma
Function
---------------
CREATE FUNCTION SplitString
(
#Input NVARCHAR(MAX),
#Character CHAR(1)
)
RETURNS #Output TABLE (
Item NVARCHAR(1000)
)
AS
BEGIN
DECLARE #StartIndex INT, #EndIndex INT
SET #StartIndex = 1
IF SUBSTRING(#Input, LEN(#Input) - 1, LEN(#Input)) <> #Character
BEGIN
SET #Input = #Input + #Character
END
WHILE CHARINDEX(#Character, #Input) > 0
BEGIN
SET #EndIndex = CHARINDEX(#Character, #Input)
INSERT INTO #Output(Item)
SELECT SUBSTRING(#Input, #StartIndex, #EndIndex - 1)
SET #Input = SUBSTRING(#Input, #EndIndex + 1, LEN(#Input))
END
RETURN
END
GO
Store Procedure
----------------------
DECLARE #CustomerID VARCHAR(50) = '1,2,3'
DELETE FROM Customer WHERE CustomerID in (SELECT Item
FROM dbo.SplitString(#CustomerID, ','))
Hope this help you :)
Related
I have a column Airports where it has values as 'DXB,KWI,COK'.
I need to compare these column value with a string like 'DXB,LHR' remove the column value which in comma separated string?
After checking with string I want to update the column value as 'KWI,COK'.?
Any solutions
Airports |id
_____________________
dxb,cok,kwi |1
cok,dxb |2
kwi,dxb |3
Airport column id 1 will to update as 'COK,DXB' remove dxb which is in compared comma separated value?
Try to use REPLACE function:
CREATE TABLE #Test(
Airports varchar(256),
id int
)
INSERT #Test(Airports,id)VALUES('dxb,cok,kwi',1)
INSERT #Test(Airports,id)VALUES('cok,dxb',2)
INSERT #Test(Airports,id)VALUES('kwi,dxb',3)
INSERT #Test(Airports,id)VALUES('kwi,dxb,zxc',4)
INSERT #Test(Airports,id)VALUES('dxb',5)
INSERT #Test(Airports,id)VALUES('aaa,bbb',6)
SELECT *,REPLACE(REPLACE(REPLACE(Airports,'dxb,',''),',dxb',''),'dxb','')
FROM #Test
UPDATE #Test
SET
Airports=REPLACE(REPLACE(REPLACE(Airports,'dxb,',''),',dxb',''),'dxb','')
WHERE Airports LIKE '%dxb%'
SELECT *
FROM #Test
DROP TABLE #Test
ALTER FUNCTION [dbo].[SplitString]
(
#Input NVARCHAR(MAX),
#Character CHAR(1)
)
RETURNS #Output TABLE (
Item NVARCHAR(1000)
)
AS
BEGIN
DECLARE #StartIndex INT, #EndIndex INT
SET #StartIndex = 1
IF SUBSTRING(#Input, LEN(#Input) - 1, LEN(#Input)) <> #Character
BEGIN
SET #Input = #Input + #Character
END
WHILE CHARINDEX(#Character, #Input) > 0
BEGIN
SET #EndIndex = CHARINDEX(#Character, #Input)
INSERT INTO #Output(Item)
SELECT SUBSTRING(#Input, #StartIndex, #EndIndex - 1)
SET #Input = SUBSTRING(#Input, #EndIndex + 1, LEN(#Input))
END
RETURN
END
ALTER FUNCTION [dbo].[DistinctSplitString]
(
#string1 nvarchar(max),
#string2 nvarchar(max),
#chars character(1)
)
RETURNS #Output TABLE (
Item NVARCHAR(1000)
)
AS
BEGIN
INSERT INTO #output
select SP1.Item from dbo.SplitString(#string1,#chars) as SP1
LEFT JOIN dbo.SplitString(#string2,#chars) as SP2
ON SP1.Item = SP2.Item
WHERE sp2.Item IS NULL
RETURN
END
By using this two function we can easily get values
I need to update a table by using Stored procedure.
In that Stored Procedure i am using a IN Clause for some specific rows,Here i use a string which is having a value exacltly like this ='AC101','AC102','AC103'
eg:
string Recipt = "'AC101','AC102','AC103'";
Also My stored procedured query is
#PaymentDate nvarchar(MAX),
#ReciptNo nvarchar(50)
AS
BEGIN
SET NOCOUNT ON;
update Monthly_Payment set Payment_Date = #PaymentDate where Recipt_No in (#ReciptNo );
END
It's executing the query but not update the records which is mentioned in string
Note:
If i use normal query it's updated successfully.
ex:
update Monthly_Payment set Payment_Date = #PaymentDate where Recipt_No in (#ReciptNo );
Please update on this.
DECLARE #MonthlyPayment TABLE
(
PaymentDate NVARCHAR(10) ,
ReceiptNo NVARCHAR(50)
);
INSERT INTO #MonthlyPayment
( PaymentDate, ReceiptNo )
VALUES ( '2018-01-13', 'AC102' ),
( '2018-01-11', 'AC101' ),
( '2018-02-10', 'AC103' );
DECLARE #PaymentDate NVARCHAR(MAX)= '2018-05-04' ,
#ReceiptNo NVARCHAR(50)= N'AC101,AC102,AC103';
UPDATE #MonthlyPayment
SET PaymentDate = #PaymentDate
WHERE ReceiptNo IN ( SELECT value
FROM STRING_SPLIT(#ReceiptNo, ',') );
/*The STRING_SPLIT function is available only under compatibility level 130. If your database compatibility level is lower than 130, SQL Server will not be able to find and execute */
SELECT PaymentDate ,
ReceiptNo
FROM #MonthlyPayment;
Try this answer this will definitely work for you
Step 1 : first create this function. just run the following code
CREATE FUNCTION [dbo].[StringSplitToTable]
(
#Input NVARCHAR(MAX) ,
#Character CHAR(1)
)
RETURNS #Output TABLE ( Item VARCHAR(500) )
AS
BEGIN
DECLARE #StartIndex INT ,
#EndIndex INT
SET #StartIndex = 1
IF SUBSTRING(#Input, LEN(#Input) - 1, LEN(#Input)) <> #Character
BEGIN
SET #Input = #Input + #Character
END
WHILE CHARINDEX(#Character, #Input) > 0
BEGIN
SET #EndIndex = CHARINDEX(#Character, #Input)
INSERT INTO #Output
( Item
)
SELECT SUBSTRING(#Input, #StartIndex, #EndIndex - 1)
SET #Input = SUBSTRING(#Input, #EndIndex + 1, LEN(#Input))
END
RETURN
END
Step 2:
This Update query will be like the following
NOTE: MAKE SURE DATA SHOULD BE IN THIS FORMAT #ReciptNo='AC101,AC102,AC103'
update Monthly_Payment set Payment_Date = #PaymentDate where Recipt_No in (select item from StringSplitToTable(#ReciptNo,',') );
I am working on SQL Server (2005,2008 & 2012)
I wanna extract first five numbers from varchar column via using UDF
Input:
rrr123ddd4567ddd19828www2
123hhhsss124ss18762s
qq12349wsss12376ss
Output:
19828
18762
12349
My Trail is as following:
DECLARE
#myString VARCHAR(1000),
#temp VARCHAR(100),
#position INT,
#ExecuteInsert nvarchar (500),
#FirstChar bit
SET #myString = 'rrr123ddd4567ddd19828www2'
SET #position = 1
SET #FirstChar = 1
WHILE #position <= LEN(#myString)
BEGIN
IF (ISNUMERIC(SUBSTRING(#myString,#position,1))) = 1
BEGIN
SET #temp = isnull(#temp,'') + SUBSTRING(#myString,#position,1)
SET #FirstChar = 1
END
ELSE /* The char is alphabetical */
BEGIN
if (#FirstChar= 1)
BEGIN
SET #temp = isnull(#temp,'') + ','
SET #FirstChar = 0
END
END
SET #position = #position + 1
END
IF (RIGHT(#temp,1) <> ',')
BEGIN
SET #temp = #temp + ','
END
SELECT #temp = REPLACE(','+ #temp + ',',',,','')
SELECT #temp = Replace (#temp,',','''),(''')
Select #temp = '(''' + #temp + ''')'
Create table #temp
(
col1 varchar(100)
)
SET #ExecuteInsert = 'insert into #temp values ' + #temp
Execute sp_executesql #ExecuteInsert
select top 1 col1 from #temp
where LEN(col1) = 5
drop table #temp
-- Output >> 19828
The previous query is working well with string input , but I wanna using this code within UDF to could using it with columns.
if I used the previous query within UDF, the following error is raising:
Cannot access temporary tables from within a function.
EDIT
if I used Table variable , I get the next error:
Only functions and some extended stored procedures can be executed
from within a function.
any help will be greatly appreciated.
CREATE FUNCTION udfTest
(
-- Add the parameters for the function here
)
RETURNS int
AS
BEGIN
-- Declare the return variable here
DECLARE
#Result int,
#myString VARCHAR(1000),
#temp VARCHAR(100),
#position INT,
#ExecuteInsert nvarchar (500),
#FirstChar bit
SET #myString = 'rrr123ddd4567ddd19828www2'
SET #position = 1
SET #FirstChar = 1
WHILE #position <= LEN(#myString)
BEGIN
IF (ISNUMERIC(SUBSTRING(#myString,#position,1))) = 1
BEGIN
SET #temp = isnull(#temp,'') + SUBSTRING(#myString,#position,1)
SET #FirstChar = 1
END
ELSE /* The char is alphabetical */
BEGIN
if (#FirstChar= 1)
BEGIN
SET #temp = isnull(#temp,'') + ','
SET #FirstChar = 0
END
END
SET #position = #position + 1
END
IF (RIGHT(#temp,1) <> ',')
BEGIN
SET #temp = #temp + ','
END
SELECT #temp = REPLACE(','+ #temp + ',',',,','')
SELECT #temp = Replace (#temp,',','''),(''')
Select #temp = '(''' + #temp + ''')'
Declare #tempTable TABLE
(
col1 varchar(100)
)
insert into #tempTable SELECT #temp
select top 1 #Result=col1 from #tempTable
where LEN(col1) = 5
return #Result
END
GO
Here you are my answer of my question , hope helps others.
The objective is creating UDF function for using it with columns, not only fixed values.
The approach is using SplitString instead of sp_executesql
for splitting a comma separated string and loop it's values in table.
Demo:-
Create table DummyTable
( col1 varchar (100))
go
Insert into DummyTable values ('rrr123ddd4567ddd19828www2')
Insert into DummyTable values ('123hhhsss124ss18762s')
Insert into DummyTable values ('qq12349wsss12376ss')
go
/*
SplitString via Mudassar Khan
http://www.aspsnippets.com/Articles/Split-and-convert-Comma-Separated-Delimited-String-to-Table-in-SQL-Server.aspx
*/
Create FUNCTION SplitString
(
#Input NVARCHAR(MAX),
#Character CHAR(1)
)
RETURNS #Output TABLE (
Item NVARCHAR(1000)
)
AS
BEGIN
DECLARE #StartIndex INT, #EndIndex INT
SET #StartIndex = 1
IF SUBSTRING(#Input, LEN(#Input) - 1, LEN(#Input)) <> #Character
BEGIN
SET #Input = #Input + #Character
END
WHILE CHARINDEX(#Character, #Input) > 0
BEGIN
SET #EndIndex = CHARINDEX(#Character, #Input)
INSERT INTO #Output(Item)
SELECT SUBSTRING(#Input, #StartIndex, #EndIndex - 1)
SET #Input = SUBSTRING(#Input, #EndIndex + 1, LEN(#Input))
END
RETURN
END
GO
-------------------------------------
-------------------------------------
-------------------------------------
/*
My Own Function
*/
Create FUNCTION udfGetFirstFiveNumbers
(
#myString VARCHAR(1000)
)
RETURNS varchar(100)
AS
BEGIN
DECLARE
#temp VARCHAR(100),
#result Varchar (100),
#position INT,
#ExecuteInsert nvarchar (500),
#FirstChar bit
SET #position = 1
SET #FirstChar = 1
WHILE #position <= LEN(#myString)
BEGIN
IF (ISNUMERIC(SUBSTRING(#myString,#position,1))) = 1
BEGIN
SET #temp = isnull(#temp,'') + SUBSTRING(#myString,#position,1)
SET #FirstChar = 1
END
ELSE /* The char is alphabetical */
BEGIN
if (#FirstChar= 1)
BEGIN
SET #temp = isnull(#temp,'') + ','
SET #FirstChar = 0
END
END
SET #position = #position + 1
END
IF (RIGHT(#temp,1) <> ',')
BEGIN
SET #temp = #temp + ','
END
SELECT #temp = REPLACE(','+ #temp + ',',',,','')
SELECT #result = Item
FROM dbo.SplitString(#temp, ',')
where len(Item) = 5
return #result
END
GO
-- Test
select col1, dbo.udfGetFirstFiveNumbers(col1) as result
from DummyTable
Result:-
I am trying to split a string however its of data type varchar so to throws an error saying it cannot be converted to a float. I have tried but cant find a solution. How can i can i do it.
(SELECT Value FROM dbo.SplitString('648-44-21001-13764 ', '-') WHERE Position = 3)
Create FUNCTION SplitString
(
#Input NVARCHAR(MAX),
#Character CHAR(1)
)
RETURNS #Output TABLE (
Value NVARCHAR(1000),
Position int
)
AS
BEGIN
DECLARE #StartIndex INT, #EndIndex INT,#Position int
SET #Position = 0
SET #StartIndex = 1
IF SUBSTRING(#Input, LEN(#Input) - 1, LEN(#Input)) <> #Character
BEGIN
SET #Input = #Input + #Character
END
WHILE CHARINDEX(#Character, #Input) > 0
BEGIN
SET #EndIndex = CHARINDEX(#Character, #Input)
INSERT INTO #Output(Value,Position)
SELECT SUBSTRING(#Input, #StartIndex, #EndIndex - 1),#Position
SET #Input = SUBSTRING(#Input, #EndIndex + 1, LEN(#Input))
set #Position=#Position+1;
END
RETURN
END
GO
Check your Function Value column return type, it seems VARCHAR so You have to explicit convert it to float:
ALTER FUNCTION [dbo].[SplitString]
(
#String NVARCHAR(4000),
#Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(#Delimiter,#String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(#Delimiter,#String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Position' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Value' = SUBSTRING(#String,stpos,COALESCE(NULLIF(endpos,0),LEN(#String)+1)-stpos)
FROM Split
)
SELECT CAST((SELECT Value FROM dbo.SplitString('648-44-21001-13764 ', '-') WHERE Position = 3) AS FLOAT)
CREATE FUNCTION [dbo].[func_1]
(
#ListNum AS nvarchar(MAX)
)
RETURNS #t TABLE
(
col_1 nvarchar(MAX)
)
AS
BEGIN
INSERT #t
SELECT col_1
FROM table_name
WHERE col_2 IN (#ListNum)
RETURN
END
When I pass only one value in paramater (for example : 1) the function correctly works but how can I pass multiple value (for example : 1,2,3,4,5). I get the following error :
Procedure execution failed
42000 - [SQL Server]Error converting data type nvarchar to bigint.
Is there a simple way to solve this?
Hi you can try like this,
CREATE FUNCTION Splitstring (#Input NVARCHAR(MAX),
#Character CHAR(1))
RETURNS #Output TABLE (
Item NVARCHAR(1000))
AS
BEGIN
DECLARE #StartIndex INT,
#EndIndex INT
SET #StartIndex = 1
IF Substring(#Input, Len(#Input) - 1, Len(#Input)) <> #Character
BEGIN
SET #Input = #Input + #Character
END
WHILE Charindex(#Character, #Input) > 0
BEGIN
SET #EndIndex = Charindex(#Character, #Input)
INSERT INTO #Output
(Item)
SELECT Substring(#Input, #StartIndex, #EndIndex - 1)
SET #Input = Substring(#Input, #EndIndex + 1, Len(#Input))
END
RETURN
END
GO
CREATE FUNCTION [dbo].[Func_1] (#ListNum AS NVARCHAR(MAX))
RETURNS #t TABLE (
col_1 NVARCHAR(MAX))
AS
BEGIN
INSERT #t
SELECT p.col1
FROM dbo.Splitstring(#ListNum, ',') s
JOIN Table_Name t
ON t.col2 = s.Item
RETURN
END
DECLARE #var VARCHAR(100)='1,2,3,4'
SELECT *
FROM dbo.Func_1(#var)
Introduce one more function called split string. It will return the comma separated list as a table. Join the comma separated table with your actual table. This will gives the result.
For versions 2008+ using table separated values can assist where the calling procedure can construct the table and you are able to create a table type. If you must pass comma (or other character separated values) in a single string then you will need to separate the comma delimited string into a result set of its own.
The XML method works well when your string doesn't contain any special XML characters such as angle brackets <> - how-to-split-a-comma-separated-value-to-columns
I think this will work for your adjusted function;
CREATE FUNCTION [dbo].[func_1]
(
#ListNum AS nvarchar(MAX)
)
RETURNS #t TABLE
(
col_1 nvarchar(MAX)
)
AS
BEGIN
DECLARE #S varchar(max),
#Split char(1),
#X xml
SELECT #S = #ListNum,
#Split = ','
SELECT #X = CONVERT(xml,' <root> <s>' + REPLACE(#S,#Split,'</s> <s>') + '</s> </root> ')
INSERT #t
SELECT col_1
FROM table_name
WHERE col_2 IN (SELECT [Value] = T.c.value('.','varchar(20)')
FROM #X.nodes('/root/s') T(c))
RETURN
END