【问题标题】:Find an unmatched curly brackets in a string in SQL在 SQL 中的字符串中查找不匹配的大括号
【发布时间】:2014-06-04 10:20:05
【问题描述】:

如何在 SQL 的字符串中找到不匹配的大括号?

DECLARE @iVariable varchar(100)
SET iVariable = '{Day}{Month}{Year}'

如果找到任何不匹配的左括号 ({Day}{Month{Year}),则应返回 'Unmatched {'

如果发现任何不匹配的右括号({Day}{Month}Year}),则应返回 'Unmatched }'

如果没有不匹配的括号,它应该以逗号分隔格式返回值,例如 ('Day,Month,Year')

这样做有什么逻辑吗?

【问题讨论】:

  • 你用的是什么数据库?
  • @Gordon - SQL Server 2008

标签: sql sql-server logic varchar


【解决方案1】:

我要做的是在用 ''(空字符串)替换 '{' 后验证字符串的长度。

DECLARE @iVariable varchar(100) = '{Day}{Month}{Year}'

select case 
   when len(@iVariable) -  len(replace(@iVariable, '{', '')) < len(@iVariable) -  len(replace(@iVariable, '}', '')) 
   then 'Unmatched }'
   when len(@iVariable) -  len(replace(@iVariable, '{', '')) > len(@iVariable) -  len(replace(@iVariable, '}', '')) 
   then 'Unmatched {'
   else right(replace(replace(@iVariable, '{', ','), '}', ''), len(replace(replace(@iVariable, '{', ','), '}', '')) - 1)
end

这里发生的情况是我检查'}'是否比'{'多,它返回不匹配的'}'。 '}' 也是如此。

如果数字匹配,则返回原始字符串,替换掉“{”和“}”,并插入逗号。

编辑:正如 Gordon 在 cmets 中所说,这不适用于例如“{}}{”。

相反,您可以使用用户定义的函数。例如:

create function SomeFunc(@iVariable varchar(2000))
returns varchar(3000)
as
begin

if len(replace(replace(@iVariable, '}', ''), '{', '')) = 0 
   return 'No data present'
else
begin

   -- Declare stuff to be used
   declare @result varchar(3000) = ''
   declare @AMT_Left  int = len(@iVariable) -  len(replace(@iVariable, '{', ''))
   declare @AMT_Right int = len(@iVariable) -  len(replace(@iVariable, '}', ''))


   -- First test if no. of brackets match:
   if @AMT_Left > @AMT_Right 
      set @result = 'Unmatched }'
   else if @AMT_Left < @AMT_Right 
      set @result = 'Unmatched {'
   else if @AMT_Left = @AMT_Right
   begin
   -- If matched, define result, and use while loop for error handling
      set @result = right(replace(replace(@iVariable, '{', ','), '}', ''), len(replace(replace(@iVariable, '{', ','), '}', '')) - 1)
      DECLARE @intFlag INT
      SET @intFlag = 1
      -- Loop through each set and check if '{' occurs before '}':
      WHILE (@intFlag <= @AMT_Left and @result != 'Non matching pair')
      BEGIN
         if charindex('{', @iVariable) > charindex('}', @iVariable)
            set @result =  'Non matching pair'

         set @iVariable = right(@iVariable, len(@iVariable) - charindex('}', @iVariable))
         SET @intFlag = @intFlag + 1
      end
   end

end
return @result
end;

go

使用这些输入值进行测试:

select dbo.SomeFunc('{Day}{Month}{Year}')
select dbo.SomeFunc('{Day}{Month{Year}')
select dbo.SomeFunc('{Day}{Month}Year}')
select dbo.SomeFunc('{}{}')
select dbo.SomeFunc('{}}{')
select dbo.SomeFunc('{Day}}Month{')

结果:

Day,Month,Year
Unmatched }
Unmatched {
No data present
No data present
Non matching pair

【讨论】:

    【解决方案2】:

    可能有更优雅的方式来做到这一点,但以下应该涵盖所有情况:

    with v as (
          select '{Day}{Month}{Year}' as var union all
          select '{Day}{Month}{Year}}{' union all
          select '{Day}{Month}{Year}}}'
         ),
         cte as (
          select left(var, 1) as c, 1 as num, var
          from v
          union all
          select substring(var, num+1, 1), num + 1, var
          from cte
          where num <= len(var)
         ) 
    select var,
           (case when min(balance) < 0 then 'Unbalanced }'
                 when sum(case when c = '{' then 1
                               when c = '}' then -1
                               else 0
                          end) > 0
                 then 'Unbalanced {'
                 else 'Balanced'
           end)
    from (select cte.*,
                 (select sum(case when c = '{' then 1
                                  when c = '}' then -1
                                  else 0
                             end)
                  from cte cte2
                  where cte2.var = cte.var and cte2.num <= cte.num
                 ) as balance
          from cte
         ) t
    group by var;
    

    这会逐个字符地分解值,然后检查平衡。

    【讨论】:

      猜你喜欢
      • 2013-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-22
      • 2012-03-11
      • 1970-01-01
      • 2016-06-14
      • 1970-01-01
      相关资源
      最近更新 更多