在SQL Server中分离单个列的值并对其进行更新

在SQL Server中分离单个列的值并对其进行更新,sql,sql-server,Sql,Sql Server,我有一个名为favorite_question的专栏,更新如下: if it is null then insert a value if not null then old value + , + new value if((select Favorite_question from User_Details where User_Id = @userid) IS NULL) begin update User_Details set Favorite_question

我有一个名为favorite_question的专栏,更新如下:

if it is null
then insert a value
if not null then old value + , + new value

if((select Favorite_question from User_Details where User_Id = @userid) IS NULL)
begin
     update User_Details 
     set Favorite_question = (cast(@questionid as varchar(50))) 
     where User_Id = @userid
end
else
begin
     update User_Details 
     set Favorite_question = ((select Favorite_question 
                               from User_Details 
                               where User_Id = @userid ) + ',' +
                              (cast(@questionid as varchar(50)))) 
     where User_Id = @userid
end
其中@userid是用户值,@questionid是问题值

最喜欢的问题被认为是varchar50

我想随机从此列中删除一个值

例如

如果列值为=2,6,8,9,5,我想从中删除8或上面的任何值


同样的sql查询是什么。

UPDATE语句可以进行大量优化。整个ifselect。。。可替换为:

UPDATE User_Details 
SET Favorite_question = COALESCE(Favorite_question + ',', '') + 
                        cast(@questionid as varchar(50))
where User_Id = @userid
现在开始真正的问题:如何从Favorite_questions列中删除文本和数字。 假设该列包含值“2,6,8,9,5”。如果要删除2,则得到',6,8,9,5',因此必须添加处理逻辑以删除开头的孤立逗号。如果要删除5,则会得到“2,6,8,9”,因此必须添加处理逻辑以删除结尾处的孤立逗号。如果要删除8,则得到“2,6,9,5”,因此必须添加处理逻辑来删除中间的双逗号。如果该列包含值“12,6,8,29,5,2”,并且您希望删除“2”,那么您不会希望以类似“1,6,8,9,5”的内容结束

基本上,我们应该花费大量的精力从文本中删除一个正确的数字,并保持文本处于一个干净的状态no',6,8,9,5',2,6',9,5'或类似的状态。SQL不太擅长文本处理

基本问题是您的数据模型没有标准化。您应该从User_Details表中删除列Favorite_question,并创建一个额外的表User_FavoriteQuestions User_Id,question_Id来存储用户的FavoriteQuestions。然后,您的第一个UPDATE语句将替换为

INSERT INTO User_FavoriteQuestions (User_Id, Question_id) 
VALUES(@userid, @questionid)
你真正的问题是:

DELETE FROM User_FavoriteQuestions 
WHERE User_Id = @userid AND Question_id = @questionid

一旦规范化了数据模型,使用SQL对其进行操作就变得容易多了

好的,这种级别的字符串操作并不是SQL的强项。然而,这是可能的

首先,如果要在多个字符串上执行此操作,或者即使是在这种情况下,也可能需要将其放入函数中

为了简化,一种方法是使用一个数字表,该表只包含连续数字的列表。这可以作为一个永久表,但在这个例子中,我将它显示为临时表

declare @numberList table
(
  NumberID int
)
它可以以一种单调乏味的方式填充,但这是来自

接下来,您要将原始文本分成各个部分:

declare @question varchar(20)
declare @questionTable table
(
  qNo int identity(1,1),
  qChar varchar(10)
)

set @question = '2,6,8,9,5'

set @question = ',' + @question + ','

insert into @questionTable(qChar)
select SUBSTRING(@question,NumberID + 1,CHARINDEX(',', @question, NumberID + 1) - NumberID - 1)
from @numberList
where NumberID <= LEN(@question)-1
  and SUBSTRING(@question, NumberID, 1) = ','
然后从临时表中删除零件:

delete from @questionTable where qNo = @posn
然后取回剩下的部分:

 declare @output varchar(20)

 select @output = coalesce(@output+',', '') + qChar
 from @questionTable

不需要通过临时表就可以做到这一点,但是有很多charindex和REPLACEs…

我的最佳猜测是,您可以使用Merge来使用单个语句进行更新/插入

-合并语句

将用户详细信息合并为udp 使用“用户详细信息”中的“选择收藏夹”问题、用户Id 其中User_Id=@userid作为uds

在udp.User\u Id=uds.User\u Id上

匹配时 然后更新集udp.Favorite_question=udp.Favorite_question+','+cast@questionid作为varchar50

当不匹配时 插入器Id,最喜欢的问题 VALUESuds.User\u Id,cast@questionid作为varchar50 ;

有关相同的详细信息,请参见我的博客:


拉动的字符串操作需要几个步骤

declare @S varchar(20)
declare @R varchar(20)

-- String of values
set @S = '2,6,8,9,5'
-- Value to remove
set @R = '8'

-- Add extra commas before and after
set @S = ','+@S+','
set @R = ','+@R+','

-- Remove the value
set @S = stuff(@S, charindex(@R, @S), len(@R)-1, '')

-- Remove extra commas
set @S = substring(@S, 2, len(@S)-2)

select @S
结果:

2,6,9,5
如果需要使用和更新执行此操作,可以使用交叉应用来处理以下步骤:

declare @T table
(
  S varchar(20)
)

insert into @T values('2,6,8,9,5')

declare @R varchar(20)
set @R = '8'

update T1
set S = substring(T3.S, 2, len(T3.S)-2)
from @T as T1
  cross apply (select ','+T1.S+',') as T2(S)
  cross apply (select stuff(T2.S, charindex(','+@R+',', T2.S), len(@R)+1, '')) as T3(S)

select *
from @T  
2,6,9,5
declare @T table
(
  S varchar(20)
)

insert into @T values('2,6,8,9,5')

declare @R varchar(20)
set @R = '8'

update T1
set S = substring(T3.S, 2, len(T3.S)-2)
from @T as T1
  cross apply (select ','+T1.S+',') as T2(S)
  cross apply (select stuff(T2.S, charindex(','+@R+',', T2.S), len(@R)+1, '')) as T3(S)

select *
from @T