【问题标题】:RegEX to replace "TOP ZZZZ" in SQL Server query stringRegEX 替换 SQL Server 查询字符串中的“TOP ZZZZ”
【发布时间】:2015-10-28 05:09:33
【问题描述】:

我需要一些帮助来弄清楚如何使用 REGEX 来确定 TOP 之后的数字是多少SELECT 查询字符串。

示例:

SELECT top 1000 First_name, Last_name FROM PERS_DAT
SELECT top 50 First_name, Middle_name, Last_Name FROM PERS_DAT
SELECT top 105 Last_name FROM PERS_DAT

从上面的示例查询字符串中,我希望它输出如下:

1000
50
105

REGEX 将如何找出这些信息并将其替换为我自己的值?

【问题讨论】:

  • 这些选择是否存储为某个表中的行。如果是,那么您可以使用 substr 而不是正则表达式。
  • String.Split(New Char() {" "c})[2]Regex.Split(s, "\W+")[2]
  • @RobertHarvey,你的意思肯定是(2),而不是[2] :)

标签: sql sql-server regex vb.net sql-server-2012


【解决方案1】:

这取决于模式需要的灵活性(它需要支持多少种不同的输入变化),但对于正则表达式模式来说,这样的事情将是一个好的开始:

(?<=^\s*SELECT\s+TOP\s+)\d+

您需要指定模式匹配不区分大小写,以便匹配以下任何一项:

SELECT TOP 50
SELECT top 50
select top 50
... etc.

另外,如果输入字符串包含多个 SQL 语句,您需要指定多行选项,以便 ^ 匹配每行的开头而不是字符串的开头。

这是一个完整的例子:

Dim input As String = _
    "SELECT top 1000 First_name, Last_name FROM PERS_DAT" & Environment.NewLine & 
    "SELECT top 50 First_name, Middle_name, Last_Name FROM PERS_DAT" & Environment.NewLine & 
    "SELECT top 105 Last_name FROM PERS_DAT"
Dim pattern As String = "(?<=^\s*SELECT\s+TOP\s+)\d+"
For Each m As Match In RegEx.Matches(input, pattern, RegexOptions.IgnoreCase Or RegexOptions. Multiline)
    Console.WriteLine(m.Value)
Next

正则表达式模式使用后视(即(?&lt;=))语句来指定必须进行任何有效匹配的文本。输入字符串中唯一被捕获为匹配值的部分是\d+ 部分(即数字)。其他一切都只是说数字必须以新行开头,后跟单词“select”和“top”,由任意数量的空白字符分隔。

更新 1

根据您在下面的 cmets,下面是一个示例,说明如何使用 Regex.Replace 将数字替换为不同的值:

Dim input As String = "SELECT top 1000 First_name, Last_name FROM PERS_DAT" 
Dim pattern As String = "(?<=^\s*SELECT\s+TOP\s+)\d+"
Dim output As String = Regex.Replace(input, pattern, Function(x) (Integer.Parse(x.Value) * 10).ToString(), RegexOptions.IgnoreCase)

在上面的示例中,我为 MatchEvaluator 参数传递了一个 lambda 表达式。 lambda 将匹配的数字转换为Integer,将其乘以10,然后将结果转换为字符串并将其作为替换值返回。因此,通过提供该 lambda 表达式,它将导致它用 SELECT top 10000 替换 SELECT top 1000

更新 2

作为一个更复杂的例子,如果你创建了一个这样的方法:

Private Function CapAt350(m As Match) As String
    If Integer.Parse(m.Value) < 350 Then
        Return m.Value
    Else
        Return "350"
    End If
End Function

然后你可以像这样使用它作为你的匹配评估器:

Dim input As String = "SELECT top 1000 First_name, Last_name FROM PERS_DAT"
Dim pattern As String = "(?<=^\s*SELECT\s+TOP\s+)\d+"
Dim output As String = Regex.Replace(input, pattern, AddressOf CapAt350, RegexOptions.IgnoreCase)

【讨论】:

  • 抱歉给您带来了困惑。在给定时间我将只有 1 个 SQL SELECT 语句。我只在我的 OP 中添加了 3 来演示 3 次我会得到什么。
  • 找到我要查找的数字后(如果 m.value > 350) 然后我需要将那个更高的值更改为 350。您将如何在您的 for each 部分中做到这一点?
  • 每个匹配项都提供了描述原始字符串中匹配项的位置和长度的属性,但是,最简单的方法是使用 Regex.Replace 而不是遍历匹配项。您可以为Replace 方法提供自定义MatchEvaluator 方法,该方法可以为每个输入值返回适当的替换值。
  • 您能否在您的帖子中的代码中偶然显示这一点?
  • 我已经更新了我的答案以显示一个示例(并且还删除了多行选项)
【解决方案2】:

如果您的数据存储在表格的列中,您可以在下面不使用正则表达式:-

select substring(firstpart,1,charindex(' ',firstpart,1))
from (select 
substring(quotationId,12,datalength(quotationId)) as firstpart           
              from quotation)x;

Sql 填充:- http://sqlfiddle.com/#!3/411ee8/29

【讨论】:

    【解决方案3】:

    如果我正确理解了您的问题。

     Imports System.Text.RegularExpressions  
    

    代码:

       Dim qry As String
       qry = "SELECT top 1000 First_name, Last_name FROM PERS_DAT"
       qry = qry.Replace(Integer.Parse(Regex.Replace(qry, "[^\d]", "")), "10") 
       /*'here 10 is a custom value,If you want replace 1000 with 10
       /*'output : SELECT top 10 First_name, Last_name FROM PERS_DAT
    

    如果需要,请创建如下所示的函数

    Function Tune_Query_String(ByVal qry As String, ByVal myval As String)
            Tune_Query_String = qry.Replace(Integer.Parse(Regex.Replace(qry, "[^\d]", "")), myval)
            Return Tune_Query_String
    End Function
    

    用法:

    Dim qry As String
    qry  = "SELECT top 50 First_name, Middle_name, Last_Name FROM PERS_DAT"
    qry = Tune_Query_String(qry,"5")
    /*'output:SELECT top 5 First_name, Middle_name, Last_Name FROM PERS_DAT,replaced 50 with 5  
    

    【讨论】:

    • 我测试了它并为我工作,你试过了吗,那么你得到了什么输出??
    猜你喜欢
    • 2014-07-03
    • 1970-01-01
    • 2015-08-20
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    • 2017-05-14
    • 2020-09-21
    • 1970-01-01
    相关资源
    最近更新 更多