2009-03-18 2 views
0

У меня есть строка получателей электронной почты в формате, как это:Выберите элемент из строки элементов

DECLARE @recipients VARCHAR(MAX); 
.... 
PRINT @recipients; 
/* the result 
[email protected];[email protected];[email protected];... 
*/ 

«ВЫБОР DISTIECT ...» представляет собой простой и мощный SQL заявление, но оно работает против Таблица. Есть ли простой способ выбрать отличным получателем из переменной списка получателя, как цикл FOR в C# или Ruby?

FOR @recipient IN @recipients 
BEGIN 
    -- send email to @recipient 
END 

Кстати, я использую TSQL в сервере SQL 2005.

ответ

2

Вот решение для вас, которое использует временную таблицу.

declare @emails varchar(2000) 
set @emails = '[email protected];[email protected];[email protected];' 

declare @results table (row int identity(1,1), email varchar(500)) 

while ((select charindex(';',@emails)) > 0) 
begin 
    insert into @results select substring(@emails,1,charindex(';',@emails)) 
    select @emails = substring(@emails,charindex(';',@emails)+1,len(@emails)) 
end 

select distinct email from @results 

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

После этого вы можете использовать цикл через временную таблицу для отправки ваших индивидуальных писем.

0

Что вы хотите в Сплите функцию, которая будет возвращать таблицу для вас работать.

Существуют несчетные варианты реализации around, но я не знаю о встроенном или о консенсусе «лучшего».

+0

Ваше предложение выглядит это не просто TSQL способом. Функция принимает два параметра, один из получателей и другой как разделитель типа ';' по умолчанию. Это правильно? –

+0

Несомненно. Вы можете сделать разделитель как угодно по умолчанию. Что касается «простого метода T-SQL» - функции являются встроенной частью T-SQL, то функции, связанные с таблицей, существуют со времен SQL Server 2005. –

+0

@David Chu: в Sql Server нет «простого» способа. –

1

например.

CREATE FUNCTION dbo.Split (@sep char(1), @s varchar(512)) 
RETURNS table 
AS 
RETURN (
    WITH Pieces(pn, start, stop) AS (
     SELECT 1, 1, CHARINDEX(@sep, @s) 
     UNION ALL 
     SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1) 
     FROM Pieces 
     WHERE stop > 0 
    ) 
    SELECT pn, 
     SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s 
    FROM Pieces 
) 
GO 
+0

У меня ошибка: Типы не совпадают между якорем и рекурсивной частью в столбце «start» рекурсивного запроса «Pieces» –

+0

OK. Я получил ошибку. Я использовал @s varchar (max). Не знаю, почему max здесь не работает. 512 или 4000 в порядке –

0

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

SELECT DISTINCT String FROM dbo.GetTableFromStringList(@recipients) 

Вы, вероятно, хотите сделать фактическую отправку по электронной почте в чем-то, кроме кода T-SQL, хотя.

Вот функция:

CREATE FUNCTION [dbo].[GetTableFromStringList] 
(
    @StringList VARCHAR(1000), 
    @Delimiter CHAR(1) = ',' 
) 
RETURNS @Results TABLE 
(
    String VARCHAR(1000) NOT NULL 
) 
AS 
BEGIN 
    DECLARE 
     @string  VARCHAR(1000), 
     @position SMALLINT 

    SET @StringList = LTRIM(RTRIM(@StringList)) + @Delimiter 
    SET @position = CHARINDEX(@Delimiter, @StringList) 

    WHILE (@position > 0) 
    BEGIN 
     SET @string = LTRIM(RTRIM(LEFT(@StringList, @position - 1))) 

     IF (@string <> '') 
     BEGIN 
      INSERT INTO @Results (String) VALUES (@string) 
     END 

     SET @StringList = RIGHT(@StringList, LEN(@StringList) - @position) 
     SET @position = CHARINDEX(@Delimiter, @StringList, 1) 
    END 

    RETURN 
END 
Смежные вопросы