我一直在努力寻找一个正则表达式,仅当它们不在括号内时才帮助我匹配3个不同的字符串,但是到目前为止,我仅设法将其匹配在括号旁边,并且在这种特定情况下不适合我。
为澄清起见,我需要匹配任何括号中都不包含的字符串“ HAVING”,“ ORDER BY”和“ GROUP BY”,无论括号中包含的字符串不仅仅是字符串。
在这种情况下:
Select *
from some_table
group by something;
应该匹配,但是:
Select *
from(
Select *
from some_other_table
group by something_else
)
或
Select this, and_this
from(
Select *
from some_other_table
having some_condition
)
不应该。
我不是Javascript正则表达式的专家,因此,您能给我的任何帮助将不胜感激。
答案 0 :(得分:1)
我假设您想检查给定的SQL查询是否在顶层(不在子查询中)包含HAVING
,ORDER BY
或GROUP BY
。
由于括号和单词都可以包含在字符串文字('...'
),带引号的标识符("..."
)和注释(-- ...
)中,这使情况变得复杂。 / p>
在下面的代码中,我假设这就是所有可能“出错”的东西(即没有其他引用结构),并且没有带引号的字符是特殊的(特别是,\
的使用没有区别)
想法:
“删除”一词的意思是“用空格代替”,因为否则可能会在以前没有的地方创建新令牌(例如,hav(...)IN"asdf"g
会变成havINg
,如果用括号/引用的部分被替换为空)。
实施:
function contains_groupy_bits(sql) {
sql = sql.replace(/'[^']*'|"[^"]*"|--[^\n]*/g, ' ');
let tmp;
while ((tmp = sql.replace(/\([^()]*\)/g, ' ')) !== sql) {
sql = tmp;
}
return /\b(?:having|order\s+by|group\s+by)\b/i.test(sql);
}
const examples = [
`Select *
from some_table
group by something;`,
`Select *
from(
Select *
from some_other_table
group by something_else
)`,
`Select this, and_this
from(
Select *
from some_other_table
having some_condition
)`,
`select name, count(*) from things
where mark = '('
group by name -- )`,
];
for (const ex of examples) {
console.log("'" + ex + "': " + contains_groupy_bits(ex));
}