从SQL查询中检索参数

时间:2019-01-06 15:26:03

标签: java sql regex

我想从SQL查询中获取所有参数。在这种情况下,查询是数组中的纯字符串。 我有很多成对的查询,格式如下:

SELECT * FROM my_table t WHERE (t.attr1 = ? AND t.attr2 = ?) OR t.attr3= ?

其对是(其中包含我要检索的参数):

SELECT * FROM my_table t WHERE (t.attr1 = 3 AND t.attr2 = 'str') OR t.attr3= 4

所以输出将是:

3, 'str' and 4.

如何基于此对检索这些值?

我在Java中尝试使用正则表达式,但是会很困难,因为?可以是数字 字符串等等。该字符串可以包含另一个?这是字符串的一部分,例如:

UPDATE my_table SET attr2 = ? WHERE attr5 = ?
UPDATE my_table SET attr2 = 'Is it true?' WHERE attr5 = 'What is it?'

2 个答案:

答案 0 :(得分:1)

这是一个使用基本Java regex模式匹配的工作脚本。它通过执行两次比赛来工作。首先,它查找分配给?位置占位符的每列/别名。然后,对于每个匹配的列/别名,它将对具有绑定值的查询字符串进行第二次查找。

String query1 = "SELECT * FROM my_table t WHERE (t.attr1 = ? AND t.attr2 = ?) OR t.attr3= ?";
String query2 = "SELECT * FROM my_table t WHERE (t.attr1 = 3 AND t.attr2 = 'str') OR t.attr3= 4";

String p1 = "([\\w.]+)\\s*=\\s*\\?(?=(([^']*'){2})*[^']*$)";
Pattern r1 = Pattern.compile(p1);
Matcher m1 = r1.matcher(query1);

// for each matching column/alias with a placeholder
while (m1.find()) {
    String p2 = m1.group(1) + "\\s*=\\s*([\\w.']+)";
    Pattern r2 = Pattern.compile(p2);
    Matcher m2 = r2.matcher(query2);

    // if we find it in the second query string, then print the value
    if (m2.find()) {
        System.out.println("Column: " + m1.group(1) + " has parameter value: " + m2.group(1));
    }
}

Column: t.attr1 has parameter value: 3
Column: t.attr2 has parameter value: 'str'
Column: t.attr3 has parameter value: 4

请注意,我在这里做一些假设,包括匹配的列将只包含单词字符(\w)和点,并且匹配的值将仅包含单词字符和单引号(对于字符串文字)。上面的代码可能会在很多情况下失败,这还取决于您的数据库及其特定语法。我正在为您提出的问题提供立即的解决方案,并作为一种可行的通用方法。

答案 1 :(得分:1)

您可以使用此方法来执行此操作,即在查询中将每个?替换为(.*),然后根据它创建一个模式。然后应用另一对具有实际值的字符串,然后打印出将根据查询字符串中存在的?动态创建的所有组中的值。

这是同样的Java代码。

// This map stores your paired queries where key stores the placeholder query and value stores the query having actual parameters.
Map<String, String> pairMap = new HashMap<>();
pairMap.put("SELECT * FROM my_table t WHERE (t.attr1 = ? AND t.attr2 = ?) OR t.attr3= ?", "SELECT * FROM my_table t WHERE (t.attr1 = 3 AND t.attr2 = 'str') OR t.attr3= 4");
pairMap.put("UPDATE my_table SET attr2 = ? WHERE attr5 = ?", "UPDATE my_table SET attr2 = 'Is it true?' WHERE attr5 = 'What is it?'");

pairMap.forEach((k,v) -> {
    System.out.println("For query: "+k);
    k = k.replaceAll("([*+^$()\\[\\]{}])", "\\\\$1"); // this escapes all the characters that have special meaning in regex so they get treated as literal characters
    k = k.replaceAll("\\?", "(.*)");

    Pattern p = Pattern.compile(k);
    Matcher m = p.matcher(v);
    if (m.matches()) {
        for (int i=0;i<m.groupCount();i++) {
            System.out.println(m.group(i+1));
        }
    } else {
        System.out.println("Didn't match");
    }
    System.out.println();
});

哪些印刷品

For query: SELECT * FROM my_table t WHERE (t.attr1 = ? AND t.attr2 = ?) OR t.attr3= ?
3
'str'
4

For query: UPDATE my_table SET attr2 = ? WHERE attr5 = ?
'Is it true?'
'What is it?'

如您所见,该代码适用于查询字符串中占位符?的任何变量值,并打印配对查询中存在的所有具有实际值的值。