简体   繁体   English

通过正则表达式确定SQL命令是否为UPDATE命令

[英]Determine Whether SQL Command is an UPDATE command by regular expressions

I've lots of SQL commands from Entity framework's interceptors such as following: 我有很多来自实体框架的拦截器的SQL命令,如下所示:

UPDATE [dbo].[Products]
SET [Name] = @0
WHERE ([Id] = @1)

How can I determine that this command is an UPDATE command ? 如何确定此命令是UPDATE命令?

I've written following regular expression: 我写了以下正则表达式:

(update)? [a-z0-9-]+ (set)

But it does not support commands in multiple lines and the command text should be in one line, and it does not support table names with schema and [] characters in their names. 但是它不支持多行命令,命令文本应该在一行中,并且不支持名称中带有模式和[]字符的表名。

It only supports simple SQL commands as following: 它仅支持简单的SQL命令,如下所示:

UPDATE Products SET [Name] = @0 WHERE ([Id] = @1)

Note: I'm using this regular expression and IDbCommandInterceptor feature of Entity Framework to provide WITH (ROWLOCK) table hints to SQL server for UPDATE commands, so I need a regular expression from UPDATE keyword to SET keyword because WITH (ROWLOCK) should be inserted right before SET keyword. 注意:我正在使用此正则表达式和Entity Framework的IDbCommandInterceptor功能向SQL Server提供UPDATE命令的WITH (ROWLOCK)表提示,因此我需要一个从UPDATE关键字到SET关键字的正则表达式,因为应该插入WITH (ROWLOCK)SET关键字之前。

Consider following code: 考虑以下代码:

String updateCommandRegularExpression = "(update)? [a-z0-9-]+ (set)";

Boolean isUpdateCommand = Regex.IsMatch(commandText, updateCommandRegularExpression, RegexOptions.IgnoreCase | RegexOptions.Multiline); // You may use better regular expression pattern here.

if (isUpdateCommand)
{
    Boolean isSnapshotIsolationTransaction = sqlCommand.Transaction != null && sqlCommand.Transaction.IsolationLevel == IsolationLevel.Snapshot;
    // Transactions with Snapshot isolation level have more complicated table hints to enable rowlock.

    String tableHintToAdd = isSnapshotIsolationTransaction ? " with (rowlock , updlock) set " : " with (rowlock) set ";

    commandText = Regex.Replace(commandText, updateCommandRegularExpression, (match) =>
    {
        return Regex.Replace(match.Value, " SET ", tableHintToAdd, RegexOptions.IgnoreCase); // You may use better regular expression here.
    }, RegexOptions.IgnoreCase | RegexOptions.Multiline);

    command.CommandText = commandText;
}

How about something like this? 这样的事情怎么样?

'[; \t]*[Uu][Pp][Dd][Aa][Tt][Ee][ \t]'

Basically, an update command is one where the first word is update -- at least for simple commands. 基本上,更新命令是第一个单词被update命令-至少对于简单命令而言。 If you allow common table expressions ( with statements), then the logic is more challenging. 如果允许公用表表达式( with语句),则逻辑更具挑战性。

EDIT: 编辑:

I would suggest the following approach. 我建议采用以下方法。 Use the above expression to determine if the command is an update. 使用上面的表达式确定命令是否为更新。 Then, replace "set " with " with (ROWLOCK) set". 然后,将“ set”替换为“(ROWLOCK)set”。 This will handle the cases where the table might have special characters or use an alias. 这将处理表可能具有特殊字符或使用别名的情况。 The one downside is it will not help if the table contains "set". 缺点是,如果表中包含“ set”,将无济于事。

Because you are doing this in C#, you can test to see if the characters before and after the set are white space characters rather than alphanumeric. 因为您是在C#中执行此操作,所以可以测试一下集合前后的字符是否为空格字符,而不是字母数字。

Note: This will not work correctly if the update already has hints. 注意:如果update已包含提示,则此操作将无法正常工作。 You can look for that by looking for "with" before the "set". 您可以通过在“设置”之前寻找“ with”来查找。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM