如何插入到多对多的关系中。 SQLite的

时间:2017-08-02 01:13:17

标签: android sql sqlite android-sqlite

在我的Android应用程序中,我有一个SQLite数据库。这种结构:

PrivateList(idList INTEGER PRIMARY KEY, name TEXT, creationDate TEXT, active INTEGER, deactivationDate TEXT);

PrivateProduct (idProduct INTEGER PRIMARY KEY, description TEXT, quantity INTEGER, active INTEGER, additionDate TEXT);

List_Product(idList INTEGER NOT NULL, idProduct INTEGER NOT NULL, PRIMARY KEY (idList, idProduct), FOREIGN KEY(idList) REFERENCES PrivateList(idList), FOREIGN KEY(idProduct) REFERENCES PrivateProduct(idProduct));

我有一个自动生成器列表和使用for的元素来试用该应用程序:

localDB = new LocalDB(this, "localBD", null, 1);
        SQLiteDatabase sqLiteDatabase = localDB.getWritableDatabase();

        if (sqLiteDatabase != null){

            for (int i = 0; i < 10; i++){
                String a = "List" + i;
                String b = "Product" + i;
                Log.i("execfor", "INSERT INTO PrivateList (name, creationDate, active, deactivationDate) " + " VALUES ('" + a + "', CURRENT_TIMESTAMP, 1, null);");
                sqLiteDatabase.execSQL("INSERT INTO PrivateList (name, creationDate, active, deactivationDate) " + " VALUES ('" + a + "', CURRENT_TIMESTAMP, 1, null);");
                sqLiteDatabase.execSQL("INSERT INTO PrivateProduct (description, quantity, active, additionDate) " + " VALUES ('" + b + "', 3, 1, CURRENT_TIMESTAMP);");
                //sqLiteDatabase.execSQL("INSERT INTO List_Product (idList, idProduct) values ");//

            }

        }

但是我找不到从每个列表和产品中获取rowId的方法,以将idlist和idproduct插入List_Product。

提前谢谢。

2 个答案:

答案 0 :(得分:2)

有助于抓取ID的主要变化是从使用execSQL切换到使用insert,因为insert返回插入行的ID,execsql没有

这里有一点Using execSQL for INSERT operation in Android SQLite

但是,我不确定您是否可以通过CURRENT_TIMESTAMP传递 ContentValues ,这样会获得当前时间戳,而不是仅将值设置为文字CURRENT_TIMESTAMP。您可以在相应的列定义中使用DEFAULT CURRENT_TIMEPSTAMP(正如我在下面的代码中所示)。

我建议你不要在每个列表/产品排列之间建立一个链接(对于你来说,这将是100行,列表行和10个产品行),因为在现实生活中你可能没有这样的场景而不是你两者之间有一些联系。所以在下面的代码中我随机创建了链接。

首先来自Database Helper的一些代码(为方便起见,名为SO45449914)用于执行插入: -

public long insertListRow(String name,
                          int active) {
    ContentValues cv = new ContentValues();
    cv.put(LISTNAME_COL,name);
    cv.put(LISTACTIVE_COL,active);
    cv.put(LISTDEACTIVATIONDATE_COL,"");
    return this.getWritableDatabase().insert(PRIVATELISTTABLE,null,cv);
}

public long insertProductRow(String description,int quantity, int active) {
    ContentValues cv = new ContentValues();
    cv.put(PRODUCTDESCRIPTION_COL,description);
    cv.put(PRODUCTQUANTITY_COL,quantity);
    cv.put(PRODUCTACTIVE_COL,active);
    return this.getWritableDatabase().insert(PRIVATEPRODUCTTABLE,null,cv);
}

public void insertListProductLink(long listid, long productid) {
    ContentValues cv = new ContentValues();
    cv.put(LISTPRODUCTLIST_COL,listid);
    cv.put(LISTPRODUCTPRODUCT_COL,productid);
     if (this.getWritableDatabase().insertOrThrow(LISTPRODUCTTABLE,null,cv) <0) {
        //handle failed insert
    }
}

注   - 我已经为所有列名使用了类变量。   - 具有当前时间戳的列通过默认值获得此值,因此不需要为这些列设置cv.put

