How can I convert split function to inline table valued udf in SQL server?
up vote
1
down vote
favorite
Assuming I have this query ( pseudo) :
Select T.a,
T.b,
(select top 1 element from fn_split(c,',') where element=T.element)
From largeTable T
Where fn_split
runs for each row , I would like to use inline table valued udf so , that performance will be better.
NB : fn_split
just create a table via splitting via ,
:
But looking at inline table valued udf structure :
create FUNCTION [dbo].[fn_...]
(
...
)
RETURNS table
AS
RETURN SELECT ...(!!!)
It should return the select right away as the first statement !
But what if my UDF looks like :
CREATE FUNCTION [dbo].[FN_Split]
(
@InDelimitedString varchar(max),
@InDelimiter varchar(10)
)
RETURNS
@tblArray TABLE
(
ElementID smallint IDENTITY(1,1),
Element varchar(1000)
)
AS
BEGIN
DECLARE @StrPos smallint,
@StrStart smallint,
@DelimiterLength smallint
SET @DelimiterLength = LEN(@InDelimiter)
WHILE LEN(@InDelimitedString) > 0
BEGIN
--Removed for clarity . do some CHARINDEX manipulation ETc.
END
RETURN
END
Question :
I can't return select
right away , but still , I want to change the fn_split
to inline table valued udf.
How can I do it ?
sql-server sql-server-2008-r2 inline-table-function
add a comment |
up vote
1
down vote
favorite
Assuming I have this query ( pseudo) :
Select T.a,
T.b,
(select top 1 element from fn_split(c,',') where element=T.element)
From largeTable T
Where fn_split
runs for each row , I would like to use inline table valued udf so , that performance will be better.
NB : fn_split
just create a table via splitting via ,
:
But looking at inline table valued udf structure :
create FUNCTION [dbo].[fn_...]
(
...
)
RETURNS table
AS
RETURN SELECT ...(!!!)
It should return the select right away as the first statement !
But what if my UDF looks like :
CREATE FUNCTION [dbo].[FN_Split]
(
@InDelimitedString varchar(max),
@InDelimiter varchar(10)
)
RETURNS
@tblArray TABLE
(
ElementID smallint IDENTITY(1,1),
Element varchar(1000)
)
AS
BEGIN
DECLARE @StrPos smallint,
@StrStart smallint,
@DelimiterLength smallint
SET @DelimiterLength = LEN(@InDelimiter)
WHILE LEN(@InDelimitedString) > 0
BEGIN
--Removed for clarity . do some CHARINDEX manipulation ETc.
END
RETURN
END
Question :
I can't return select
right away , but still , I want to change the fn_split
to inline table valued udf.
How can I do it ?
sql-server sql-server-2008-r2 inline-table-function
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
Assuming I have this query ( pseudo) :
Select T.a,
T.b,
(select top 1 element from fn_split(c,',') where element=T.element)
From largeTable T
Where fn_split
runs for each row , I would like to use inline table valued udf so , that performance will be better.
NB : fn_split
just create a table via splitting via ,
:
But looking at inline table valued udf structure :
create FUNCTION [dbo].[fn_...]
(
...
)
RETURNS table
AS
RETURN SELECT ...(!!!)
It should return the select right away as the first statement !
But what if my UDF looks like :
CREATE FUNCTION [dbo].[FN_Split]
(
@InDelimitedString varchar(max),
@InDelimiter varchar(10)
)
RETURNS
@tblArray TABLE
(
ElementID smallint IDENTITY(1,1),
Element varchar(1000)
)
AS
BEGIN
DECLARE @StrPos smallint,
@StrStart smallint,
@DelimiterLength smallint
SET @DelimiterLength = LEN(@InDelimiter)
WHILE LEN(@InDelimitedString) > 0
BEGIN
--Removed for clarity . do some CHARINDEX manipulation ETc.
END
RETURN
END
Question :
I can't return select
right away , but still , I want to change the fn_split
to inline table valued udf.
How can I do it ?
sql-server sql-server-2008-r2 inline-table-function
Assuming I have this query ( pseudo) :
Select T.a,
T.b,
(select top 1 element from fn_split(c,',') where element=T.element)
From largeTable T
Where fn_split
runs for each row , I would like to use inline table valued udf so , that performance will be better.
NB : fn_split
just create a table via splitting via ,
:
But looking at inline table valued udf structure :
create FUNCTION [dbo].[fn_...]
(
...
)
RETURNS table
AS
RETURN SELECT ...(!!!)
It should return the select right away as the first statement !
But what if my UDF looks like :
CREATE FUNCTION [dbo].[FN_Split]
(
@InDelimitedString varchar(max),
@InDelimiter varchar(10)
)
RETURNS
@tblArray TABLE
(
ElementID smallint IDENTITY(1,1),
Element varchar(1000)
)
AS
BEGIN
DECLARE @StrPos smallint,
@StrStart smallint,
@DelimiterLength smallint
SET @DelimiterLength = LEN(@InDelimiter)
WHILE LEN(@InDelimitedString) > 0
BEGIN
--Removed for clarity . do some CHARINDEX manipulation ETc.
END
RETURN
END
Question :
I can't return select
right away , but still , I want to change the fn_split
to inline table valued udf.
How can I do it ?
sql-server sql-server-2008-r2 inline-table-function
sql-server sql-server-2008-r2 inline-table-function
asked Apr 30 '15 at 7:26
Royi Namir
73.9k98326584
73.9k98326584
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
4
down vote
accepted
The problem is with your split function. It is doing the split in an RBAR fashion. You should use a set-based splitter. Here is the DelimitedSplit8k by Jeff Moden, which is one of the fastest splitter there is:
CREATE FUNCTION [dbo].[DelimitedSplit8K](
@pString VARCHAR(8000), @pDelimiter CHAR(1)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH E1(N) AS (
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)
,E2(N) AS (SELECT 1 FROM E1 a, E1 b)
,E4(N) AS (SELECT 1 FROM E2 a, E2 b)
,cteTally(N) AS(
SELECT TOP (ISNULL(DATALENGTH(@pString), 0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
,cteStart(N1) AS(
SELECT 1 UNION ALL
SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString, t.N, 1) = @pDelimiter
),
cteLen(N1, L1) AS(
SELECT
s.N1,
ISNULL(NULLIF(CHARINDEX(@pDelimiter, @pString, s.N1),0) - s.N1, 8000)
FROM cteStart s
)
SELECT
ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
Item = SUBSTRING(@pString, l.N1, l.L1)
FROM cteLen l
Note: Be sure to look into the article for the updated function
For more split functions, read these articles by Sir Aaron Bertrand:
- Split strings the right way – or the next best way
- Splitting Strings : A Follow-Up
- Splitting Strings : Now with less T-SQL
- Comparing string splitting / concatenation methods
- Processing a list of integers : my approach
- Splitting a list of integers : another roundup
- More on splitting lists : custom delimiters, preventing duplicates, and maintaining order
- Removing Duplicates from Strings in SQL Server
is this inline table valued udf ??
– Royi Namir
Apr 30 '15 at 7:31
Yes, it is an ITVF.
– Felix Pamittan
Apr 30 '15 at 7:31
1
God I love those CTE's
– Royi Namir
Apr 30 '15 at 7:32
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
accepted
The problem is with your split function. It is doing the split in an RBAR fashion. You should use a set-based splitter. Here is the DelimitedSplit8k by Jeff Moden, which is one of the fastest splitter there is:
CREATE FUNCTION [dbo].[DelimitedSplit8K](
@pString VARCHAR(8000), @pDelimiter CHAR(1)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH E1(N) AS (
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)
,E2(N) AS (SELECT 1 FROM E1 a, E1 b)
,E4(N) AS (SELECT 1 FROM E2 a, E2 b)
,cteTally(N) AS(
SELECT TOP (ISNULL(DATALENGTH(@pString), 0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
,cteStart(N1) AS(
SELECT 1 UNION ALL
SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString, t.N, 1) = @pDelimiter
),
cteLen(N1, L1) AS(
SELECT
s.N1,
ISNULL(NULLIF(CHARINDEX(@pDelimiter, @pString, s.N1),0) - s.N1, 8000)
FROM cteStart s
)
SELECT
ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
Item = SUBSTRING(@pString, l.N1, l.L1)
FROM cteLen l
Note: Be sure to look into the article for the updated function
For more split functions, read these articles by Sir Aaron Bertrand:
- Split strings the right way – or the next best way
- Splitting Strings : A Follow-Up
- Splitting Strings : Now with less T-SQL
- Comparing string splitting / concatenation methods
- Processing a list of integers : my approach
- Splitting a list of integers : another roundup
- More on splitting lists : custom delimiters, preventing duplicates, and maintaining order
- Removing Duplicates from Strings in SQL Server
is this inline table valued udf ??
– Royi Namir
Apr 30 '15 at 7:31
Yes, it is an ITVF.
– Felix Pamittan
Apr 30 '15 at 7:31
1
God I love those CTE's
– Royi Namir
Apr 30 '15 at 7:32
add a comment |
up vote
4
down vote
accepted
The problem is with your split function. It is doing the split in an RBAR fashion. You should use a set-based splitter. Here is the DelimitedSplit8k by Jeff Moden, which is one of the fastest splitter there is:
CREATE FUNCTION [dbo].[DelimitedSplit8K](
@pString VARCHAR(8000), @pDelimiter CHAR(1)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH E1(N) AS (
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)
,E2(N) AS (SELECT 1 FROM E1 a, E1 b)
,E4(N) AS (SELECT 1 FROM E2 a, E2 b)
,cteTally(N) AS(
SELECT TOP (ISNULL(DATALENGTH(@pString), 0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
,cteStart(N1) AS(
SELECT 1 UNION ALL
SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString, t.N, 1) = @pDelimiter
),
cteLen(N1, L1) AS(
SELECT
s.N1,
ISNULL(NULLIF(CHARINDEX(@pDelimiter, @pString, s.N1),0) - s.N1, 8000)
FROM cteStart s
)
SELECT
ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
Item = SUBSTRING(@pString, l.N1, l.L1)
FROM cteLen l
Note: Be sure to look into the article for the updated function
For more split functions, read these articles by Sir Aaron Bertrand:
- Split strings the right way – or the next best way
- Splitting Strings : A Follow-Up
- Splitting Strings : Now with less T-SQL
- Comparing string splitting / concatenation methods
- Processing a list of integers : my approach
- Splitting a list of integers : another roundup
- More on splitting lists : custom delimiters, preventing duplicates, and maintaining order
- Removing Duplicates from Strings in SQL Server
is this inline table valued udf ??
– Royi Namir
Apr 30 '15 at 7:31
Yes, it is an ITVF.
– Felix Pamittan
Apr 30 '15 at 7:31
1
God I love those CTE's
– Royi Namir
Apr 30 '15 at 7:32
add a comment |
up vote
4
down vote
accepted
up vote
4
down vote
accepted
The problem is with your split function. It is doing the split in an RBAR fashion. You should use a set-based splitter. Here is the DelimitedSplit8k by Jeff Moden, which is one of the fastest splitter there is:
CREATE FUNCTION [dbo].[DelimitedSplit8K](
@pString VARCHAR(8000), @pDelimiter CHAR(1)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH E1(N) AS (
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)
,E2(N) AS (SELECT 1 FROM E1 a, E1 b)
,E4(N) AS (SELECT 1 FROM E2 a, E2 b)
,cteTally(N) AS(
SELECT TOP (ISNULL(DATALENGTH(@pString), 0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
,cteStart(N1) AS(
SELECT 1 UNION ALL
SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString, t.N, 1) = @pDelimiter
),
cteLen(N1, L1) AS(
SELECT
s.N1,
ISNULL(NULLIF(CHARINDEX(@pDelimiter, @pString, s.N1),0) - s.N1, 8000)
FROM cteStart s
)
SELECT
ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
Item = SUBSTRING(@pString, l.N1, l.L1)
FROM cteLen l
Note: Be sure to look into the article for the updated function
For more split functions, read these articles by Sir Aaron Bertrand:
- Split strings the right way – or the next best way
- Splitting Strings : A Follow-Up
- Splitting Strings : Now with less T-SQL
- Comparing string splitting / concatenation methods
- Processing a list of integers : my approach
- Splitting a list of integers : another roundup
- More on splitting lists : custom delimiters, preventing duplicates, and maintaining order
- Removing Duplicates from Strings in SQL Server
The problem is with your split function. It is doing the split in an RBAR fashion. You should use a set-based splitter. Here is the DelimitedSplit8k by Jeff Moden, which is one of the fastest splitter there is:
CREATE FUNCTION [dbo].[DelimitedSplit8K](
@pString VARCHAR(8000), @pDelimiter CHAR(1)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH E1(N) AS (
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)
,E2(N) AS (SELECT 1 FROM E1 a, E1 b)
,E4(N) AS (SELECT 1 FROM E2 a, E2 b)
,cteTally(N) AS(
SELECT TOP (ISNULL(DATALENGTH(@pString), 0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
,cteStart(N1) AS(
SELECT 1 UNION ALL
SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString, t.N, 1) = @pDelimiter
),
cteLen(N1, L1) AS(
SELECT
s.N1,
ISNULL(NULLIF(CHARINDEX(@pDelimiter, @pString, s.N1),0) - s.N1, 8000)
FROM cteStart s
)
SELECT
ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
Item = SUBSTRING(@pString, l.N1, l.L1)
FROM cteLen l
Note: Be sure to look into the article for the updated function
For more split functions, read these articles by Sir Aaron Bertrand:
- Split strings the right way – or the next best way
- Splitting Strings : A Follow-Up
- Splitting Strings : Now with less T-SQL
- Comparing string splitting / concatenation methods
- Processing a list of integers : my approach
- Splitting a list of integers : another roundup
- More on splitting lists : custom delimiters, preventing duplicates, and maintaining order
- Removing Duplicates from Strings in SQL Server
edited Nov 10 at 22:47
Aaron Bertrand
206k27360401
206k27360401
answered Apr 30 '15 at 7:30
Felix Pamittan
29.1k62444
29.1k62444
is this inline table valued udf ??
– Royi Namir
Apr 30 '15 at 7:31
Yes, it is an ITVF.
– Felix Pamittan
Apr 30 '15 at 7:31
1
God I love those CTE's
– Royi Namir
Apr 30 '15 at 7:32
add a comment |
is this inline table valued udf ??
– Royi Namir
Apr 30 '15 at 7:31
Yes, it is an ITVF.
– Felix Pamittan
Apr 30 '15 at 7:31
1
God I love those CTE's
– Royi Namir
Apr 30 '15 at 7:32
is this inline table valued udf ??
– Royi Namir
Apr 30 '15 at 7:31
is this inline table valued udf ??
– Royi Namir
Apr 30 '15 at 7:31
Yes, it is an ITVF.
– Felix Pamittan
Apr 30 '15 at 7:31
Yes, it is an ITVF.
– Felix Pamittan
Apr 30 '15 at 7:31
1
1
God I love those CTE's
– Royi Namir
Apr 30 '15 at 7:32
God I love those CTE's
– Royi Namir
Apr 30 '15 at 7:32
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f29961576%2fhow-can-i-convert-split-function-to-inline-table-valued-udf-in-sql-server%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown