Как превратить один столбец таблицы в строку csv в SQL Server без использования курсора

Я хочу вернуть результаты select Column from Table в строку, разделенную запятыми, с помощью SQL Server.

Рассматриваемый столбец довольно большой (nvarchar(2000)), поэтому решение должно обрабатывать очень большие значения результатов.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
26
0
30 005
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий
DECLARE @result nvarchar(max)
SET @result = ''

SELECT @result = @result + [Column] + N','
FROM [TABLE]

--TODO: trim last ',' if you require

PRINT @result

Если Column может быть нулевым, то либо сначала исключите его, либо используйте ISNULL / COALESCE - в противном случае один NULL нарушит всю последовательность. Эффективнее исключить его с помощью WHERE:

SELECT @result = @result + [Column] + N','
FROM [TABLE]
WHERE [Column] IS NOT NULL

работает как рекламируется. Благодарю. для тех, кто найдет это позже, последнюю запятую легко скинуть: select @result = substring(@result, 1, (LEN(@result)-1))

Kyle West 18.01.2009 21:16

SELECT @result = COALESCE (@result + N ',', N '') + [Column] позволит избежать последней запятой без штрафа за производительность.

Robert Jeppesen 20.03.2009 13:25

без конечной запятой версии:

declare @s varchar(max);

select @s = isnull(@s + ', ' + lastname, lastname)
from person
order by lastname;

print @s;

Я ожидал, что это потребует еще несколько циклов процессора, хотя ... лично, если бы мне нужно было его обрезать, я бы вместо этого использовал строковые функции.

Marc Gravell 18.01.2009 20:32

Строки MSSQL неизменяемы, я бы ожидал, что копирование больших строк (обрезка также даст копию) также потребует некоторых циклов процессора, хотя я не уверен. Я думаю, что если это разовая вещь, то микрооптимизации не нужны.

Michael Buen 18.01.2009 21:03

Я бы использовал coalesce вместо isnull

B4ndt 16.11.2015 16:39

Я создал процедуру, которая будет динамически создавать CSV из любой произвольной таблицы без необходимости явно указывать столбцы. Это полезно, если вы не хотите писать собственный код каждый раз, когда хотите преобразовать таблицу SQL в строку CSV.

-- Description: Turns a query into a formatted CSV.
-- Any ORDER BY clause needs to be passed in the separate ORDER BY parameter.
CREATE PROC [dbo].[spQueryToCsv] 
(
  @query nvarchar(MAX), --A query to turn into CSV format. It should not include an ORDER BY clause.
  @orderBy nvarchar(MAX) = NULL, --An optional ORDER BY clause. It should contain the words 'ORDER BY'.
  @csv nvarchar(MAX) = NULL OUTPUT --The CSV output of the procedure.
)
AS
BEGIN   
  SET NOCOUNT ON;

  IF @orderBy IS NULL BEGIN
    SET @orderBy = '';
  END

  SET @orderBy = REPLACE(@orderBy, '''', '''''');  

  DECLARE @realQuery nvarchar(MAX) = '
    DECLARE @headerRow nvarchar(MAX);
    DECLARE @cols nvarchar(MAX);

    SELECT * INTO #dynSql FROM (' + @query + ') sub;    

    SELECT @cols = ISNULL(@cols + '' + '''','''' + '', '''') + ''''''"'''' + ISNULL(REPLACE(CAST(['' + name + ''] AS nvarchar(max)), ''''"'''', ''''""''''), '''''''') + ''''"''''''
    FROM tempdb.sys.columns 
    WHERE object_id = object_id(''tempdb..#dynSql'')
    ORDER BY column_id;        

    SET @cols = ''
      SET @csv = (SELECT '' + @cols + '' FROM #dynSql ' + @orderBy + ' FOR XML PATH(''''m_m''''));
      ''
    EXEC sys.sp_executesql @cols, N''@csv nvarchar(MAX) OUTPUT'', @csv=@csv OUTPUT    

    SELECT @headerRow = ISNULL(@headerRow + '','', '''') + ''"'' + REPLACE(name, ''"'', ''""'') + ''"''
    FROM tempdb.sys.columns 
    WHERE object_id = object_id(''tempdb..#dynSql'')
    ORDER BY column_id;

    SET @headerRow = @headerRow + CHAR(13) + CHAR(10);

    SET @csv = @headerRow + @csv;    
    ';

  EXEC sys.sp_executesql @realQuery, N'@csv nvarchar(MAX) OUTPUT', @csv=@csv OUTPUT
  SET @csv = REPLACE(REPLACE(@csv, '<m_m>', ''), '</m_m>', CHAR(13) + CHAR(10))
END

GO

Применение:

DECLARE @csv nvarchar(max)
EXEC [dbo].[spQueryToCsv]  @query = 'SELECT * FROM Customers', @csv = @csv OUTPUT, @orderBy = 'ORDER BY CustomerId'
SELECT @csv

Это основано на аналогичном коде, который я написал, чтобы превратить произвольную таблицу в HTML-строка.

У меня возникли проблемы с методом, описанным в предложенном ответе. Я взял код из SQLAuthority. Но это работает каждый раз, если у вас есть проблема с предложенным решением.

SELECT SUBSTRING(
(SELECT ',' + s.ColumnName
FROM dbo.table s
ORDER BY s.ColumnName
FOR XML PATH('')),2,200000) AS CSV
GO

Для большого количества значений (~ 100k) этот ответ работает намного быстрее, чем принятый ответ, хотя 200000 необходимо увеличить.

crokusek 14.01.2019 22:45

Я бы предложил использовать STUFF (@ String, 1,1, '') вместо подстроки с огромным значением длины, если вы действительно не хотите установить максимальную длину.

Pete 11.11.2019 20:49

STRING_AGG был добавлен в sql 2017

https://docs.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-2017

SELECT STRING_AGG (ColumnName, ',') AS csv 
FROM TableName
GROUP BY ColumnName2

Для победы! Спасибо.

Rado 06.02.2019 21:18

Если вы застряли в старых базах данных и не можете использовать STRING_AGG и не хотите обрезать после создания строки:

Опция 1:

DECLARE @Comma varchar(10) = '';
DECLARE @Result varchar(MAX) = '';

SELECT @Result = @Result + @Comma + Column, @Comma = ','
FROM Table;

Вариант 2:

DECLARE @Result varchar(MAX) = '';

SELECT @Result = @Result + CASE WHEN LEN(@Result) > 0 THEN ',' ELSE '' END + Column
FROM Table;

Вариант 1 мне нравится, потому что он короче. Я не проводил никаких тестов производительности, поэтому не могу сказать, что лучше в этом отношении.

Если вы выберете вариант 1, убедитесь, что @Comma установлена ​​после @Result, иначе вы получите дополнительную запятую в начале строки.

Протестировано на SQL Server 2008

Другие вопросы по теме