首先 - 抱歉我的英语。第二 - 我学习t-SQL。
目标:
我想在两个字符串之间找到区别,然后检查哪个列是这个区别。如果差异在第一列,请执行某些操作,如果在第二列中 - 执行其他操作。
我实际上在做什么
列'消息'是一个包含ID列表的字符串。所以我要取代所有的#'#'与','并删除最后一个','什么给了我 ActualID 和 BeforeID 列。见下文:
DECLARE @string VARCHAR(512);
DECLARE @string2 VARCHAR(512);
DECLARE @string3 VARCHAR(512);
SET @string = '41#42#43#44#45#46#47#48#49#50#51#52#53#54#55#56#57#58#59#';
SET @string2 = REPLACE((SELECT messages FROM USERS WHERE userid = 4), '#', ', ' )
SET @string3 = left(@string2, len(@string2) - 1);
SET @string2 = REPLACE(@string, '#', ', ' )
SET @string = left(@string2, len(@string2) - 1);
SELECT @string3 as ActualID, @string as BeforeID
现在,我希望将 BeforeID 与 ActualID 进行比较。例如:
在BeforeID中,我们有1, 2, 3
/ In ActualID 1, 2, 3, 4
在上面的示例中添加了4
。因此,如果添加它,我想将其添加到@AddedElements
。
如果添加了4, 5, 7
,那么SELECT @AddedElements as AddedElements
应该返回4, 5, 7
(有逗号)
但是,并非全部。
如果 BeforeID = 1, 5, 10, 14
且 ActualID = 1, 5, 14
,我想要的是 BeforeID 中的元素,但不会将 AcutalID 添加到@DeletedElements中。
因此SELECT @DeletedElements as DeletedElements
应该返回10
添加元素/已删除的元素应返回一次。我的意思是,我希望获得的完整结果应该是
SELECT @AddedElements as AddedElements, @DeletedElements as DeletedElements
有可能吗?如果,那怎么办?
答案 0 :(得分:1)
首先,我必须首先说这只是糟糕的设计;但话虽如此,我也发现自己处于各种情况下,我无法改变工作方式,只是试着让它们在当前配置中更好地工作。因此,我建议这样的事情:
1:创建一个UDF(用户定义函数),它可以处理拆分字符串并将它们返回到可以使用的表格数据中:
CREATE FUNCTION [dbo].[UDF_StringDelimiter]
/*********************************************************
** Takes Parameter "LIST" and transforms it for use **
** to select individual values or ranges of values. **
** **
** EX: 'This,is,a,test' = 'This' 'Is' 'A' 'Test' **
*********************************************************/
(
@LIST VARCHAR(8000)
,@DELIMITER VARCHAR(255)
)
RETURNS @TABLE TABLE
(
[RowID] INT IDENTITY
,[Value] VARCHAR(255)
)
WITH SCHEMABINDING
AS
BEGIN
DECLARE
@LISTLENGTH AS SMALLINT
,@LISTCURSOR AS SMALLINT
,@VALUE AS VARCHAR(255)
;
SELECT
@LISTLENGTH = LEN(@LIST) - LEN(REPLACE(@LIST,@DELIMITER,'')) + 1
,@LISTCURSOR = 1
,@VALUE = ''
;
WHILE @LISTCURSOR <= @LISTLENGTH
BEGIN
INSERT INTO @TABLE (Value)
SELECT
CASE
WHEN @LISTCURSOR < @LISTLENGTH
THEN SUBSTRING(@LIST,1,PATINDEX('%' + @DELIMITER + '%',@LIST) - 1)
ELSE SUBSTRING(@LIST,1,LEN(@LIST))
END
;
SET @LIST = STUFF(@LIST,1,PATINDEX('%' + @DELIMITER + '%',@LIST),'')
;
SET @LISTCURSOR = @LISTCURSOR + 1
;
END
;
RETURN
;
END
;
2:考虑放弃整个“切换逗号”的东西,因为它没有意义 - 我在这里写的函数有两个参数:字符串本身和分隔符(分隔单个字符串的迷你字符串)大字符串,在你的情况下'#')然后你只需要做几个快速比较,找出添加的内容和删除的内容。
DECLARE
@AddedElements VARCHAR(255) = ''
,@DeletedElements VARCHAR(255) = ''
,@ActualID VARCHAR(255) = '41#42#43#44#45#46#47#48#49#50#51#52#53#54#55#56#57#58#59#'
,@BeforeID VARCHAR(255) = '41#42#43#44#45#46#47#48#50#51#52#53#54#55#56#57#58#59#60#'
;
SET @AddedElements = @AddedElements +
SUBSTRING(
(
SELECT ', ' + Value
FROM dbo.UDF_StringDelimiter(@ActualID,'#')
WHERE Value NOT IN
(
SELECT Value
FROM dbo.UDF_StringDelimiter(@BeforeID,'#')
)
GROUP BY ', ' + Value
FOR XML PATH('')
)
,3,255)
;
SET @DeletedElements = @DeletedElements +
SUBSTRING(
(
SELECT ', ' + Value
FROM dbo.UDF_StringDelimiter(@BeforeID,'#')
WHERE Value NOT IN
(
SELECT Value
FROM dbo.UDF_StringDelimiter(@ActualID,'#')
)
GROUP BY ', ' + Value
FOR XML PATH('')
)
,3,255)
;
SELECT @AddedElements AS AddedElements,@DeletedElements AS DeletedElements
;
使用此方法,如果您向@ActualID
添加@BeforeID
中不存在的值,它将显示在@AddedElements
中。
同样,如果您从先前@ActualID
中存在的@BeforeID
中删除了一个元素,它将显示在@DeletedElements
中。
当然,所有这些都假设动态字符串(这里真正比较的那个)是@ActualID
。我操作时理解@BeforeID
实际上是DB中的存储值,而@ActualID
是从某个地方传入的动态字符串。如果这是错误的,请更新我,我会适当地改变策略。
快速说明:对我来说,重要的是要指出这只是处理这种情况的一种方式,而且我确信有更好的方法;但是根据我所拥有的信息,这是我能想到的最好的,而不会花太多时间和精力。