簡體   English   中英

Android SQLite - 加入兩個表並將結果呈現為列表

[英]Android SQLite - Joining two tables and render the result as list

我在sqlite中有兩個表:

projects
---id
---projectname

outlets
---id
---pid
---outletname
---status

我要渲染的projectnameoutletname其中status滿足條件。 我想將結果輸出呈現為列表。 我正在使用以下代碼:

private void showProjectStatus() {
        sqLiteDatabase = sqLiteHelper.getWritableDatabase();
        cursor = sqLiteDatabase.rawQuery("select  projectName, OutletName from projects inner join outlets on outlets.pid = projects.id where outlets.Status = 1"+"", null);
        //cursor = sqLiteDatabase.rawQuery("SELECT * FROM '"+SQLiteHelper.TABLE_NAME1+"' where Status = 1"+"", null);

上面的光標完美地工作。

        ID_Array.clear();
        ProjectName_Array.clear();
        OutletName_Array.clear();


        if (cursor != null && cursor.getCount() > 0) {
            if (cursor.moveToFirst()) {
                do {
                    ID_Array.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Table1_Column_ID)));
                    OutletName_Array.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Table1_Column_PID)));
                    ProjectName_Array.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Table1_Column_OutletName)));

我需要幫助來渲染上述內容。 如何將游標返回的值直接呈現為列表,而不是引用表中的實際列。

                } while (cursor.moveToNext());
            }
        } else {
            Toast.makeText( this, "No data to display!", Toast.LENGTH_SHORT ).show();
        }

我需要幫助來渲染上述內容。 如何將游標返回的值直接呈現為列表,而不是引用表中的實際列。

簡而言之,您不能使用標准 API(並且使用替代方法而不是 Cursor 似乎不會更困難,您將獲得結果集)。 所以一個 Cursor 就是你從中得到的結果。


查看您的代碼,當您試圖從 Cursor 獲取不存在的值時,您可能會感到困惑。

通過使用SELECT projectName, OutletName FROM .....你會得到一個 Cursor 像(2 列):-

在此處輸入圖片說明

你是說你想要在 Cursor 中有兩列,他們的名字是projectNameOutletName 嘗試使用cursor.getColumnIndex(SQLiteHelper.Table1_Column_ID)將導致返回 -1(在 Cursor 中找不到列名)並且 Cursor 中沒有偏移量為 -1 的列。

PID 也是如此。

如果除了 outletName 和 projectName 列之外還需要 ID 和 PID 列,則將查詢更改為:-

cursor = sqLiteDatabase.rawQuery("select  projects.id,pid,projectName, OutletName from projects inner join outlets on outlets.pid = projects.id where outlets.Status = 1"+"", null).

在這種情況下,光標將類似於(4 列):-

在此處輸入圖片說明

假設您想要所有四列,請在單獨的數組中進行檢查,然后可能會考慮:-

private void showProjectStatus() {

    ID_Array.clear();
    ProjectName_Array.clear();
    OutletName_Array.clear();

    sqLiteDatabase = sqLiteHelper.getWritableDatabase();
    Cursor cursor = sqliteDatabase.query(
        "projects inner join outlets on outlets.pid = projects.id",
        new String[]{
            "projects." + SQLiteHelper.Table1_Column_ID,
            SQLiteHelper.Table1_Column_PID,
            "projectName", //<<<<< defined value not used as unknown
            SQLiteHelper.Table1_Column_OutletName
        },
        "outlets.Status=1",
        null,null,null,null
    );
    while (cursor.moveToNext()) {
        ID_Array.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Table1_Column_ID));
        ProjectName_Array.add(cursor.getString(cursor.getColumnIndex("projectName"));
        OutletName_Array.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Table1_Column_OutletName));
    }
    cursor.close()
}
  • 注意 SQLiteHelper.Table1_Column_ProjectName 或 SQLiteHelper.Table1_Column_projectName 或任何可能定義為尚未使用的值。
    • 應該注意的是 Cursor getColumnIndex 有一個錯誤,因為它不依賴於大小寫。 因此,列名應該與查詢中使用的列名完全相同。
  • 檢查從任何 SQLiteDatabase 方法返回的 Cursor 是否為空是沒有用的。 將始終返回有效的 Cursor。 如果沒有行,則光標的計數將為 0,並且任何移動第一行 (-1) 之前以外的位置的嘗試都將返回 false(因此 while 循環的工作原理)。
  • 一般推薦使用查詢便捷方法而不是rawQuery方法(但上面兩種都可以使用)。

注意以上代碼為原則性代碼; 它尚未運行或測試,因此可能包含一些錯誤。

但是,當您似乎想要驅動ListView 時,如果您使用CursorAdapter的子類,則適配器可以代表您完成大部分工作。

SimpleCursorAdapter ,這樣的適配器,非常靈活,允許布局顯示多列。 CursorAdapters 的顯着優點之一是 ItemSelection (Click LongClick) 事件將id傳遞給方法(對於非 CursorAdapters,傳遞的值是作為 long 的位置)。 要做到這一點,游標必須有一個特別名為_id的列( Base.Columns._ID ),並且該列應該是 rowid 的別名(即表中的列是使用INTEGER PRIMARY KEY (可選地使用 AUTOINCREMENT)定義的)。


SimpleCursorAdapter 示例

SQLiteHelper.java

public class SQLiteHelper extends SQLiteOpenHelper {

    public static final String DBNAME = "mydb";
    public static final int DBVERSION = 1;
    public static final String TABLE_NAME1 = "projects";
    public static final String TABLE_NAME2 = "outlets";

