Separate a TEXT block by new lines - sql

In T-SQL, I need to separate a TEXT value by new lines character and then loop on each line.
In other words, I need an explode() function, but for T-SQL, and I need to to loop on each line.
I tough about creating a new temporary table and storing lines of the string in this table as rows, and then loop on this with a cursor. I'm just not sure about how to separate a string.
Is there a quick way to do this in T-SQL ?

(I supposed your data would be larger than 4000 caracters.)
The split function:
CREATE FUNCTION dbo.Split
(
#RowData nvarchar(2000),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table
(
Id int identity(1,1),
Data nvarchar(2000)
)
AS
BEGIN
Declare #Cnt int
Set #Cnt = 1
While (Charindex(#SplitOn,#RowData)>0)
Begin
Insert Into #RtnValue (data)
Select
Data = ltrim(rtrim(Substring(#RowData,1,Charindex(#SplitOn,#RowData)-1)))
Set #RowData = Substring(#RowData,Charindex(#SplitOn,#RowData)+1,len(#RowData))
Set #Cnt = #Cnt + 1
End
Insert Into #RtnValue (data)
Select Data = ltrim(rtrim(#RowData))
Return
END
And the explode function:
CREATE FUNCTION dbo.*tableName*_Explode
(
#id int
)
RETURNS #RtnValue table
(
Id int,
Data NVARCHAR(2000)
)
AS
BEGIN
DECLARE #LINEBREAK AS varchar(2)
SET #LINEBREAK = CHAR(13) + CHAR(10)
DECLARE #short_text NVARCHAR(2000)
DECLARE #short_text_length INT
DECLARE #sub_length INT
SET #sub_length = 2000
DECLARE #sub_index INT
SET #sub_index = 1
BEGIN
SET #short_text = (select SUBSTRING(*tableData*,#sub_index,#sub_length) from *tableName* WHERE id = #id)
SET #short_text_length = DATALENGTH(#short_text)
WHILE (#short_text_length > 0)
BEGIN
Insert Into #RtnValue (id,data)
SELECT #id, #short_text
SET #sub_index = (#sub_index + #sub_length)
SET #short_text = (select SUBSTRING(*tableData*,#sub_index,#sub_length) from *tableName* WHERE id = #id)
SET #short_text_length = DATALENGTH(#short_text)
END
IF (SELECT COUNT(*) FROM #RtnValue) = 0
Insert Into #RtnValue (id,data)
SELECT #id, ''
END
RETURN
END

Related

SQL Query for searching for a specific part of a string in a column

I want to search for a specific part of a nvarchar text string in a column.
The text string is structured like this X#2016-06-17#7483631#2016-06-27#2#167890##920, it's split up by #. I want to find 6th text block, 167890 in this case.
Is there a simple way to do this?
Perhaps with a little XML
Example
Declare #YourTable table (SomeCol varchar(500))
Insert Into #YourTable values
('X#2016-06-17#7483631#2016-06-27#2#167890##920')
Select SomeCol
,Pos6 = cast('<x>' + replace(A.SomeCol,'#','</x><x>')+'</x>' as xml).value('/x[6]','varchar(50)')
From #YourTable A
Returns
SomeCol Pos6
X#2016-06-17#7483631#2016-06-27#2#167890##920 167890
Create a SPLIT function, returning each part with an index like below:
CREATE FUNCTION [dbo].[StringSplit_WithIndex] (#str_in VARCHAR(8000),#separator VARCHAR(4) ) RETURNS #strtable TABLE (strval VARCHAR(8000),rn INT IDENTITY(1,1)) AS
BEGIN
DECLARE
#Occurrences INT,
#Counter INT,
#tmpStr VARCHAR(8000)
SET #Counter = 0
IF SUBSTRING(#str_in,LEN(#str_in),1) <> #separator
SET #str_in = #str_in + #separator
SET #Occurrences = (DATALENGTH(REPLACE(#str_in,#separator,#separator+'#')) - DATALENGTH(#str_in))/ DATALENGTH(#separator)
SET #tmpStr = #str_in
WHILE #Counter <= #Occurrences
BEGIN
SET #Counter = #Counter + 1
INSERT INTO #strtable
VALUES ( SUBSTRING(#tmpStr,1,CHARINDEX(#separator,#tmpStr)-1))
SET #tmpStr = SUBSTRING(#tmpStr,CHARINDEX(#separator,#tmpStr)+1,8000)
IF DATALENGTH(#tmpStr) = 0
BREAK
END
RETURN
END
Then, all you need to use the "rn" field after splitting like:
DECLARE #s VARCHAR(255) = 'X#2016-06-17#7483631#2016-06-27#2#167890##920'
SELECT *
FROM [StringSplit_WithIndex](#s,'#')
WHERE rn=6

how to pass more values for a single parameter in storedprocedure in sql server

MY text:-
CREATE proc usp_delete
#tranid int
as
begin
delete from customer where tranid in(#tranid)
end
Note:- I want to delete records more than 1 records through this stored procedure like:- if I pass 1,2,3,4,5,6 that time all 6 records should be deleted
You can use table-valued parameter for that you need to declare that
CREATE TYPE EntityId AS TABLE
( Id INT )
GO
CREATE PROCEDURE usp_delete
#tranid EntityId READONLY
AS
BEGIN
DELETE c
FROM customer c
JOIN #tranid t ON t.Id=c.tranid
END
For Executing with TVP declare a varible of type and pass it to the stored procedure
DECLARE #entityId EntityId
INSERT INTO #entityId
VALUES(1),(2),(3),(4),(5)
EXEC usp_delete #entityId
In later version of SQL Server you can use STRING_SPLIT to convert a delimited list into individual values and then join to your table using CROSS APPLY.
CREATE PROC usp_delete #tranid VARCHAR(MAX) AS
BEGIN
DELETE c
FROM customer c
CROSS APPLY STRING_SPLIT(#tranid, ',')
WHERE c.tranid = value
END
GO
EXEC usp_delete '2,3,4'
In older version you can write your own table-valued function to convert a delimited string into a result set.
CREATE function [dbo].[delimited_string_to_table] (
#delimiter char(1)
, #string text
)
returns #table table (
seqnbr int not null
, string varchar(255) not null
)
as
begin
declare #pos int
declare #textpos int
declare #chunklen smallint
declare #tmpstr varchar(8000)
declare #leftover varchar(8000)
declare #tmpval varchar(8000)
declare #seq int = 1
set #textpos = 1
set #leftover = ''
while #textpos <= datalength(#string)
begin
set #chunklen = 8000 - datalength(#leftover) / 2
set #tmpstr = #leftover + substring(#string, #textpos, #chunklen)
set #textpos = #textpos + #chunklen
set #pos = charindex(#delimiter, #tmpstr)
while #pos > 0
begin
set #tmpval = ltrim(rtrim(left(#tmpstr, #pos - 1)))
insert #table (seqnbr, string) values(#seq, #tmpval)
set #tmpstr = substring(#tmpstr, #pos + 1, len(#tmpstr))
set #pos = charindex(#delimiter, #tmpstr)
set #seq = #seq + 1
end
set #leftover = #tmpstr
end
if len(rtrim(ltrim(#leftover))) != 0
insert #table(seqnbr, string) values (#seq, ltrim(rtrim(#leftover)))
return
end
GO
Which would change the example to look like this:
CREATE PROC usp_delete #tranid VARCHAR(MAX) AS
BEGIN
DELETE c
FROM customer c
JOIN dbo.delimited_string_to_table(',', #tranid)
ON c.tranid = string
END
GO

Convert Varchar To Time Range

I Have 3 varchar Time Range and it should be Converted to start & Finish time value,
here's the value :
SCH
- 9:00-12:00
- 13-15:00
- 15-17:30
so I tried by myself to split into start time and finish and convert to time value
here's my split Function :
CREATE FUNCTION dbo.Split
(
#RowData nvarchar(2000),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table
(
Id int identity(1,1),
Data nvarchar(100)
)
AS
BEGIN
Declare #Cnt int
Set #Cnt = 1
While (Charindex(#SplitOn,#RowData)>0)
Begin
Insert Into #RtnValue (data)
Select
Data = ltrim(rtrim(Substring(#RowData,1,Charindex(#SplitOn,#RowData)-1)))
Set #RowData = Substring(#RowData,Charindex(#SplitOn,#RowData)+1,len(#RowData))
Set #Cnt = #Cnt + 1
End
Insert Into #RtnValue (data)
Select Data = ltrim(rtrim(#RowData))
Return
END
and I get the start & Finish value by do this in my dev query , but when i tried to convert 15-17:30 , I Got an error Conversion, because the start value is only 15 :
declare #valueToParse varchar(20) = '15-17:30'
select #schtimestart = data from dbo.split(#valueToParse,'-') where id=1
select #schtimefinish = data from dbo.split(#valueToParse,'-') where id=2
SELECT CAST(#schtimestart AS time)
SELECT CAST(#schtimefinish AS time)
how to convert only one value as Time value, or is there any simple conversion?
I Already Fix my Split Function, so if the start time have no Minutes value so it's add automatically
here's my code
USE [Dispatch]
GO
/****** Object: UserDefinedFunction [dbo].[Split] Script Date: 25/10/2013 09:39:51 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter FUNCTION dbo.Split
(
#RowData nvarchar(2000),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table
(
Id int identity(1,1),
Data nvarchar(100)
)
AS
BEGIN
Declare #Cnt int
Set #Cnt = 1
declare #tmp as varchar(20)
While (Charindex(#SplitOn,#RowData)>0)
Begin
SET #tmp = ltrim(rtrim(Substring(#RowData,1,Charindex(#SplitOn,#RowData)-1)))
Insert Into #RtnValue (data)
Select Data = case when ISNUMERIC(SUBSTRING(#tmp,1,2)) = 1 AND ISNUMERIC(SUBSTRING(#tmp,4,2)) = 1 then #tmp else (#tmp + ':00') END
Set #RowData = Substring(#RowData,Charindex(#SplitOn,#RowData)+1,len(#RowData))
Set #Cnt = #Cnt + 1
End
Insert Into #RtnValue (data)
Select Data = ltrim(rtrim(#RowData))
Return
END

convert string into int SQL Server

This is the scenario:
My app will have the following:
A listbox (The checkbox property enabled) that will display a list of Something.
The user will select from the listbox (multiselect) by using the checkbox.
I will loop into All the checked items and store the ID's into an array. I will store the ID's into something like this separating the ID with a comma (1,2,3,4) and then I will use length -1 to delete the last comma.
How can I convert the string 1,2,3,4 into an integer type of data if my stored procedure is like this?
Select * from tblSomething Where ID in (1,2,3,4)
You can use the following SQL function.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[CommaSeparatedToString]
(
#psCSString VARCHAR(8000)
)
RETURNS #otTemp TABLE(sID VARCHAR(20))
AS
BEGIN
DECLARE #sTemp VARCHAR(50)
WHILE LEN(#psCSString) > 0
BEGIN
SET #sTemp = LEFT(#psCSString, ISNULL(NULLIF(CHARINDEX(',', #psCSString) - 1, -1),
LEN(#psCSString)))
SET #psCSString = SUBSTRING(#psCSString,ISNULL(NULLIF(CHARINDEX(',', #psCSString), 0),
LEN(#psCSString)) + 1, LEN(#psCSString))
INSERT INTO #otTemp VALUES (#sTemp)
END
RETURN
END
And call in your stored procedure like
Select * from tblSomething
Where ID in (SELECT * FROM CommaSeparatedToString('1,2,3,4'))
You can use the
SELECT CAST(MyVarcharCol AS INT) FROM Table
SELECT CONVERT(INT, MyVarcharCol) FROM Table
refer this link
http://msdn.microsoft.com/en-us/library/ms187928.aspx
You need to create dynamic query for this
e.g you are getting list of values in #values paramter so prepare and run the dynamic query like this
DECLARE #query NVARCHAR(500)
DECLARE #values VARCHAR(200)
SET #values='1,2'
SET #query =N'Select * from tblSomething Where ID in ( ' + #values + ')'
SELECT #query
EXEC #Query
Use this function to split the value:
CREATE FUNCTION [dbo].[udfSplitCSV]
(
#String varchar (max),
#Delimiter varchar (10) = ','
)
RETURNS #ValueTable TABLE ([Row] int IDENTITY(1,1), [Value] varchar(max), [Length] int, [Duplicate] int NULL)
BEGIN
DECLARE #NextString varchar(max)
DECLARE #Pos int
DECLARE #NextPos int
IF #String IS NULL RETURN
--Initialize
SET #NextString = ''
SET #String = #String + #Delimiter
--Get position of first Comma
SET #Pos = charindex(#Delimiter,#String)
SET #NextPos = 1
--Loop while there is still a comma in the String
WHILE (#Pos <> 0)
BEGIN
SET #NextString = RTrim(LTrim(SubString(#String,1,#Pos - 1)))
INSERT INTO #ValueTable ([Value], [Length]) VALUES (#NextString, Len(#NextString))
SET #String = SubString(#String,#Pos+1,Len(#String))
SET #NextPos = #Pos
SET #Pos = CharIndex(#Delimiter,#String)
END
UPDATE #ValueTable
SET [Duplicate] = X.Duplicate
FROM #ValueTable VT
INNER JOIN (Select [Row], [Value], Row_Number() OVER (Partition By [Value] ORDER BY [Value], [Row]) as Duplicate FROM #ValueTable) X
ON X.[Row] = VT.[Row]
RETURN
END
-- Select * from dbo.udfSplitCSV('a , c b,c, a', ',')
When you are storing a bunch of IDs into the array, store with single quote.
so it will be ('1','2','3').
Then you no need to covert IDs into integer.

stored proc - executing a query with NOT IN where clause

i have a stored procedure
Create PROCEDURE abc
#sRemovePreviouslySelectedWhereClause nvarchar(max)
AS
BEGIN
SELECT *
FROM table
WHERE nId NOT IN (#sRemovePreviouslySelectedWhereClause)
END;
The parameter #sRemovePreviouslySelectedWhereClause can have values like 0,1 . But this fails with error message:
Conversion failed when converting the nvarchar value ' 0,1 ' to data type int.
Is there any other way to achieve this other than dynamic queries?
First, create a split function which splits your delimited string into a table:
CREATE FUNCTION [dbo].[Split]
(
#String varchar(max)
,#Delimiter char
)
RETURNS #Results table
(
Ordinal int
,StringValue varchar(max)
)
as
begin
set #String = isnull(#String,'')
set #Delimiter = isnull(#Delimiter,'')
declare
#TempString varchar(max) = #String
,#Ordinal int = 0
,#CharIndex int = 0
set #CharIndex = charindex(#Delimiter, #TempString)
while #CharIndex != 0 begin
set #Ordinal += 1
insert #Results values
(
#Ordinal
,substring(#TempString, 0, #CharIndex)
)
set #TempString = substring(#TempString, #CharIndex + 1, len(#TempString) - #CharIndex)
set #CharIndex = charindex(#Delimiter, #TempString)
end
if #TempString != '' begin
set #Ordinal += 1
insert #Results values
(
#Ordinal
,#TempString
)
end
return
end
Then change your where clause as follows:
select
t.*
from [yourTable] t
where t.[ID] not in (select cast([StringValue] as int) from dbo.Split(#sRemovePreviouslySelectedWhereClause,','))
Create FUNCTION [dbo].[fn_Split] (
#List nvarchar(2000), #SplitOn nvarchar(5)
)
RETURNS #RtnValue table (
Value nvarchar(100) )
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
**********
Create PROCEDURE abc
#sRemovePreviouslySelectedWhereClause nvarchar(max)
AS
BEGIN
SELECT *
FROM Table
WHERE nId NOT IN (select * from dbo.fn_Split(#sRemovePreviouslySelectedWhereClause,','))
END;
You have to split the #sRemovePreviouslySelectedWhereClause parameter by ',' and place the resulting values in a temp table. Then your select would look like
select * from table where nId not in (select nId from #tempIds)
This approach you're trying doesn't work. But if you're on SQL Server 2008, you could make use of the new features called Table Valued Parameters.
Basically, you create a user-defined table type
CREATE TYPE dbo.nIdTable AS TABLE(nID INT)
and you can then pass in multiple values in that TVP from the outside (e.g. from ADO.NET or such):
CREATE PROCEDURE abc(#idValues dbo.nIdTable READONLY)
and use that table variable inside your stored proc:
SELECT *
FROM table
WHERE nId NOT IN (SELECT nID FROM #idValues)
You will need to use Dynamic sql for such kind of queries.
first construct the query and
SET #sql = 'select * from table
where nId not in (' + #sRemovePreviouslySelectedWhereClause+ ')'
then use EXEC(#sql) to run the query.