2011-06-15 23 views
3

我试图查询ContactContract的ContentProvider并获得以下算法将获取的数据:安卓:ContactsContract查询,需要更先进的选择字符串

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得到结果集?

回答

8

对ContentProvider的查询有点不同,并且对格式化不予考虑。对于ContentProviders,如果要将'%'用作通配符,则必须将'%'连接到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位数字,则需要完全匹配。

+0

我有这个(种)查询一个问题,直到我注意到Data.CONTENT_URI的使用,而不是CONTENT_FILTER_URI。我刚刚意识到我的语义误解。谢谢你的提示。 – Shoham 2014-08-21 12:20:46

0

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