Android:ContactsContract查询,需要更高级的选择字符串

发布于 2024-11-15 23:57:46 字数 1236 浏览 2 评论 0原文

我正在尝试查询 ContactContract ContentProvider 并获取以下算法将获取的数据:

given a phone number (input), return record...:
if(recordNumber has 7 digits) {
    if('%recordNumber' LIKE 'inputNumber') {
        return recordDisplayName;
    }
} else if(recordNumber has 10 digits) {
    if('recordNumber' LIKE '%inputNumber') {
        return recordDisplayName;
    }
} else if(recordNumber == inputNumber) {
    return recordDisplayName;
}

这在查询调用中有效:

ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE ?"

但我需要更多类似这样的内容:

"('%" + ContactsContract.CommonDataKinds.Phone.NUMBER+"' LIKE '?' AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=7) OR ('" + ContactsContract.CommonDataKinds.Phone.NUMBER+"' LIKE '%?' AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=10)"

但每次使用时都会出现运行时错误带单引号的查询。例如,将:更改

ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE ?"

为:

ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE '?'"

会导致运行时错误“绑定或列索引超出范围...”。所以这一定是一些语法错误......对吗? ContentProvider 查询的正确语法是什么和/或如何从 ContactsContract 获取我想要的结果集?

i'm trying to query the ContactContract ContentProvider and obtain the data that the following algorithm would obtain:

given a phone number (input), return record...:
if(recordNumber has 7 digits) {
    if('%recordNumber' LIKE 'inputNumber') {
        return recordDisplayName;
    }
} else if(recordNumber has 10 digits) {
    if('recordNumber' LIKE '%inputNumber') {
        return recordDisplayName;
    }
} else if(recordNumber == inputNumber) {
    return recordDisplayName;
}

this works in the query call:

ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE ?"

but i need something more like this:

"('%" + ContactsContract.CommonDataKinds.Phone.NUMBER+"' LIKE '?' AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=7) OR ('" + ContactsContract.CommonDataKinds.Phone.NUMBER+"' LIKE '%?' AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=10)"

but i get runtime errors everytime i use a query with a single quote. for instance, changing:

ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE ?"

to:

ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE '?'"

causes a runtime error "bind or column index out of range...". so this has to be some syntax error... right? what's the proper syntax for ContentProvider queries and/or how can i get the result set i'm after from ContactsContract?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

够运 2024-11-22 23:57:46

对 ContentProvider 的查询有点不同,而且格式要求不高。对于 ContentProvider,如果要使用“%”作为通配符,则必须将“%”连接到 WHERE 子句中的参数,而不是作为子句本身的一部分。

正确:

Cursor cursor = getContentResolver().query(
    ContactsContract.Data.CONTENT_URI, 
    null, 
    ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE ?",
    new String[] { "%"+number },
    null);

不正确:

Cursor cursor = getContentResolver().query(
    ContactsContract.Data.CONTENT_URI, 
    null, 
    ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE %?", 
    new String[] { number }, 
    null);

上面的“不正确”语句实际上对于 SQLite 查询是完全合法的,只是对于 ContentProvider 查询不合法。

此外,单引号是 ContentProvider 查询的 WHERE 子句(或连接到所述子句中的参数)中的语法错误。

最终代码:

if(number.length()==7) {
    cursor = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, 
        ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE ?",
        //"('%" + ContactsContract.CommonDataKinds.Phone.NUMBER+"' LIKE '?' AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=7) OR ('" + ContactsContract.CommonDataKinds.Phone.NUMBER+"' LIKE '%?' AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=10)",
        new String[] { "%"+number },
        null);
} else if(number.length()==10) {
    cursor = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, 
        "("+ContactsContract.CommonDataKinds.Phone.NUMBER+"=? AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=7) OR ("+ContactsContract.CommonDataKinds.Phone.NUMBER+"=? AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=10)",
        new String[] { number.substring(3), number },
        null);
} else {
    cursor = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, 
        ContactsContract.CommonDataKinds.Phone.NUMBER+"=?",
        new String[] { number },
        null);
}

此代码将检索与相关号码匹配的电话号码的匹配显示名称。
- 如果号码是 7 位数字,我们会检索电话号码最后 7 位数字(删除破折号和特殊字符,“*”和“#”除外,因为它们是有效的电话字符)与中的 7 位数字匹配的所有记录问题。
- 如果数字是 10 位数字,则返回包含 7 位数字并匹配最后 7 个字符的任何记录,或者在记录有 10 位数字的情况下包含完全匹配的记录。
- 如果相关号码既不是 7 也不是 10 位数字,则需要完全匹配。

queries to ContentProviders are a little different, and unforgiving on the formatting. for ContentProviders, if you want to use '%' as a wildcard character, the '%' must be concatenated to the argument in the WHERE clause, rather than as a part of the clause itself.

correct:

Cursor cursor = getContentResolver().query(
    ContactsContract.Data.CONTENT_URI, 
    null, 
    ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE ?",
    new String[] { "%"+number },
    null);

incorrect:

Cursor cursor = getContentResolver().query(
    ContactsContract.Data.CONTENT_URI, 
    null, 
    ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE %?", 
    new String[] { number }, 
    null);

the above "incorrect" statement is actually completely legal for SQLite queries, just not for ContentProvider queries.

in addition, single quotes are a syntax error in a ContentProvider query's WHERE clause (or concatenated to the args in said clause).

final code:

if(number.length()==7) {
    cursor = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, 
        ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE ?",
        //"('%" + ContactsContract.CommonDataKinds.Phone.NUMBER+"' LIKE '?' AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=7) OR ('" + ContactsContract.CommonDataKinds.Phone.NUMBER+"' LIKE '%?' AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=10)",
        new String[] { "%"+number },
        null);
} else if(number.length()==10) {
    cursor = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, 
        "("+ContactsContract.CommonDataKinds.Phone.NUMBER+"=? AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=7) OR ("+ContactsContract.CommonDataKinds.Phone.NUMBER+"=? AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=10)",
        new String[] { number.substring(3), number },
        null);
} else {
    cursor = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, 
        ContactsContract.CommonDataKinds.Phone.NUMBER+"=?",
        new String[] { number },
        null);
}

this code will retrieve matching display names for phone numbers that match the number in question.
- if the number is a 7 digit number, we retrieve any records who's phone numbers last 7 digits (dashes and special characters stripped, except "*" and "#" since they are valid phone characters) match the 7 digits of the number in question.
- if the number is a 10 digit number, it returns any records that either contain 7 digits and match the last 7 characters, or contain an exact match in the case that the record has 10 digits.
- if the number in question has neither 7 nor 10 digits, an exact match is necessary.

Smile简单爱 2024-11-22 23:57:46

使用 ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER 而不是 ContactsContract.CommonDataKinds.Phone.NUMBER

Use ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER instead of ContactsContract.CommonDataKinds.Phone.NUMBER

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文