2012-04-10 55 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