2011-04-26 4 views
6

Android에서 SQLite를 오랫동안 사용해 왔지만 조인 테이블 작업을 처음 수행했습니다. 나는 하루 종일 그것에 종사하고 있기 때문에 나는 그것에 대해 완전히 좌절하고있다.SQLite : 테이블을 조인하고 SimpleCursorAdapter를 사용하여 커서를 표시하는 방법

이제 2 개의 테이블, FTSProfile 및 FTSCell이 있으며 LEFT JOIN과 함께 공통 키 A를 사용하여 결합하려고합니다. 그래서 나는 원하는 것을 수행하기 위해 일련의 코드 인 ContentProvider와 Database를 구현했다. 데이터베이스에서 SQLiteQueryBuilder를 사용하여 쿼리를 작성하고 커서를 가져옵니다. 내가 사용 :

SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); 
    builder.setTables(FTS_VIRTUAL_TABLE_PROFILE+" LEFT JOIN "+FTS_VIRTUAL_TABLE_CELL+" ON "+FTS_VIRTUAL_TABLE_CELL+"."+Database.KEY_CID+"="+FTS_VIRTUAL_TABLE_PROFILE+"."+Database.KEY_CELL_ID); 
    builder.setProjectionMap(mColumnMap_CombinedTable); 

을 내 해시 맵과 같은 것입니다 :

HashMap<String,String> map = new HashMap<String,String>(); 
     for (String key: KEYS_PROFILE) map.put(key, FTS_VIRTUAL_TABLE_PROFILE+"."+key); 
     for (String key: KEYS_CELL) map.put(key, FTS_VIRTUAL_TABLE_CELL+"."+key); 
     map.put(BaseColumns._ID, BaseColumns._ID); 
     map.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "rowid AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID); 
     map.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID, "rowid AS " + SearchManager.SUGGEST_COLUMN_SHORTCUT_ID); 

그리고 난이 프로그램을 실행하고 결과를 목록을 열려고하면 다음, 내가 얻을 내가 가진 SQLiteException: no such column: _id...

해결 방법은 없지만 실제로 어떻게 제거 할 수 있는지 알고 싶습니다. 누구든지 도와 줄 수 있습니까?

답변

6

하 재미있는 질문. 나는 30 분 전에 똑같은 것을보고 있었다.;). Android 기본 연락처 앱에서 사용한 예를 따라해볼 수 있습니다. 그들은이 코드 조각을 사용하는 결과를 조회 할 때

http://www.google.com/codesearch/p?hl=en#cbQwy62oRIQ/src/com/android/providers/contacts/ContactsProvider2.java&q=ContactsProvider.java&d=5

그들은 그런 다음 인터페이스

private interface DataContactsQuery { 
     public static final String TABLE = "data " 
       + "JOIN raw_contacts ON (data.raw_contact_id = raw_contacts._id) " 
       + "JOIN contacts ON (raw_contacts.contact_id = contacts._id)"; 

     public static final String[] PROJECTION = new String[] { 
      RawContactsColumns.CONCRETE_ID, 
      DataColumns.CONCRETE_ID, 
      ContactsColumns.CONCRETE_ID 
     }; 

     public static final int RAW_CONTACT_ID = 0; 
     public static final int DATA_ID = 1; 
     public static final int CONTACT_ID = 2; 
    } 

을 선언합니다.

Cursor cursor = null; 
     try { 
      cursor = mDb.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION, 
        mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null, 
        Contacts.IN_VISIBLE_GROUP + " DESC, " + Data.RAW_CONTACT_ID); 
      if (cursor.moveToFirst()) { 
       dataId = cursor.getLong(DataContactsQuery.DATA_ID); 
       rawContactId = cursor.getLong(DataContactsQuery.RAW_CONTACT_ID); 
       contactId = cursor.getLong(DataContactsQuery.CONTACT_ID); 
      } else { 
       // No contact found, return a null URI 
       return -1; 
      } 
     } finally { 
      if (cursor != null) { 
       cursor.close(); 
      } 
     } 

