Function that returns multiple columns

3.8k views Asked by At

I am creating a function that splits up strings. I want to pass the function to a string and get several rows back (the amount of rows would be dynamic depending on the length of the string).

I was thinking of possibly using a table function and joining this to my query.

I am NOT asking for this to be written for me, I am simply wondering if this is even possible in SQL Server 2014, and what the best approach would be if it is.

So the string 'ABC' would be returned as:

COL1  COL2  COL3
A      B    C
2

There are 2 answers

2
D Stanley On BEST ANSWER

I am simply wondering if this is even possible in SQL Server 2014

Yes, you can create table-valued user defined functions that return, well, a table value.

So the string 'ABC' would be returned as:

COL1  COL2  COL3
A      B    C

Well, now you're in trouble - table-valued functions must have a return value with a pre-defined schema, so you can't dynamically set the column names. You could return those as rows, though:

Item  Value
1     A
2     B
3     C
0
Giorgi Nakeuri On

You didn't mentioned where do you want to apply this but there are solutions:

DECLARE @t TABLE(id int, n VARCHAR(50))
INSERT INTO @t VALUES
(1, 'ABCDEF'),
(2, 'EFGHIJKLMNOPQ')


;WITH cte AS
(SELECT id, n, SUBSTRING(n, 1, 1) c, 1 AS ind FROM @t
 UNION ALL 
 SELECT id, n, SUBSTRING(n, ind + 1, 1), ind + 1 FROM cte WHERE LEN(n) > ind
)

SELECT *
FROM cte 
PIVOT (MAX(c) FOR ind IN([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[12],[13],[14],[15])) p

Output:

id  n               1   2   3   4   5   6   7    8    9    10   12   13   14    15
1   ABCDEF          A   B   C   D   E   F   NULL NULL NULL NULL NULL NULL NULL  NULL
2   EFGHIJKLMNOPQ   E   F   G   H   I   J   K    L    M    N    P    Q    NULL  NULL

Here is dynamic version:

DECLARE @l INT, @c VARCHAR(MAX) = ''
SELECT @l = MAX(LEN(n)) FROM PivotTable

WHILE @l > 0
BEGIN
 SET @c = ',[' + CAST(@l AS VARCHAR(MAX)) + ']' + @c
 SET @l = @l - 1
END

SET @c = STUFF(@c, 1, 1,'')

DECLARE @s NVARCHAR(MAX) = '
;WITH cte AS
(SELECT id, n, SUBSTRING(n, 1, 1) c, 1 AS ind FROM PivotTable
 UNION ALL 
 SELECT id, n, SUBSTRING(n, ind + 1, 1), ind + 1 FROM cte WHERE LEN(n) > ind
)

SELECT *
FROM cte 
PIVOT (MAX(c) FOR ind IN(' + @c + ')) p'

EXEC (@s)