J'ai une liste d'identifiants séparés par des virgules comme:
1,17,25,44,46,67,88
Je veux les convertir en enregistrements de table (en table temporaire) comme
#tempTable
number_
--------
1
17
25
44
46
67
88
C’est possible avec une fonction, une table?
Pourquoi je veux ça? Je souhaite utiliser la clause INNER JOIN
(dans la procédure stockée) avec une ou plusieurs autres tables, par exemple:
SELECT a,b,c FROM T1
INNER JOIN functionNameWhichReturnsTable
ON functionNameWhichReturnsTable.number_ = T1.a
Je ne peux pas utiliser IN
car je vais utiliser une procédure stockée qui accepte un paramètre de type NVARCHAR. Ce paramètre fournira la liste des identifiants.
Je vous remercie
Doublage possible de séparer les valeurs séparées par des virgules et stocker dans une table dans le serveur SQL .
Veuillez essayer une valeur précise de Valeur délimitée par des virgules dans le tableau :
CREATE FUNCTION [dbo].[ufn_CSVToTable] ( @StringInput VARCHAR(8000), @Delimiter nvarchar(1))
RETURNS @OutputTable TABLE ( [String] VARCHAR(10) )
AS
BEGIN
DECLARE @String VARCHAR(10)
WHILE LEN(@StringInput) > 0
BEGIN
SET @String = LEFT(@StringInput,
ISNULL(NULLIF(CHARINDEX(@Delimiter, @StringInput) - 1, -1),
LEN(@StringInput)))
SET @StringInput = SUBSTRING(@StringInput,
ISNULL(NULLIF(CHARINDEX(@Delimiter, @StringInput), 0),
LEN(@StringInput)) + 1, LEN(@StringInput))
INSERT INTO @OutputTable ( [String] )
VALUES ( @String )
END
RETURN
END
GO
Vérifiez l'exigence d'une autre manière en utilisant XML:
DECLARE @param NVARCHAR(MAX)
SET @param = '1:0,2:1,3:1,4:0'
SELECT
Split.a.value('.', 'VARCHAR(100)') AS CVS
FROM
(
SELECT CAST ('<M>' + REPLACE(@param, ',', '</M><M>') + '</M>' AS XML) AS CVS
) AS A CROSS APPLY CVS.nodes ('/M') AS Split(a)
La méthode que j'ai trouvée ne nécessite aucune fonction ni astuce XML.
En gros, vous transformez la chaîne en une seule instruction d'insertion pour la table temporaire.
.__ qui peut ensuite être utilisé pour un traitement ultérieur.
IF OBJECT_ID('tempdb..#tempTable') IS NOT NULL DROP TABLE #tempTable;
CREATE TABLE #tempTable (number int);
DECLARE @TEXT varchar(max) = '1,17,25,44,46,67,88';
DECLARE @InsertStatement varchar(max) = 'insert into #tempTable values ('+REPLACE(@TEXT,',','),(')+');';
EXEC (@InsertStatement);
SELECT * FROM #tempTable;
Cette méthode est utilisable pour 1000 valeurs maximum.
Parce que 1000 est la limite maximale d'une expression de valeur de ligne.
Ou jusqu'à ce que la limite de varchar pour le @InsertStatement soit atteinte.
En outre, comme l'a souligné Stuart Ainsworth.
Comme cette méthode utilise EXEC, méfiez-vous de l’injection de code et ne l’utilisez pas pour les chaînes basées sur une entrée utilisateur non vérifiée.
Essayez ce code
SELECT RTRIM(part) as part
INTO Table_Name
FROM dbo.splitstring(@Your_Comma_string,',')
la fonction splitstring est la suivante
CREATE FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(MAX) )
RETURNS
@returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN
DECLARE @name NVARCHAR(255)
DECLARE @pos INT
WHILE CHARINDEX(',', @stringToSplit) > 0
BEGIN
SELECT @pos = CHARINDEX(',', @stringToSplit)
SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)
INSERT INTO @returnList
SELECT @name
SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
END
INSERT INTO @returnList
SELECT @stringToSplit
RETURN
END
En complétant les réponses, vous pouvez également utiliser la chaîne CSV pour stocker plusieurs valeurs dans plusieurs colonnes:
--input sql text
declare @text_IN varchar(max) ='text1, text1.2, text1.3, 1, 2010-01-01\r\n text2, text2.2, text2.3, 2, 2016-01-01'
Divisez le fichier csv en lignes:
declare @temptable table (csvRow varchar(max))
declare @DelimiterInit varchar(4) = '\r\n'
declare @Delimiter varchar(1) = '|'
declare @idx int
declare @slice varchar(max)
set @text_IN = REPLACE(@text_IN,@DelimiterInit,@Delimiter)
select @idx = 1
if len(@text_IN)<1 or @text_IN is null return
while @idx!= 0
begin
set @idx = charindex(@Delimiter,@text_IN)
if @idx!=0
set @slice = left(@text_IN,@idx - 1)
else
set @slice = @text_IN
if(len(@slice)>0)
insert into @temptable(csvRow) values(@slice)
set @text_IN = right(@text_IN,len(@text_IN) - @idx)
if len(@text_IN) = 0 break
end
Fractionner les lignes en colonnes:
;WITH XMLTable (xmlTag)
AS
(
SELECT CONVERT(XML,'<CSV><champ>' + REPLACE(csvRow,',', '</champ><champ>') + '</champ></CSV>') AS xmlTag
FROM @temptable
)
SELECT RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[1]','varchar(max)'))) AS Column1,
RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[2]','varchar(max)'))) AS Column2,
RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[3]','varchar(max)'))) AS Column3,
RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[4]','int'))) AS Column4,
RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[5]','datetime'))) AS Column5
FROM XMLTable
Les oeuvres suivantes:
declare @parStoreNo As varchar(8000) = '1,2,3,4'
CREATE TABLE #parStoreNo (StoreNo INT)-- drop #parStoreNo
declare @temptable VARCHAR(1000) = @parStoreNo
declare @SQL VARCHAR(1000)
SELECT @SQL = CONVERT(VARCHAR(1000),' select ' + REPLACE(ISNULL(@temptable,' NULL '),',', ' AS Col UNION ALL SELECT '))
INSERT #parStoreNo (StoreNo)
EXEC (@SQL)