SQL LIKE查询:转义通配符

时间:2017-02-10 11:52:05

标签: java android sql sql-like

我有一个LIKE查询,我在Android Uri列上运行,其格式如下:

  1. 内容://com.android.externalstorage.documents/tree/0000-0000%3A_Issues/document/0000-0000%3A的 _Issues %2F的 ParentB
  2. 内容://com.android.externalstorage.documents/tree/0000-0000%3A_Issues/document/0000-0000%3A的 _Issues %2F的 ParentA
  3. 内容://com.android.externalstorage.documents/tree/0000-0000%3A_Issues/document/0000-0000%3A的 _Issues %2F的 ParentA %2F的 ParentB
  4. 这些对应于此文件树:

    _Issues
    |-ParentA
       |-ParentB
    |-ParentB
    

    我尝试了各种手动查询来逃避通配符,但我似乎无法获得正确的匹配。我将其简化为测试:

    select name from meta where parent LIKE '%_Issues%2FParentB%';
    
    1. 如果我逃脱'%':
    2.   

      %_问题\%2FParentB%'

      我根本没有得到任何结果。

      1. 如果我不逃避:
      2.   

        '%_问题%2FParentB%'

        我匹配浅的ParentB(所需)和嵌套的ParentB(不需要的)。我理解这是因为我允许问题和ParentB之间的任何内容与%。

        我不明白为什么查询1没有结果。我错过了什么?

        更新

        select name from meta where parent LIKE '%_Issues_2FParentB%';

        工作,注意' _',所以' \'显然没有逃脱这个数据库。显式地说明@GordonLinoff建议的转义字符在我的计算机上工作:

        select name from meta where parent LIKE '%_Issues\%2FParentB%' escape '\';

        现在想一想如何在Android中完成同样的工作......

2 个答案:

答案 0 :(得分:3)

是。最简单的方法是使用=,如果合适的话。

否则,LIKE语法包含转义字符。在您的示例中,$不会出现在任何地方,因此您可以执行以下操作:

where x like replace(y, '%', '$%') escape '$'

我相信在所有数据库中,默认值为\,因此您也可以这样做:

where x like replace(y, '%', '\%') 

但是,我更喜欢使用escape关键字,因此意图非常明确。

答案 1 :(得分:0)

为了扩展@GordonLinoff的答案,这里具体说明我是如何在Android中完成的,因为它稍微复杂一点:

/***
 * Creates a LIKE selection statement with all of the given arguments
 * @param column column to select on
 * @param likes array of arguments to select on
 * @param selectionArgs out: formatted arguments to pass to query
 * @param joiner joiner between individual LIKE
 * @param NOT true to set NOT LIKE for all selection arguments
 * @param argStart set a wildcard before every selection argument
 * @param argEnd set a wildcard after every selection argument
 * @return selection statement to query
 */
public static String createLike(String column, String[] likes, List<String> selectionArgs,
                                String joiner, boolean NOT,
                                @Nullable String argStart, @Nullable String argEnd,
                                @Nullable String escapeChar)
{
    StringBuilder selection = new StringBuilder();
    for (int i = 0; i < likes.length; i++)
    {
        if (i > 0) selection.append(joiner);

        if (argStart == null)
            argStart = "";
        if (argEnd == null)
            argEnd = "";

        selection.append(column)
                .append(NOT ? " NOT LIKE ?" : " LIKE ?");

        if (escapeChar != null)
            selection.append(" ESCAPE '\\'");

        String argument = likes[i];
        if (escapeChar != null)
            argument = argument.replace(escapeChar, "\\" + escapeChar);
        argument = argStart + argument + argEnd;
        selectionArgs.add(argument);
    }

    return selection.toString();
}

并致电:

DbUtil.createLike(Meta.PARENT,
                    filter.hiddenFolders.toArray(new String[filter.hiddenFolders.size()]),
                    selectionArgs,
                    AND,    // Requires AND so multiple hides don't negate each other
                    true,   // NOT
                    null,   // No wild to start, matches path exactly
                    "%",    // Wildcard end to match all children
                    "%"));  // Uri contain '%' which means match any so escape them