2012-04-10 60 views
2

我需要采取一列中的前半部分单词,并存储在另一列。 我可以假设有偶数的单词。 我用它做了一个游标和一个函数,我发现它需要一个字符串并使用分隔符将它解析到一个表中。试图摆脱光标更新

drop table #test 
create table #test (id int identity, my_name varchar(128), cleaned_name varchar(128)) 

insert into #test (my_name) VALUES ('abcd efgh abcd1 efgh1') 
insert into #test (my_name) VALUES ('name1 name2 name1a name2a') 
insert into #test (my_name) VALUES ('one two one* two*') 

select * 
from #test 


DECLARE @HalfName varchar(100) 
DECLARE @i varchar(100) 
set @i = 1 
while @i <= (select count(*) from #test) 
begin 
     SELECT @HalfName = COALESCE(@HalfName + ' ', '') + aa.WORD 
     FROM (select top (select count(*)/2 from dm_generic.dbo.GETALLWORDS((select [my_name] 
     from #test 
     where id = @i), ' ')) * 
     from dm_generic.dbo.GETALLWORDS(
     (select [my_name] 
     from #test 
     where id = @i), ' ') 
    ) aa 

     update #test 
     set cleaned_name = @HalfName 
     where id = @i 

     set @i = @i + 1 
     set @HalfName = '' 
end 

select * 
from #test   

我试图做到这一点无光标:

UPDATE bb 
    SET cleaned_name = 
      (SELECT COALESCE (bb.cleaned_name + ' ', '') + aa.WORD 
      FROM (SELECT TOP (SELECT count (*)/2 
           FROM dm_generic.dbo.GETALLWORDS (
             (SELECT [my_name] 
              FROM #test a 
              WHERE a.id = bb.id), 
             ' ')) 
          * 
        FROM dm_generic.dbo.GETALLWORDS ((SELECT [my_name] 
                  FROM #test b 
                 WHERE b.id = bb.id), 
                 ' ')) aa) 
    FROM #test bb 

什么,我得到的是:

Msg 512, Level 16, State 1, Line 1 
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. 
The statement has been terminated. 

任何帮助将不胜感激。

感谢所有响应,我终于用this solution通过@BradC酿造我自己的,那就是:

update updated 
set cleaned_name = (
SELECT Clean 
FROM #test AS extern 
CROSS APPLY 
( 
select TOP (SELECT count (*)/2 
      FROM dm_generic.dbo.GETALLWORDS (
              (SELECT [my_name] 
              FROM #test a 
              WHERE a.id = extern.id), ' ')) 
WORD + ' ' 
FROM dm_generic.dbo.GETALLWORDS (
     (SELECT [my_name] 
      FROM #test a 
      WHERE a.id = extern.id), 
     ' ') 
    FOR XML PATH('') 
) pre_trimmed (Clean) 
where extern.id = updated.id) 
from #test updated 

@NikolaMarkovinović解决方案的伟大工程,以及。

回答

1

局部变量连接技巧在没有局部变量的情况下无法工作 - 您正在使用@HalfName连接来自GETALLWORDS的单词,但无法使用列名称(在本例中为cleared_name)。要使其工作,您应该使用for xml path concatenation trick

因此,如果您正在使用SQL Server 2005或更新工作,试试这个:

UPDATE bb 
    SET cleaned_name = 
     (SELECT stuff ((SELECT TOP (SELECT count (*)/2 
            FROM dm_generic.dbo.GETALLWORDS (
             (SELECT [my_name] 
              FROM #test a 
              WHERE a.id = bb.id), 
             ' ') 
           ) 
          ' ' + aa.my_name 
         FROM dm_generic.dbo.GETALLWORDS (
             (SELECT [my_name] 
              FROM #test a 
              WHERE a.id = bb.id), 
             ' ') aa 
         FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)') 
        , 1, 1, '') 
    ) 
    FROM #test bb 

声明:我不能对此进行测试。只用UDF尝试一下,然后将其合并到查询中。

更新:我放错了括号 - 最后一行中的第一个右括号应该被删除,并且应该在最后一行之后添加一个。

+0

我收到“Msg 174,Level 15,State 1,Line 3 stuff函数需要4个参数。” 。价值是什么以及它在同一行中的价值是什么? – bodman 2012-04-10 12:15:07

+0

@bodman希望我已经纠正了我的答案。 – 2012-04-10 12:23:45

+0

是@NikolaMarkovinović现在可以工作,但'+ aa.my_name实际上应该是''+ aa.WORD,它是从GETALLWORDS返回的列的名称。我仍然试图弄清楚这是什么:.value('(./ text())[1]','VARCHAR(MAX)') – bodman 2012-04-11 07:52:25

0

下面创建功能

ALTER FUNCTION [dbo].[halfWords] 
    (
     @InputString VARCHAR(4000) 
    ) 
RETURNS VARCHAR(4000) 
AS BEGIN 

    DECLARE @Index INT 
    DECLARE @Char CHAR(1) 
    DECLARE @PrevChar CHAR(1) 
    DECLARE @WordCount INT 
    DECLARE @WordCount2 INT 
    DECLARE @firstHalf varchar(4000) 

    SET @Index = 1 
    SET @WordCount = 0 

    WHILE @Index <= LEN(@InputString) 
     BEGIN 
      SET @Char = SUBSTRING(@InputString, @Index, 1) 
      SET @PrevChar = CASE WHEN @Index = 1 THEN ' ' 
           ELSE SUBSTRING(@InputString, @Index - 1, 1) 
          END 

      IF @PrevChar = ' ' 
       AND @Char != ' ' 
       SET @WordCount = @WordCount + 1 

      SET @Index = @Index + 1 
      SET @wordcount2 = (@wordcount/2) 
     END 


    SET @wordcount = 0 
    SET @Index = 1 
    WHILE @Index <= LEN(@InputString) 
     BEGIN 
      SET @Char = SUBSTRING(@InputString, @Index, 1) 
      SET @PrevChar = CASE WHEN @Index = 1 THEN ' ' 
           ELSE SUBSTRING(@InputString, @Index - 1, 1) 
          END 

      IF @PrevChar = ' ' 
       AND @Char != ' ' 
       SET @WordCount = @WordCount + 1 


      IF (@wordcount2 = @WordCount) 
       BEGIN 
        SET @firstHalf = SUBSTRING(@InputString, 0, @Index) 

       END 
      SET @Index = @Index + 1 

     END 
    RETURN @firstHalf 
    END 

,然后用它下面的更新查询

UPDATE #test 
    SET  cleaned_name = dbo.[halfWords] (my_name) 

选择查询参考

SELECT dbo.halfWords ('one two three four five six seven eight') 

将返回

one two three four