regex - 使用 RegEx 解析 Transact SQL

标签 regex tsql parsing text

我对 RegEx 非常缺乏经验 - 只是偶尔为我通过反复试验制定的编程任务直接使用 RegEx,但现在我遇到了一个严重的 regEx 挑战:

我有大约 970 个包含 Sybase Transact SQL 片段的文本文件,我需要在这些文件中找到每个表名并在表名前加上“#”。因此,我的选择是要么花一周时间手动编辑文件,要么使用 regEx(Python 3 或 Delphi-PRCE)编写脚本或应用程序来执行此任务。

规则如下:

表名总是大写 - 所以我只寻找大写 话;

列名、SQL 表达式和变量始终为小写;

SQL 关键字、表别名和列值可以是大写,但不能以“#”为前缀;

表别名(不能加前缀)在它们之前总是有空格,直到 前一个单词,这将是一个表名。

列值(不能有前缀)要么是数值,要么是包含在 引号。

这里是一些需要应用所有上述规则的示例文本:

update SYBASE_TABLE
set ok = convert(char(10),MB.limit)
from MOVE_BOOKS MB, PEOPLEPLACES PPL
where MB.move_num = PPL.move_num
AND PPL.mot_ind = 'B'
AND PPL.trade_type_ind = 'P'

到目前为止,我只做到了这一点:(不算太远...)

(?-i)[[:上:]]

任何帮助将不胜感激。 TIA,

最佳答案

这无法通过简单的正则表达式替换来实现。您将无法区分是表格、字符串文字还是注释的大写单词:

update TABLE set x='NOT_A_TABLE' where y='NOT TABLES EITHER' 
-- AND NO TABLES HERE AS WELL

编辑

您似乎认为确定一个单词是否在字符串文字中很容易,然后像这样考虑 SQL:

-- a quote: '
update TABLE set x=42 where y=666
-- another quote: '

update TABLE set x='not '' A '''' table' where y=666 

编辑二

好吧,我(痴迷地)强调了一个简单的正则表达式替换是不可行的事实。但我还没有提供(可能的)解决方案。您可以做的是基于几个不同的正则表达式创建某种“混合词法分析器”。您要做的是扫描输入文件并在每个字符的开头尝试匹配 commentstring literalkeyword,或 大写单词。如果这 4 个先前的模式都不匹配,则只消耗一个字符并重复该过程。

Python 中的一个小演示:

#!/usr/bin/env python
import re 

input = """
UPDATE SYBASE_TABLE
SET ok = convert(char(10),MB.limit) -- ignore me!
from MOVE_BOOKS MB, PEOPLEPLACES PPL
where MB.move_num = PPL.move_num
-- comment '
AND PPL.mot_ind = 'B '' X'
-- another comment '
AND PPL.trade_type_ind = 'P -- not a comment'
"""

regex = r"""(?xs)          # x = enable inline comments, s = enable DOT-ALL
  (--[^\r\n]*)             # [1] comments
  |                        # OR
  ('(?:''|[^\r\n'])*')     # [2] string literal
  |                        # OR
  (\b(?:AND|UPDATE|SET)\b) # [3] keywords
  |                        # OR
  ([A-Z][A-Z_]*)           # [4] capitalized word
  |                        # OR
  .                        # [5] fall through: matches any char
"""

output = ''

for m in re.finditer(regex, input): 
    # append a `#` if group(4) matched
    if m.group(4): output += '#'
    # append the matched text (any of the groups!)
    output +=  m.group()

# print the adjusted SQL
print output

产生:

UPDATE #SYBASE_TABLE
SET ok = convert(char(10),#MB.limit) -- ignore me!
from #MOVE_BOOKS #MB, #PEOPLEPLACES #PPL
where #MB.move_num = #PPL.move_num
-- comment '
AND #PPL.mot_ind = 'B '' X'
-- another comment '
AND #PPL.trade_type_ind = 'P -- not a comment'

这可能不是您想要的确切输出,但我希望该脚本足够简单,您可以根据自己的需要进行调整。

祝你好运。

关于regex - 使用 RegEx 解析 Transact SQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6157644/

相关文章:

sql - 同时向多个表中插入数据

java - Android - Java 解析 JSON

java - 使 Gson 在使用重复键解析 JSON 时抛出异常

c++ - 如何在 C++ 中使用 Boost::regex.hpp 库?

java - 特定格式的正则表达式

php - 正则表达式中 '\G' anchor 有什么用?

javascript - 使用 javascript 查找最后一次出现的字符

sql-server-2005 - 如何在SQL Server 2005中查找 View 的派生列类型?

sql - 表中身份列的显式值错误?

python - 有没有办法自动生成有效的算术表达式?