如何在特定单词后截断字符串?

时间:2019-12-21 07:52:40

标签: sql sql-server tsql sql-server-2014 truncate

我有一个数据类型为nvarchar(max)的字符串,如下所示:

declare @cbCheckdate nvarchar(max) ='
{"request_id":"364202","final_decision":"FAIL","derived_Attribute_1":"PASS|Number of active MFI :1",
"derived_Attribute_4":"PASS|Total Exposure + Applied Amount :53051.0",
"derived_Attribute_3":"PASS|Number of Total Active Institutions :2",
"derived_Attribute_2":"FAIL|Overdue Amount:17984.0","derived_Attribute_5":"PASS|Write off amount:0.0",
"cbResponseMsg":"Final Decision:FAIL || Number of active MFI :1 || Total Exposure + Applied Amount :53051.0 
|| Number of Total Active Institutions :2 || FAILOve'

我需要截断上述字符串,如下所示:

declare @cbCheckdate nvarchar(max) ='{"request_id":"364202","final_decision":"FAIL","derived_Attribute_1":"PASS|Number of active MFI :1",
"derived_Attribute_4":"PASS|Total Exposure + Applied Amount :53051.0",
"derived_Attribute_3":"PASS|Number of Total Active Institutions :2",
"derived_Attribute_2":"FAIL|Overdue Amount:17984.0","derived_Attribute_5":"PASS|Write off amount:0.0"'

基本上我需要做的是:如果我的字符串中包含这个单词cbResponseMsg,那么我需要删除该单词以及其后的所有文本。

6 个答案:

答案 0 :(得分:1)

由于您使用的是SQL Server 2014 ,并且还没有内置的JSON支持,因此我可能会为此编写一个小函数:

CREATE OR ALTER FUNCTION dbo.TruncateAfter(@Input NVARCHAR(MAX), @Delimiter NVARCHAR(100))
RETURNS NVARCHAR(MAX)
AS
BEGIN
    DECLARE @Result NVARCHAR(MAX);

    DECLARE @DelimiterPos INT;
    SET  @DelimiterPos = CHARINDEX(@Delimiter, @Input);

    IF (@DelimiterPos > 0)
        SET @Result = TRIM(LEFT(@Input, @DelimiterPos - 1));
    ELSE
        SET @Result = @Input;

    RETURN @Result;
END

现在,您可以使用两个参数调用此函数-输入和要查找的“定界符”。如果找到定界符,则从其位置开始的任何文本都会被截断-如果定界符未出现在输入中,则返回整个输入:

DECLARE @cbCheckdate NVARCHAR(MAX) = N'
{"request_id":"364202","final_decision":"FAIL","derived_Attribute_1":"PASS|Number of active MFI :1",
"derived_Attribute_4":"PASS|Total Exposure + Applied Amount :53051.0",
"derived_Attribute_3":"PASS|Number of Total Active Institutions :2",
"derived_Attribute_2":"FAIL|Overdue Amount:17984.0","derived_Attribute_5":"PASS|Write off amount:0.0",
"cbResponseMsg":"Final Decision:FAIL || Number of active MFI :1 || Total Exposure + Applied Amount :53051.0 
|| Number of Total Active Institutions :2 || FAILOve'

DECLARE @Delimiter NVARCHAR(MAX) = N'cbResponseMsg';

SELECT 
    dbo.TruncateAfter (@cbCheckdate, @Delimiter)

应返回所需的输出。

答案 1 :(得分:0)

此输入可能是JSON格式,因此,如果您使用SQL Server 2016+,则可以使用JSON_MODIFY()函数从输入JSON中删除cbResponseMsg键:

声明:

DECLARE @cbCheckdate nvarchar(max) = '{
   "request_id":"364202",
   "final_decision":"FAIL",
   "derived_Attribute_1":"PASS|Number of active MFI :1",
   "derived_Attribute_4":"PASS|Total Exposure + Applied Amount :53051.0",
   "derived_Attribute_3":"PASS|Number of Total Active Institutions :2",
   "derived_Attribute_2":"FAIL|Overdue Amount:17984.0",
   "derived_Attribute_5":"PASS|Write off amount:0.0",
   "cbResponseMsg":"Final Decision:FAIL || Number of active MFI :1 || Total Exposure + Applied Amount :53051.0 || Number of Total Active Institutions :2 || FAILOve"
}'

SELECT @cbCheckdate = JSON_MODIFY(@cbCheckdate, '$.cbResponseMsg', NULL)
SELECT @cbCheckdate

结果:

{
   "request_id":"364202",
   "final_decision":"FAIL",
   "derived_Attribute_1":"PASS|Number of active MFI :1",
   "derived_Attribute_4":"PASS|Total Exposure + Applied Amount :53051.0",
   "derived_Attribute_3":"PASS|Number of Total Active Institutions :2",
   "derived_Attribute_2":"FAIL|Overdue Amount:17984.0",
   "derived_Attribute_5":"PASS|Write off amount:0.0"
}

答案 2 :(得分:0)

你可以做到

set @cbCheckdate = left(@cbCheckdate, CHARINDEX('cbResponseMsg', @cbCheckdate) -2)  select @cbCheckdate

答案 3 :(得分:0)

使用内置函数stuffcharindexreverselensign,这是一种无需用户定义函数的安全方法:

declare @cbCheckdate nvarchar(max) ='
{"request_id":"364202","final_decision":"FAIL","derived_Attribute_1":"PASS|Number of active MFI :1",
"derived_Attribute_4":"PASS|Total Exposure + Applied Amount :53051.0",
"derived_Attribute_3":"PASS|Number of Total Active Institutions :2",
"derived_Attribute_2":"FAIL|Overdue Amount:17984.0","derived_Attribute_5":"PASS|Write off amount:0.0",
"cbResponseMsg":"Final Decision:FAIL || Number of active MFI :1 || Total Exposure + Applied Amount :53051.0 
|| Number of Total Active Institutions :2 || FAILOve';

declare @delimiter nvarchar(100) = '"cbResponseMsg"';

SELECT  REVERSE(
            STUFF(
                REVERSE(@cbCheckdate), 
                1,
                CHARINDEX(REVERSE(@delimiter), REVERSE(@cbCheckdate)) + 
                    LEN(@delimiter) * SIGN(CHARINDEX(@delimiter, @cbCheckdate)),
            '')
        )

这是从内到外的细分:

    如果没有找到分隔符,
  • CHARINDEX(@delimiter, @cbCheckdate)将返回0;如果在字符串中找到分隔符,则返回正整数。
  • SIGN将为0返回0,为正数返回1,或者为负数返回-1(与此情况无关)。
  • CHARINDEX(REVERSE(@delimiter), REVERSE(@cbCheckdate)) + LEN(@delimiter) * SIGN(CHARINDEX(@delimiter, @cbCheckdate))将返回0,如果找不到分隔符,或者是一个正整数,表示分隔符开始到字符串结尾之间的字符数。
  • STUFF函数将一个空字符串放入源字符串中,从第一个字符(1开始,然后替换它作为第三个参数使用的字符数。
  • 最后,由于所有操作都是在反转的字符串上完成的,因此reverse再返回一次结果,以正确的顺序返回字符串。

答案 4 :(得分:0)

您可以尝试

SELECT
        CASE
         WHEN @cbCheckdate LIKE '%cbResponseMsg%' THEN LEFT(@cbCheckdate, CHARINDEX('cbResponseMsg', @cbCheckdate)-3)
         ELSE @cbCheckdate
        END

答案 5 :(得分:0)

尝试作为简单有效的查询:

            if User.objects.filter(email=email).exists():
                print("Email taken")
            elif User.objects.filter(username=user_name).exists():
                print("Username taken")
            else:        
                user = User.objects.create_user(username = user_name, first_name=first_name,last_name=last_name, email=email)
                user.set_password(pass1)
                user.save()
                print("User created")