从带有分隔字符串的表中插入记录

时间:2011-08-24 11:14:36

标签: sql-server-2000 delimited-text

我有一个表结构,其中包含一个标识符列和一个包含已删除字符串的列。我想要实现的是将已删除的字符串插入到新表中,作为拆分字符串中每个值的单独记录。

源表的表结构如下:

CREATE TABLE tablea(personID VARCHAR(8), delimStr VARCHAR(100))

一些示例数据:

INSERT INTO tablea (personID, delimStr) VALUES ('A001','Monday, Tuesday')
INSERT INTO tablea (personID, delimStr) VALUES ('A002','Monday, Tuesday, Wednesday')
INSERT INTO tablea (personID, delimStr) VALUES ('A003','Monday')

我的目的地表格如下:

CREATE TABLE tableb(personID VARCHAR(8), dayName VARCHAR(10))

我正在尝试创建一个存储过程来进行插入,我的SP到目前为止看起来像:

CREATE PROCEDURE getTKWorkingDays
  @pos integer = 1
  , @previous_pos integer = 0
  AS 
    BEGIN 
    DECLARE @value varchar(50)
            , @string varchar(100)
            , @ttk varchar(8)   
    WHILE @pos > 0 
      BEGIN 
        SELECT  @ttk = personID
                , @string = delimStr
                FROM    dbo.tablea
        SET @pos = CHARINDEX(',', @string, @previous_pos + 1) 
          IF @pos > 0 
            BEGIN       
              SET @value = SUBSTRING(@string, @previous_pos + 1, @pos - @previous_pos - 1)  
              INSERT  INTO dbo.tableb ( personID, dayName ) VALUES  ( @ttk, @value )        
              SET @previous_pos = @pos  
            END     
      END
      IF @previous_pos < LEN(@string) 
        BEGIN   
          SET @value = SUBSTRING(@string, @previous_pos + 1, LEN(@string))  
          INSERT  INTO dbo.tableb ( tkinit, dayName ) VALUES  ( @ttk, @value ) 
        END 
END

插入的数据(原始表中170个左右只有1个记录,在分割了被删除的字符串之后,应该会在新表中产生大约600个左右的记录),这是不正确的。

我期望使用上面的示例数据看到:

personID    dayName
A001        Monday
A001        Tuesday
A002        Monday
A002        Tuesday
A002        Wednesday
A003        Monday

是否有人能够指出任何资源或确定我哪里出错,以及如何使此查询有效?

数据库是MS SQL Server 2000。

我提前感谢您提供的任何帮助。

马特

1 个答案:

答案 0 :(得分:1)

你的SELECT语句让“下一个”的人没有WHERE子句,所以我不确定SQL Server如何知道移动到下一个人。如果这是一次性任务,为什么不使用游标?

CREATE TABLE #n(n INT PRIMARY KEY);

INSERT #n(n) SELECT TOP 100 number     FROM [master].dbo.spt_values 
WHERE number > 0    GROUP BY number    ORDER BY number;

DECLARE 
    @PersonID VARCHAR(8),  @delimStr VARCHAR(100), 
    @str VARCHAR(100),     @c CHAR(1);

DECLARE c CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY
    FOR SELECT PersonID, delimStr FROM dbo.tablea;

OPEN c;

FETCH NEXT FROM c INTO @PersonID, @delimStr;

SET @c = ',';

WHILE @@FETCH_STATUS = 0
BEGIN
    SELECT @delimStr = @c + @delimStr + @c;

    -- INSERT dbo.tableb(tkinit, [dayName])
    SELECT @PersonID, LTRIM(SUBSTRING(@delimStr, n+1, CHARINDEX(@c, @delimStr, n+1)-n-1))
        FROM #n AS n
        WHERE n.n <= LEN(@delimStr) - 1
        AND SUBSTRING(@delimStr, n.n, 1) = @c;

    FETCH NEXT FROM c INTO @PersonID, @delimStr;
END

CLOSE c;
DEALLOCATE c;

DROP TABLE #n;

如果您create a permanent numbers table(显然超过100行),您可以将其用于多种用途。您可以创建一个拆分函数,允许您在没有游标的情况下执行上述操作(好,没有显式游标)。但是,当你最终离开SQL Server 2000时,这可能会效果最好。较新版本的SQL Server具有更灵活和可扩展的方式来执行拆分和连接。