在活动中有以下代码: -

        void doSO45449914() {
            SO45449914 dbhelper = new SO45449914(this);
            int loopcount = 10;
            long[] listids = new long[loopcount];
            long[] productids = new long [loopcount];


            for (int i=0; i < 10; i++) {
                listids[i] = dbhelper.insertListRow("a" + i,1);
                productids[i] = dbhelper.insertProductRow("b" + i,3,1);
            }

            Cursor csra = dbhelper.getWritableDatabase().query(SO45449914.PRIVATELISTTABLE,
                     null,null,null,null,null,null
            );
            Cursor csrb = dbhelper.getWritableDatabase().query(SO45449914.PRIVATEPRODUCTTABLE,
                    null,null,null,null,null,null
            );
            Log.d("SO45449914","Number of rows in LIST TABLE = " + csra.getCount());
            Log.d("SO45449914","Number of rows in PRODUCTS TABLE = " + csrb.getCount());
            for (long aid: listids) {
                Log.d("SO45449914","LIST ID from store = " + Long.toString(aid));
            }
            for (long bid: productids) {
                Log.d("SO45449914","PRODUCT ID from store = " + Long.toString(bid));
            }
            for (long lid: listids) {
                for (long prdid: productids) {
                    if ((Math.random() * 100) > 60) {
                        dbhelper.insertListProductLink(lid,prdid);
                        Log.d("SO45449914",
                                "Adding link between List id(" +
                                        Long.toString(lid) +
                                        ") and product id(" +
                                        Long.toString(prdid) +
                                        ")"
                        );
                    }
                }
            }

            csra.close();
            csrb.close();
        }

Exlapnation

前几行根据要创建的列表和产品数量(两者的数量相同)准备长数组。整数loopcount决定了多少。

第一个循环,插入Lists和Products,它们使用insert方法在相应的数组元素中存储返回的 id

然后创建两个游标以获取行计数,然后将其写入日志。存储在数组中的id将输出到日志中。

然后调用两个嵌套循环,其中Products是内部(不重要),随机(大约40%的时间)将一行插入到链接表中。我假设随机但你总是很容易调整算法以遵循模式。 if ((Math.random() * 100) > 60) {决定是否插入链接。

然后关闭两个游标。

结果

以下是结果表的屏幕截图: -

PrivateList表

PrivateList Table

PrivateProduct表

Private Product Table

List_Product表

enter image description here

.....(List_Product表中有44行)

答案 1 :(得分:0)

嗯,这就是我的所作所为。尽管在List_Product表中没有这么多行,但有一种方法可以做同样的事情;我想了解方法。 (我也有问题所以它没有做我想要的确切)。

localDB = new LocalDB(this, "localBD", null, 1);
    SQLiteDatabase sqLiteDatabase = localDB.getWritableDatabase();

    if (sqLiteDatabase != null){

        long idList;
        long idProduct;

        for (int i = 0; i < 10; i++){
            String a = "List" + i;
            String b = "Product" + i;
            ContentValues contentValuesList = new ContentValues();
            contentValuesList.put("name", a);
            contentValuesList.put("active", 1);
            contentValuesList.put("creationDate", "CreationDate");
            contentValuesList.put("deactivationDate", "");
            idList = sqLiteDatabase.insert("PrivateList", null, contentValuesList);

            for (int j = 0; j < 10; j++){
                ContentValues contentValuesProduct = new ContentValues();
                contentValuesProduct.put("description", b);
                contentValuesProduct.put("active", 1);
                contentValuesProduct.put("quantity", 1);
                contentValuesProduct.put("additionDate", "additionDdate");
                idProduct = sqLiteDatabase.insert("PrivateProduct", null, contentValuesProduct);

                ContentValues contentValuesListProduct = new ContentValues();
                contentValuesListProduct.put("idList", idList);
                contentValuesListProduct.put("idProduct", idProduct);
                sqLiteDatabase.insert("List_Product", null, contentValuesListProduct);
            }

我知道它可能更有效率,但现在没关系。

这是数据库中的结果:

PrivateList:

enter image description here

有10行

PrivateProduct:

enter image description here

有100行。

List_Product:

enter image description here

问题是我不知道sqlLiteDatabase.insert(...)方法的存在。

谢谢大家。