Sqlite 查询另一个结果 if first is null cursor window 分配错误

Sqlite query for another result if first is null cursor window allocation error

我的 Sqlite 数据库中有以下 table:PRODUCTS、PRODUCT_VALUES 和 PAYMENT_FORMS,这是它们各自的列。

产品

+----+---------------+
| id | product_name  | 
+----+---------------+
|  1 | COMPUTER      |
|  2 | CELLPHONE     |
|  3 | LAPTOP        |
+----+---------------+

PAYMENT_METHOD

+----+---------------------+
| id | PAYMENT_METHOD_NAME |
+----+---------------------+
|  1 | CASH                |
|  2 | CREDIT              |
|  3 | 3X_CREDIT           |
+----+---------------------+

PRODUCT_VALUES

此 table 根据付款方式存储产品的价值,因此一个产品可以有多个值,例如 15.67 美元的现金和 16.30 美元的信用卡。但是假设该产品没有设置 3 倍的信用价值,所以在这种情况下,我需要获得现金价值,下面 table 中的第一个。

+-------------------+------------+---------+
| payment_method_id | product_id | value   |
+-------------------+------------+---------+
|                 1 |          1 |   15.67 |
|                 2 |          1 |   16.30 |
|                 3 |          1 |    NULL |
+-------------------+------------+---------+

现在我需要根据付款方式显示产品名称和价值,我正在使用以下 select:

    public ArrayList<Products> getProducts(int paymentMethodId) {

  ArrayList<Products> products = new ArrayList<>();

  // Cursor for the product search
  Cursor cursor = null;

  // Cursor for the product value search
  Cursor valuesCursor = null;

  // Products columns
  String[] columns = { Products.ID, Products.NAME };

  // Values columns
  String[] valuesColumns = { ProductsValues.VALUE };

  try {

    // Get all products on the table
    cursor = conn.query(Products.TABLE, columns, null, null, null, null, null, null);

    if (cursor.getCount() > 0) {

      cursor.moveToFirst();

      do {

        try {

          Products product = new Products();

          int productId = cursor.getInt(cursor.getColumnIndex(Produtos.ID));
          String productName = cursor.getInt(cursor.getString(cursor.getColumnIndex(Produtos.NAME)));
          product.setId(productId);
          product.setName(productName);

          // Gets the product value
          try{

            // Searchs the value based on the paymentMethodId
            valuesCursor = conn.query(ProductsValues.TABLE, valuesColumns, ProductsValues.PAYMENT_METHOD_ID + " = ?", new String[]{String.valueOf(paymentMethodId)}, null, null, null, null);

            if (valuesCursor != null && valuesCursor.getCount() > 0) {

              valuesCursor.moveToFirst();
              product.setValue(BigDecimal.valueOf(valuesCursor.getDouble(valuesCursor.getColumnIndex(ProductsValues.VALUE))));

            } else {

              // Searchs using the paymentMethodId 1
              valuesCursor = conn.query(ProductsValues.TABLE, valuesColumns, ProductsValues.PAYMENT_METHOD_ID + " = 1", null, null, null, null, null);

              if (valuesCursor != null && valuesCursor.getCount() > 0) {

                valuesCursor.moveToFirst();
                product.setValue(BigDecimal.valueOf(valuesCursor.getDouble(valuesCursor.getColumnIndex(ProductsValues.VALUE))));

              }

            }

          } catch (SQLiteException e){

            Log.e("TAG", "getProducts: Error selecting products", e);

          } finally {

            // Closes the valuesCursor
            if (aluesCursor != null) {

              aluesCursor.close();

            }

          }

          // ADD the product on the Array
          products.add(product);

        } catch (SQLiteException e){

          Log.e("TAG", "getProducts: Error selecting products", e);

        }
        // Repeats for the next product
      } while (cursor.moveToNext());

    }

  } catch (SQLiteException e) {

    Log.e("TAG", "getProducts: Error selecting products", e);

  } finally {

    // Closes the products cursor
    if (cursor != null) {

      cursor.close();

    }

  }

  return products;

}

然后基于 product_id 和 payment_method_id 我 select 值,但是如果结果为 null 我再次使用 [= 执行相同的 select 38=] 1,这是强制性的,因此不为空。在此之后,我在我的 Product 对象上设置值,并将结果 return 显示到我的 Activity 中。

但是当有很多产品时,大约在 2000 年,我遇到了游标 window 分配错误,打开了 967 个游标。

有没有办法select更有效地做到这一点?

您应该使用 rawQuery() 通过 JOIN 执行适当的 SQL 语句。喜欢:

SELECT
p.id, p.product_name, IFNULL(pv.value,pv2.value) AS value
FROM
PRODUCTS p
INNER JOIN PRODUCT_VALUES pv2 ON p.id = pv2.product_id AND pv2.payment_method_id = 1
LEFT OUTER JOIN PRODUCT_VALUES pv ON p.id = pv.product_id AND pv.payment_method_id = ?

解释:

我们 select 来自 PRODUCTS 的产品数据,并在 PRODUCT_VALUES 上使用 payment_method_id 1 创建了一个 INNER JOIN,它始终存在。此外,我们使用我们想要的特定 payment_method_idPRODUCT_VALUES 上执行另一个 OUTER JOIN

如果产品不存在特定 payment_method_id,则外部联接的值将全部为 null。因此,我们使用 IFNULL(pv.value,pv2.value) 到 return 特定值 iff 找到一个(= 不为空),否则使用 payment_method_id = 1 的默认值。