【问题标题】:REGEX in stored procedure in "="/like clause“=”/like子句中存储过程中的正则表达式
【发布时间】:2021-12-22 00:49:00
【问题描述】:

我创建了一个带有 3 个内部连接的存储过程(请不要评判我 :D):

SELECT 
    T.Name, A.Value 
FROM
    Table AS T
INNER JOIN
    TableAnotherTable AS TA ON TA.ID_1 = T.ID_1
INNER JOIN
    AnotherTable AS A ON A.ID_2 = TA.ID_2
INNER JOIN
    EndTable AS ET ON ET.Value = A.Value

TableAnotherTableTableAnotherTable之间的关联表。因此,此存储过程在某些情况下有效(如果 ET.Value 等于A.Value)。

但是如果:

ET.Value = 'SOME\THING\RIGHT\<ABC>\THERE'
A.Value= 'SOME\THING\RIGHT\{DEFGHILM}\THERE'

存储过程也必须工作。

如何将内部连接子句的最后一个ON(带有“=”)更改为:

Regex("pattern1", E.Value) like Regex("pattern", A.Value)

其中patternpattern1({.*?})(&lt;.*?&gt;)

谢谢

例子:

ET.Value = 'HI'
A.Value = 'HI'
true

ET.Value = 'SOME\THING\RIGHT\<ABC>\THERE'
A.Value = 'SOME\THING\RIGHT\{DEFGHILMNOP}\THERE'
true

ET.Value = 'HOME\SWEET\HOME\<12345>\'
A.Value = 'HOME\SWEET\HOME\{4875928346}\'
true

ET.Value = 'EXAMPLE\<1234>'
A.Value = 'EG\{1234}'
false

ET.Value = 'dog'
A.Value = 'cat'
false

【问题讨论】:

  • 和 {} 之间的文本也必须相等?唯一改变的是封装?
  • 不,文字不同。我感兴趣的部分是 和 {} 之外的部分
  • @Carbon4horse 我已经更新了问题。
  • 所以你想忽略&lt;&gt;{} 之间的所有内容?
  • 其他问题:您是否需要匹配第三个反斜杠和最后一个反斜杠之后,还是真的只是SameValue1DIFFERENTSameValue2,其中 SameValues 可以是任何东西(并且只是匹配)?

标签: sql sql-server stored-procedures inner-join


【解决方案1】:

您可以比较没有 和 {} 之间部分的文本:

这里是加入条件:

LEFT(ET.VALUE,CHARINDEX('<', ET.VALUE)-1) +  RIGHT(ET.VALUE,LEN(ET.VALUE)- CHARINDEX('>', ET.VALUE))
=
LEFT(A.Value,CHARINDEX('{', A.Value)-1) +  RIGHT(A.Value,LEN(A.Value)- CHARINDEX('}', A.Value))

但在性能方面可能会很糟糕,因为您转换了用于连接表的键。

【讨论】:

  • 这不起作用,因为如果我有类似的东西:ET.Value = 'HI' e A.Value = 'Hi',没有 {} 或 。
  • @rlnnclt 然后添加ON (ET.VALUE = A.VALUE OR LEFT ...)
  • 你需要NULLIF(CHARINDEX..., 0)以防万一你找不到值
【解决方案2】:

很遗憾,SQL Server 中没有正则表达式替换功能。最接近的方法是使用PATINDEX 定位&lt;{}&gt;' characters and STUFF` 之间的所有内容:

SELECT t.*, CASE WHEN val1_new = val2_new THEN 'match' END
FROM (VALUES
    ('SOMETHING\<1>\SOMETHING',  'SOMETHING\{2}\SOMETHING'),
    ('SOMETHING\BLABLA\<1>\BLA', 'SOMETHING\BLABLA\{2}\BLA'),
    ('SOME\<1>\THING\BLA',       'SOMETHING\{2}\BLABLA'),
    ('dog',                      'dog')
) AS t(val1, val2)
CROSS APPLY (
    SELECT
        PATINDEX('%[<{]%', val1) AS val1_pos1,
        PATINDEX('%[>}]%', val1) AS val1_pos2,
        PATINDEX('%[<{]%', val2) AS val2_pos1,
        PATINDEX('%[>}]%', val2) AS val2_pos2
) AS ca1
CROSS APPLY (
    SELECT
        CASE WHEN val1_pos1 > 0 AND val1_pos2 > 0 THEN STUFF(val1, val1_pos1, val1_pos2 - val1_pos1 + 1, '') ELSE val1 END,
        CASE WHEN val2_pos1 > 0 AND val2_pos2 > 0 THEN STUFF(val2, val2_pos1, val2_pos2 - val2_pos1 + 1, '') ELSE val2 END
) AS ca3(val1_new, val2_new)

【讨论】:

  • 我怎样才能包含这种情况:ET.Value = 'HI' e A.Value = 'Hi' -> match ?
  • 如果两个字符都没有找到,那么你就按原样比较它们。
  • 以哪种方式?抱歉,我是存储过程的新手(是的,我知道我从一个复杂的问题开始)
  • 我已经尝试使用SELECT t.*, CASE WHEN val1_new = val2_new OR val1 = val2 THEN 'match' END 并且它有效。 Result of test
  • INNER JOIN EndTable 更改为 CROSS JOIN EndTable(无 ON 子句),然后从我的答案中添加 CROSS APPLY... val1 将是 A.Value,val2 将是 ET.Value。最后在最后加上WHERE val1_new = val2_new
猜你喜欢
  • 1970-01-01
  • 2014-06-06
  • 2011-09-15
  • 2015-06-07
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2012-07-02
相关资源
最近更新 更多