salve Giorgio,
la soluzione e' perfetta... ma... :D
personalmente non mi e' mai piaciuto utilizzare il tipo di dato text, e non mi e' mai piaciuto utilizzare i "cicli di loop" all'interno di un sistema orientato ai set di dati...
personalmente, quindi, avrei implementato la funzionalita' di split in altro modo, cioe' usando una common table expression ricorsiva, tra l'altro piu' efficiente...
tra l'altro, a partire da SQL Server 2016, e' presente anche un'apposita fuzione di sistema, STRING_SPLIT https://docs.microsoft.com/it-it/sql/t-sql/functions/string-split-transact-sql?view=sql-server-ver15, che puo' fare la stessa cosa...
tornando al codice secco, la mia soluzione sarebbe probabilmente simile a
SET NOCOUNT ON;
USE tempdb;
GO
IF OBJECT_ID('[dbo].[ufn_Split2Table]') <> 0
DROP FUNCTION [dbo].[ufn_Split2Table]
GO
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[ufn_Split2Table] (
@delimiter char(1),
@string varchar(MAX)
)
RETURNS @tbl TABLE (
seqnbr int IDENTITY(1, 1) NOT NULL,
string varchar(255) NOT NULL
)
AS BEGIN
/* splitta il parametro in base al separatore @delimiter */
SET @string = LTRIM(RTRIM(@string));
IF (LEN(@string) > 0) BEGIN
WITH Pieces(pn, startPos, endPos, List) AS (
SELECT 1, CAST(1 AS bigint), CHARINDEX(@delimiter, @string), @string AS List
UNION ALL
SELECT pn + 1, endPos + 1, CHARINDEX(@delimiter, Pieces.List , endPos + 1), Pieces.List
FROM Pieces
WHERE endPos > 0
),
cte AS (
SELECT LTRIM(RTRIM(SUBSTRING(Pieces.List, startPos, CASE WHEN endPos > 0 THEN endPos-startPos ELSE 2147483647 END))) AS [string]
FROM Pieces
)
INSERT @tbl ( [string] )
SELECT cte.[string]
FROM cte
WHERE LEN(cte.[string]) > 0;
END;
RETURN;
END;
GO
PRINT 'Test';
SELECT *
FROM [dbo].[ufn_Split2Table] (',', ',1,12,123,1234,,, 999,');
GO
CREATE TABLE [dbo].[Tb1] (
Id int NOT NULL PRIMARY KEY,
Valore varchar(10)
);
INSERT INTO [dbo].[Tb1]
VALUES ( 1, 'giorgio' ), ( 2, 'flaviovb' ), ( 3, 'andrea' ), ( 4, 'daniele' );
GO
PRINT 'esempio utilizzo: il parametro NON contiene Id = 3 e contiene Id = 99 che non e'' presente in tabella';
SELECT t.[Id], t.[Valore]
FROM [dbo].[Tb1] t
JOIN [dbo].[ufn_Split2Table] ( ',', '1,2,4, 9') u ON u.[string] = CONVERT(varchar(255), t.[Id]);
GO
DROP FUNCTION [dbo].[ufn_Split2Table];
DROP TABLE [dbo].[Tb1];
--<---------------------
Test
seqnbr string
----------- -----------
1 1
2 12
3 123
4 1234
5 999
esempio utilizzo: il parametro NON contiene Id = 3 e contiene Id = 99 che non e' presente in tabella
Id Valore
----------- ----------
1 giorgio
2 flaviovb
4 daniele
non ho ben compreso se in effetti [seqnbr] ti serva o meno, e se lo split deve ritornare un int o un varchar(255) come nel tuo esempio...
salutoni romagnoli e buon weekend...
--
Andrea