我有一个带varchar(128)列的表,其数据如下:
word1,word2,word3,word4
word1,word2,word3 ,,
word1 ,,,,; WORD2
; word1 word2,word3
我必须更新此表,使单词反向顺序:
word4 ,, word3,word2,word1
,, word3 ,, word2,word1
你能帮助我只使用单个SQL查询吗?
答案 0 :(得分:2)
要完成此任务,需要使用t-sql函数和游标。 fn_SplitList将允许您基于分隔符进行拆分。完成此功能后,您可以创建一个游标,以针对更新每条记录的数据运行。我使用@ table1创建了一个示例。
功能
CREATE FUNCTION [dbo].[fn_SplitList]
(
@RowData varchar(8000),
@SplitOn varchar(5)
)
RETURNS @RtnValue table
(
Id int identity(1,1),
Data varchar(100)
)
AS
BEGIN
Declare @Cnt int
Set @Cnt = 1
While (Charindex(@SplitOn,@RowData)>0)
Begin
Insert Into @RtnValue (data)
Select
Data = ltrim(rtrim(Substring(@RowData,1,Charindex(@SplitOn,@RowData)-1)))
Set @RowData = Substring(@RowData,Charindex(@SplitOn,@RowData)+1,len(@RowData))
Set @Cnt = @Cnt + 1
End
Insert Into @RtnValue (data)
Select Data = ltrim(rtrim(@RowData))
Return
END
执行更新的代码
declare @table1 table(id int primary key
,words varchar(max))
declare @id int
declare @words varchar(max)
insert into @table1 values(0, 'word1, word2, , word3, word4')
insert into @table1 values(1, 'word1, word2, word3, ,')
insert into @table1 values(2, 'word1,,,, ; word2')
insert into @table1 values(3, ';word1 word2, word3')
declare updateCursor cursor for
select id
,words
from @table1
open updateCursor
fetch next from updateCursor into @id, @words
while @@fetch_status = 0
begin
declare @row varchar(255)
select @row = coalesce(@row+', ', '') + data
from dbo.fn_SplitList(@words, ',')
order by id desc
update @table1
set words = @row
where id = @id
fetch next from updateCursor into @id, @words
end
close updateCursor
deallocate updateCursor
select *
from @table1
答案 1 :(得分:1)
最好的办法是永远不要以这种方式存储数据。如果这是一个相关的表格,那么你可以订购你的内心。就个人而言,至少将数据拆分为具有额外标识列的temptable或表变量,然后按该列的desc顺序排序可能是最快的。
答案 2 :(得分:0)
我认为您可以创建一个新表并在该表中插入第一个表中的数据。
INSERT INTO TABLE2 SELECT * FROM TABLE1 ORDER BY COLUMN1 DESC
然后,删除table2并重命名table1。
也许......
答案 3 :(得分:0)
感谢您的回答
单词用空格,逗号和/或分号分隔, 所有分隔符都应该留在原地
e.g。记录
'word1,word2 ;;; word3,'
评估
'word3,word2 ;;; word1,'
由于现有系统的要求,必须这样做 使用单个查询,
我试过了:
update t_desc set name =
(select name
from
(select name,
case when wb is null then rname when wb >= we then stuff(rname, wb, 128, REVERSE (substring(rname, wb, 128))) else
stuff(rname, wb, we-wb+1, REVERSE(substring(rname, wb, we-wb+1))) end rname,
case when wb is null or wb > we then null else PATINDEX('%[a-z0-9]%', SUBSTRING(rname, we+1, 128))+we end wb,
case when we is null or wb > we then null else PATINDEX('%[a-z0-9][^a-z0-9]%', SUBSTRING(rname, we+1, 128))+we end we
from
(select name,
case when wb is null then rname when wb >= we then stuff(rname, wb, 128, REVERSE (substring(rname, wb, 128))) else
stuff(rname, wb, we-wb+1, REVERSE(substring(rname, wb, we-wb+1))) end rname,
case when wb is null or wb > we then null else PATINDEX('%[a-z0-9]%', SUBSTRING (rname, we+1, 128))+we end wb,
case when we is null or wb > we then null else PATINDEX('%[a-z0-9][^a-z0-9]%', SUBSTRING(rname, we+1, 128))+we end we
from
(select name,
case when wb is null then rname when wb >= we then stuff(rname, wb, 128, REVERSE (substring(rname, wb, 128))) else
stuff(rname, wb, we-wb+1, REVERSE(substring(rname, wb, we-wb+1))) end rname,
case when wb is null or wb > we then null else PATINDEX('%[a-z0-9]%', SUBSTRING (rname, we+1, 128))+we end wb,
case when we is null or wb > we then null else PATINDEX('%[a-z0-9][^a-z0-9]%', SUBSTRING(rname, we+1, 128))+we end we
from
(select name,
stuff(rname, wb, we-wb+1, REVERSE(substring(rname, wb, we-wb+1))) rname,
PATINDEX('%[a-z0-9]%', SUBSTRING(rname, we+1, 128))+we wb,
PATINDEX('%[a-z0-9][^a-z0-9]%', SUBSTRING(rname, we+1, 128))+we we
from
(select name, rname,
PATINDEX('%[a-z0-9]%', rname) wb,
PATINDEX('%[a-z0-9][^a-z0-9]%', rname) we
from
(select t_desc.name, REVERSE(name) rname) t1) t2) t3) t4) t5) t6)
和类似的想法,但它没有正常工作
编辑: 除字母和数字之外的所有内容都是分隔符
EDIT2: 不幸的是,我不能调用ddl语句,我没有直接访问数据库, 我的公司使用旧的,封闭的软件 - 我们只能使用外部应用程序的控制台来选择或有时更新。 我可以将我的更新添加到作业列表 - 它将在未来每天执行。
表有大约60k行, 列包含2到20个单词,不为空
抱歉我的英语:)答案 4 :(得分:0)
我有一个想法,因为你受限于一个查询。你能创建一个表值UDF,它会像我之前建议的临时表那样做吗?加入并订购desc。它不会是高效的(当然结构设计得不好时,什么都不会),但除非你有数百万条记录,否则它可能会起作用。
或者你可以制作一个存储过程,只需从你的GUI调用它,这将允许你有多个步骤。