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_id
在 PRODUCT_VALUES
上执行另一个 OUTER JOIN
。
如果产品不存在特定 payment_method_id
,则外部联接的值将全部为 null
。因此,我们使用 IFNULL(pv.value,pv2.value)
到 return 特定值 iff 找到一个(= 不为空),否则使用 payment_method_id = 1
的默认值。
我的 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_id
在 PRODUCT_VALUES
上执行另一个 OUTER JOIN
。
如果产品不存在特定 payment_method_id
,则外部联接的值将全部为 null
。因此,我们使用 IFNULL(pv.value,pv2.value)
到 return 特定值 iff 找到一个(= 不为空),否则使用 payment_method_id = 1
的默认值。