이 정보가 유용할까요?

+1

그러나 SimpleCursorAdapter에는 데이터를 할당하기위한 "_id"(BaseColumns._ID) 필드가 필요합니다. 따라서 데이터베이스 생성 중에 그러한 필드를 선언하지 않으면 테이블에 조인 할 수 없습니다. 내가 생각하고있는 것은, 내가 구현 한 메소드를 사용하여 테이블에 가입 한 후 어떻게 "_id"컬럼을 만들 수 있는가이다. –

+0

링크가 작동하지 않습니다. 몇 가지 질문입니다.당신은 어떻게 mDB를 얻습니까? 문서화되지 않았으므로 연락처 데이터베이스를 활용하는 것이 쉽지 않은 것처럼 보입니다. 그리고 mSB는 무엇입니까? – rycfung

+0

mDB가 SQLiteDatabase 인스턴스입니다. mSB는 StringBuilder입니다. 릴리스의 소스 코드를 되돌아보아야했습니다. –

1

데이터베이스에 VIEW을 만드는 것은 어떻습니까? 이것이 빈번한 쿼리 인 경우 뷰로 표시하고 조인 설정에 많은 혼란을 피할 수 있으며 선택 기준에 대해 걱정할 필요가 없습니다. 조인을 연속 SQL로 작성할 수 있다면 뷰를 작성한 다음이를 사용할 수 있어야합니다.

코드에 나타나는 문제는 _id (CursorAdapter에 필요)이라는 열을 선택하려고했으나 해당 열이 존재하지 않는 것 같습니다. BaseColumns._IDBaseColumns._ID으로 매핑 하겠지만, 이는 단지 상수 일 뿐이며 데이터베이스에 열 _id이없는 경우 표시되는 오류가 발생합니다.

CREATE VIEW FooBar AS 
    SELECT Foo.field1 AS FooField1, 
      Foo.field2 AS FooField2, 
      Bar.field1 AS BarField1, 
      Bar.field2 AS BarField2, 
      (Foo._id * 1000000000) + Bar._id AS _id 
    FROM Foo LEFT JOIN Bar ON Foo.Field1 = Bar.Field2; 

(Foo._id * 1000000000) + Bar._id AS _id 당신이 어댑터로 이것을 사용하는 경우 당신이 필요합니다 뷰에 의해 반환 된 행에 대한 고유 _id을 합성하는 빠르고 더러운, 아마도 고통스럽게 잘못된 방법이라고. 또한 읽기 전용이라는 단점이 있습니다. VIEW은 업데이트 할 수 없습니다.

VIEW을 얻은 후에는 SELECT처럼 테이블 자체로 처리 할 수 ​​있습니다. 즉, SELECT * FROM FooBar WHERE BarField1 > 10;

+0

제안 해 주셔서 감사합니다.] 이제는 내 문제가 " _id "내 조인 테이블에. 원래 2 테이블에 "_id"라는 이름의 열이 없으며 어떻게 든 프로젝션 맵에서 쿼리를 수행하므로 데이터베이스를 만들지 않더라도 커서를 DataAdapter에 공급할 수 있습니다. 그러나 조인을 한 후 _id 필드가 사라지고 다시 추가 할 방법을 찾고 있습니다. –

+0

Ok ... 조인 된 행에 전체 결과 집합에서 고유 한 정수 필드가 포함되어 있으면 투영 맵을 _id로 반환합니다. 'map.put ("myUniqueNumericField", BaseColumns._ID);'그러면 쿼리가 해당 열의 레이블을 _id로 지정하여 CursorAdapter가 작동하도록합니다. –

+0

Whups! 'map.put (BaseColumns._ID, "myUniqueNumericField");'메모리에서 게시 할 때의 위험 ... –

관련 문제