Il n'y a pas de fonction intégrée dans Sql Server, mais cela peut être réalisé en écrivant un agrégat défini par l'utilisateur. Cet article mentionne une telle fonction comme faisant partie des échantillons de SQL Server : http://msdn.microsoft.com/en-us/library/ms182741.aspx
À titre d'exemple, j'ai inclus le code d'un agrégat de type Concaténation. Pour l'utiliser, créez un projet de base de données dans Visual Studio, ajoutez un nouveau SqlAggregate et remplacez le code par l'exemple ci-dessous. Une fois déployé, vous devriez trouver un nouvel assembly dans votre base de données et une fonction d'agrégation Concatenate
using System;
using System.Data.SqlTypes;
using System.IO;
using System.Text;
using Microsoft.SqlServer.Server;
[Serializable]
[SqlUserDefinedAggregate(Format.UserDefined, IsInvariantToNulls = true, IsInvariantToDuplicates = false, IsInvariantToOrder = false, MaxByteSize = 8000, Name = "Concatenate")]
public class Concatenate : IBinarySerialize
{
private StringBuilder _intermediateResult;
internal string IntermediateResult {
get
{
return _intermediateResult.ToString();
}
}
public void Init()
{
_intermediateResult = new StringBuilder();
}
public void Accumulate(SqlString value)
{
if (value.IsNull) return;
_intermediateResult.Append(value.Value);
}
public void Merge(Concatenate other)
{
if (null == other)
return;
_intermediateResult.Append(other._intermediateResult);
}
public SqlString Terminate()
{
var output = string.Empty;
if (_intermediateResult != null && _intermediateResult.Length > 0)
output = _intermediateResult.ToString(0, _intermediateResult.Length - 1);
return new SqlString(output);
}
public void Read(BinaryReader reader)
{
if (reader == null)
throw new ArgumentNullException("reader");
_intermediateResult = new StringBuilder(reader.ReadString());
}
public void Write(BinaryWriter writer)
{
if (writer == null)
throw new ArgumentNullException("writer");
writer.Write(_intermediateResult.ToString());
}
}
Pour l'utiliser, il suffit d'écrire une requête agrégée :
create table test(
id int identity(1,1) not null
primary key
, class tinyint not null
, name nvarchar(120) not null )
insert into test values
(1, N'This'),
(1, N'is'),
(1, N'just'),
(1, N'a'),
(1, N'test'),
(2, N','),
(3, N'do'),
(3, N'not'),
(3, N'be'),
(3, N'alarmed'),
(3, N','),
(3, N'this'),
(3, N'is'),
(3, N'just'),
(3, N'a'),
(3, N'test')
select dbo.Concatenate(name + ' ')
from test
group by class
drop table test
La sortie de la requête est :
-- Output
-- ===================
-- This is just a test
-- ,
-- do not be alarmed , this is just a test
J'ai empaqueté la classe et l'agrégat dans un script que vous pouvez trouver ici : https://gist.github.com/FilipDeVos/5b7b4addea1812067b09
0 votes
Oui, cette question a été posée plusieurs fois sur SO. stackoverflow.com/questions/1874966/ o stackoverflow.com/questions/3121079/
0 votes
Ah, c'est ma faute. Je n'ai pas utilisé les bons mots-clés de recherche :) Le vote est terminé.
0 votes
Répondu à de nombreuses reprises... mais attention, tous ne sont pas
FOR XML PATH concatenations
traiteront correctement les caractères spéciaux XML (<
,&
,>
) comme mon exemple de code (ci-dessous) le fera...0 votes
C'est aussi un double de : stackoverflow.com/questions/273238/
5 votes
SqlServer 2017 dispose désormais de STRING_AGG qui regroupe plusieurs chaînes de caractères en une seule en utilisant un séparateur donné.