2012-12-09 156 views
1

我试图执行具有各种条件查询和我得到一个例外。复杂的SQLite查询给

bind or column index out of range 

这是来自ContentProvider的查询。

@Override 
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); 
    int uriType = sURIMatcher.match(uri); 
    switch (uriType) { 
    case RESPONSEVIEW2_SELECTION_10: 
     queryBuilder.setTables(RESPONSES_VIEW); 
     String activeUserKey = getActiveUserId();; 
     String outerSelection = 
       "(((" + PeerCreatedDataColumns.SHARED + "=" + "" + trueId + "" + ") OR " 
       + "(" + PeerCreatedDataColumns.AUTHORHASH + "=" + "'" + activeUserKey + "'" + ")) AND (" 
       + "(" + ResponsesColumns.PRIMARYMATCH + "= '*'" + ") OR " 
            // '*' is defined by the program, hopefully not in conflict with anything built-in 
       + "(" + ResponsesColumns.PRIMARYMATCH + " like '?') OR " 
       + "(" + ResponsesColumns.PRIMARYMATCH + " like '" + selectionArgs[0] + "%') OR " 
       + "(" + ResponsesColumns.PRIMARYMATCH + " like '%" + selectionArgs[0] + "') OR " 
       + "(" + ResponsesColumns.PRIMARYMATCH + " like '%" + selectionArgs[0] + "%'" + ")))"; 
     Log.d(DEBUG_TAG, "query " + outerSelection); 
     Cursor cursor10 = queryBuilder.query(mDB.getReadableDatabase(), projection, outerSelection, selectionArgs, 
       null, null, sortOrder); 
     cursor10.setNotificationUri(getContext().getContentResolver(), uri); 
     Log.e(DEBUG_TAG, "responses_view2 should have better search function"); 
     return cursor10; 
    case ROW_SELECTION_11: 
     queryBuilder.setTables(RESPONSES_VIEW); 
     Log.e(DEBUG_TAG, "responses_view2 should have better search function"); 
     queryBuilder.appendWhere(PeerDatabase._ID + "=" + uri.getLastPathSegment()); 
     Cursor cursor11 = queryBuilder.query(mDB.getReadableDatabase(), projection, selection, selectionArgs, null, 
       null, sortOrder); 
     cursor11.setNotificationUri(getContext().getContentResolver(), uri); 
     return cursor11; 
    ... 
    } 
} 

这里是光标加载器,它似乎是错误的来源。

public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
    if (search == null) { 
     return null; 
    } else { 
     String[] selectArgs = { search }; 
     return new CursorLoader(getActivity(), table, createProjection, "?", selectArgs, null); 
    } 
} 

下面是完整的错误:

12-09 18:25:54.509: E/AndroidRuntime(12461): FATAL EXCEPTION: ModernAsyncTask #2 
12-09 18:25:54.509: E/AndroidRuntime(12461): java.lang.RuntimeException: An error occured while executing doInBackground() 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.ModernAsyncTask$3.done(ModernAsyncTask.java:137) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.FutureTask.setException(FutureTask.java:125) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.lang.Thread.run(Thread.java:1019) 
12-09 18:25:54.509: E/AndroidRuntime(12461): Caused by: android.database.sqlite.SQLiteException: bind or column index out of range: handle 0x28bd08 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteProgram.native_bind_string(Native Method) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteProgram.bindString(SQLiteProgram.java:244) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteQuery.bindString(SQLiteQuery.java:185) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:48) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1356) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:330) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.database.sqlite.SQLiteQueryBuilder.query(SQLiteQueryBuilder.java:280) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at org.anuvar.plana.m.provider.PeerDataProvider.query(PeerDataProvider.java:285) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.content.ContentProvider$Transport.query(ContentProvider.java:187) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.content.ContentResolver.query(ContentResolver.java:262) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:49) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:35) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:240) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:51) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:40) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:123) 
12-09 18:25:54.509: E/AndroidRuntime(12461): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306) 
12-09 18:25:54.509: E/AndroidRuntime(12461): ... 4 more 

我试图找出异常,但请让我知道是否有更好的方式来查询数据。

回答

4

selection参数中的?的数量必须与selectionArgs参数中的字符串数量相匹配。 LogCat表明这些计数不匹配,但我们很难分辨...

我发现了这个问题,请不要将?用引号括起来,否则你就会从字面上寻找一个问号。这是不正确的:

" like '?') OR " 

而是使用:

" like ?) OR " 

如果search是用户输入的,你应该保护自己免受SQL注入攻击:

+ "(" + ResponsesColumns.PRIMARYMATCH + " like ?) OR " 
+ "(" + ResponsesColumns.PRIMARYMATCH + " like ?) OR " 
+ "(" + ResponsesColumns.PRIMARYMATCH + " like ?) OR " 
+ "(" + ResponsesColumns.PRIMARYMATCH + " like ?)))"; 

,并创建一个新的selectionArgs参数是这样的:

String search = selectionArgs[0]; 
String[] matchArgs = { search, search + "%", "%" + search, "%" + search + "%" }; 
Cursor cursor10 = queryBuilder.query(mDB.getReadableDatabase(), projection, 
      outerSelection, matchArgs, null, null, sortOrder); 
+0

感谢。我把所有的东西放在一起时遇到了一些麻烦。这好多了。 – KrisC