    public static final String TABLE1_COLUMN_ID = BaseColumns._ID;
    public static final String TABLE1_COLUMN_PROJECTNAME = "projectname";
    public static final String TABLE2_COLUMN_ID = BaseColumns._ID;
    public static final String TABLE2_COLUMN_PID = "pid";
    public static final String TABLE2_COLUMN_OUTLETNAME = "outletname";
    public static final String TABLE2_COLUMN_STATUS = "status";

    public SQLiteHelper(Context context) {
        super(context, DBNAME, null, DBVERSION);
    }

    @Override
    public void onConfigure(SQLiteDatabase db) {
        super.onConfigure(db);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String createProjectsTableSQL =
                "CREATE TABLE IF NOT EXISTS " + TABLE_NAME1 +
                        "(" +
                        TABLE1_COLUMN_ID + " INTEGER PRIMARY KEY," +
                        TABLE1_COLUMN_PROJECTNAME + " TEXT" +
                        ")";
        String createOutletsTableSQL =
                "CREATE TABLE IF NOT EXISTS " + TABLE_NAME2 +
                        "(" +
                        TABLE2_COLUMN_ID + " INTEGER PRIMARY KEY," +
                        TABLE2_COLUMN_PID + " INTEGER REFERENCES " + TABLE_NAME1 + "(" +
                        TABLE1_COLUMN_ID +
                        ") ON DELETE CASCADE ON UPDATE CASCADE, " +
                        TABLE2_COLUMN_OUTLETNAME + " TEXT," +
                        TABLE2_COLUMN_STATUS + " INTEGER" +
                        ")";
        db.execSQL(createProjectsTableSQL);
        db.execSQL(createOutletsTableSQL);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public long addProject(String projectName) {
        ContentValues cv = new ContentValues();
        cv.put(TABLE1_COLUMN_PROJECTNAME,projectName);
        return this.getWritableDatabase().insert(TABLE_NAME1,null,cv);
    }

    public long addOutlet(String outletName, long projectId, boolean status) {
        ContentValues cv = new ContentValues();
        cv.put(TABLE2_COLUMN_OUTLETNAME,outletName);
        cv.put(TABLE2_COLUMN_PID,projectId);
        cv.put(TABLE2_COLUMN_STATUS,status);
        return this.getWritableDatabase().insert(TABLE_NAME2,null,cv);
    }

    public Cursor getProjectsWithOutletsWithStatusOn() {
        return this.getWritableDatabase().query(
                TABLE_NAME1 + " INNER JOIN "
                        + TABLE_NAME2 + " ON " +
                        TABLE_NAME1 + "." + TABLE1_COLUMN_ID + "=" +
                        TABLE_NAME2 + "." + TABLE2_COLUMN_PID,
                new String[]{
                        TABLE_NAME1 + "." + TABLE1_COLUMN_ID,
                        TABLE2_COLUMN_PID,
                        TABLE1_COLUMN_PROJECTNAME,
                        TABLE2_COLUMN_OUTLETNAME,
                        TABLE2_COLUMN_STATUS //? optional as will always be 1
                },
                TABLE2_COLUMN_STATUS + "=1",
                null,null,null,null
        );
    }
}

主活動.java

public class MainActivity extends AppCompatActivity {

    SQLiteHelper mHelper;
    Cursor mCursor;
    SimpleCursorAdapter mAdapter;
    ListView mListView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mListView = this.findViewById(R.id.listview);
        mHelper = new SQLiteHelper(this);
        addSomeDataIfNone();
        manageListView();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mCursor.close(); // close the Cursor (more important for invoked activities)
    }

    @Override
    protected void onResume() {
        super.onResume();
        manageListView(); // refresh Listview when resuming activity as data may have changed
    }

    private void addSomeDataIfNone() {
        if (DatabaseUtils.queryNumEntries(mHelper.getWritableDatabase(),SQLiteHelper.TABLE_NAME1) < 1) {
            long idp1 = mHelper.addProject("Project001");
            mHelper.addOutlet("OutletP1001",idp1,false);
            mHelper.addOutlet("OutletP1002",idp1,true);
            mHelper.addOutlet("Outletp1003",idp1,true);

            long idp2 = mHelper.addProject("Prject002");
            mHelper.addOutlet("OutletP2001",idp2,true);
            mHelper.addOutlet("OutletP2002",idp2,false);
        }
    }

    private void manageListView() {
        mCursor = mHelper.getProjectsWithOutletsWithStatusOn();
        if (mAdapter == null) {
            mAdapter = new SimpleCursorAdapter(
                    this,
                    android.R.layout.simple_list_item_2,
                    mCursor,
                    new String[]{
                            SQLiteHelper.TABLE1_COLUMN_PROJECTNAME,
                            SQLiteHelper.TABLE2_COLUMN_OUTLETNAME
                    },
                    new int[]{
                            android.R.id.text1,
                            android.R.id.text2
                    },
                    0
            );
            mListView.setAdapter(mAdapter);
            mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Toast.makeText(view.getContext(),
                            "You clicked " +
                                    "Project = " + mCursor.getString(mCursor.getColumnIndex(SQLiteHelper.TABLE1_COLUMN_PROJECTNAME)) +
                                    " Outlet = " + mCursor.getString(mCursor.getColumnIndex(SQLiteHelper.TABLE2_COLUMN_OUTLETNAME)) +
                                    " Project ID = " + mCursor.getString(mCursor.getColumnIndex(SQLiteHelper.TABLE1_COLUMN_ID)) +
                                    " Outlet Status = " + (mCursor.getInt(mCursor.getColumnIndex(SQLiteHelper.TABLE2_COLUMN_STATUS))> 0)
                            ,
                            Toast.LENGTH_SHORT).show();
                }
            });
        } else {
            mAdapter.swapCursor(mCursor);
        }
    }
}

結果

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM