David.Chu.ca
David.Chu.ca

Reputation: 38664

Select item from a string of items

I have a string of email recipients in the format like this:

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

"SELECT DISTIECT ..." is a simple and powerful SQL statement, but it works against a table. Is there a simple way to select distinct recipient from the recipient list variable like FOR loop in C# or Ruby?

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

By the way, I am using TSQL in SQL server 2005.

Upvotes: 0

Views: 876

Answers (4)

Tom H
Tom H

Reputation: 47392

I use a function like the one below to deal with a similar situation when receiving lists like that from the front end. Then you can just use this code to return the string as a table instead:

SELECT DISTINCT String FROM dbo.GetTableFromStringList(@recipients)

You probably want to do the actual sending of the email in something other than T-SQL code though.

Here's the function:

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

Upvotes: 0

adolf garlic
adolf garlic

Reputation: 3096

e.g.

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

Upvotes: 1

Some Canuck
Some Canuck

Reputation: 846

Here's a solution for you that uses a temporary table.

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

The idea is to continously parse the email from the string, insert it into a temporary table, and remove the parsed email from the remaining string.

You can use loop through the temporary table afterward to send your individual emails.

Upvotes: 2

Tom Ritter
Tom Ritter

Reputation: 101390

What you want in a Split function that will return a table for you to work with.

There are uncountable implementations around but I'm not aware of a built-in one, or a consensus of the 'best'.

Upvotes: 0

Related Questions