我需要将一半的单词放在一列中并存储在另一列中。 我可以假设有很多单词。 我使用游标和我发现的函数来完成它,它接受一个字符串并使用分隔符将其解析为表。
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.
任何帮助将不胜感激。
感谢所有响应者,我终于使用@BradC的this solution来酿造我自己的,这里是:
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ć解决方案也很有效。
答案 0 :(得分:1)
局部变量连接技巧在没有局部变量的情况下不起作用 - 您使用@HalfName连接GETALLWORDS中的单词,但它不能使用列名(在本例中为cleaning_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,然后将其合并到查询中。
更新:我错放了括号 - 应该删除最后一行中的第一个右括号,并且应该在最后一行后添加一个括号。
答案 1 :(得分: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