我有tableA,tableB和tableC 表A和表B由tableA.Id(PK)= tableB.tableAId(FK)连接 表B和tableC由tableB.Id(PK)= tableC.tableBId(FK)
连接我希望能够做到这一点:
SELECT c.ALL from tableC c
INNER JOIN tableB b on c.tableBId = b.Id
INNER JOIN tableA a on b.tableAId = a.Id
WHERE a.Id = 108
我在网上发现了很多帖子,它们使用db.rawquery()来实现这个查询。但是我也听说rawquery()不如query()安全。因此,为了寻求初学者的最佳实践,我的问题是:
有没有办法使用db.query()而不是db.rawquery()来实现此查询?
提前感谢。
答案 0 :(得分:19)
有没有办法使用db.query()而不是使用db.query()来实现此查询 db.rawquery()?
所以值得一提的是,rawQuery()是一个技巧。但也存在另一种方法。
query()方法用于在一个表上执行查询。 但如何在SQLite中JOIN
表使用SQLiteQueryBuilder
以及使用setTables()方法加入的最佳方式。
因此我建议您使用提到的 SQLiteQueryBuilder 。但是对于需要仅分配原始语句的rawQuery()方法,它要复杂得多。
如果不知道如何开始,请查看以下示例:
rawQuery()
的安全性低于query()
,因为query()
方法使用比“原始”语句更安全的预编译语句。但是,你总是可以(应该)使用占位符,这显着提高了声明的安全性,作为对SQL
注入的主要保护,语句变得更加人性化。
答案 1 :(得分:19)
这有点晚了,但我认为其他正在寻找的人可能从中受益:
<div>
<uib-tabset>
<uib-tab ui-sref="principal.myplanManagement.myTimeTable" active="$state.current.name =='principal.myplanManagement.myTimeTable'">
<uib-tab-heading>Add MyTimeTable</uib-tab-heading>
</uib-tab>
<uib-tab ui-sref="principal.myplanManagement.myPlan" active="$state.current.name =='principal.myplanManagement.myPlan'">
<uib-tab-heading>Add MyPlan</uib-tab-heading>
</uib-tab>
<uib-tab ui-sref="principal.myplanManagement.myWDS" active="$state.current.name=='principal.myplanManagement.myWDS'">
<uib-tab-heading>Add MyWDS</uib-tab-heading>
</uib-tab>
</uib-tabset>
<div ui-view></div>
</div>
方法通过其db.query()
参数本机支持LEFT OUTER JOIN
AND INNER JOIN
,因此您实际上不需要使用table
来完成此操作。此外,它更容易,而且非常直接。
此方法广泛用于Google I/O 2015 Schedule app's source code。
一个快速示例(为简洁起见,遗漏了字符串常量):
SQLiteQueryBuilder
密钥位于Cursor cursor = db.query(NoteContract.Note.TABLE_NAME
+ " LEFT OUTER JOIN authors ON notes._id=authors.note_id", projection, selection,
selectionArgs, null, null, "notes._id");
的第一个参数中。
目前,仅支持db.query()
和LEFT OUTER JOIN
,这对大多数应用来说已经足够了。
我希望这个答案可以帮助那些正在寻找这个的人。
答案 2 :(得分:1)
是的,您可以使用query()而不是rawQuery(),只需要一个假设 - 您要加入的表中没有两个相同的列名。
如果该条件已满,则可以使用此答案 https://stackoverflow.com/a/34688420/3529903
答案 3 :(得分:0)
根据 SharpEdge 的评论,在尝试了基于 Nimrod Dayan 的答案的更复杂的例子之后,这是一个更复杂的例子。
使用4个连接,也使用生成的列。它使用表达式(减去时间戳),然后在WHERE子句中使用它。
基本上,方法是将join子句追加到表名字符串(SQLite然后将它移到列之后)。
DBConstants.SQL?????
已解析为相应的SQL,例如DBConstants.SQLISNOTNULL
解析为IS NOT NULL
DBConstans.CALCULATED?????
是计算列的名称。
DB????TableConstants.????_COL
解析为列名称(.._FULL
解析为table.column,例如,以避免模糊_ID列。)
方法(getToolRules
)如下: -
public Cursor getToolRules(boolean rulesexist,
int minimumruleperiodindays,
int minimumbuycount) {
String columns[] = new String[] {
"0 " + DBConstants.SQLAS + DBConstants.STD_ID,
DBProductusageTableConstants.PRODUCTUSAGE_PRODUCTREF_COL,
DBProductusageTableConstants.PRODUCTUSAGE_AISLEREF_COL,
DBProductusageTableConstants.PRODUCTUSAGE_COST_COL,
DBProductusageTableConstants.PRODUCTUSAGE_BUYCOUNT_COL,
DBProductusageTableConstants.PRODUCTUSAGE_FIRSTBUYDATE_COL,
DBProductusageTableConstants.PRODUCTUSAGE_LATESTBUYDATE_COL,
DBProductusageTableConstants.PRODUCTUSAGE_ORDER_COL,
DBProductusageTableConstants.PRODUCTUSAGE_RULESUGGESTFLAG_COL,
DBProductusageTableConstants.PRODUCTUSAGE_CHECKLISTFLAG_COL,
DBProductusageTableConstants.PRODUCTUSAGE_CHECKLISTCOUNT_COL,
"(" +
DBProductusageTableConstants.PRODUCTUSAGE_LATESTBUYDATE_COL +
"- " +
DBProductusageTableConstants.PRODUCTUSAGE_FIRSTBUYDATE_COL +
" / (86400000)" +
") " + DBConstants.SQLAS + DBConstants.CALCULATED_RULEPERIODINDAYS,
DBProductsTableConstants.PRODUCTS_NAME_COL,
DBAislesTableConstants.AISLES_NAME_COL,
DBAislesTableConstants.AISLES_ORDER_COL,
DBAislesTableConstants.AISLES_SHOPREF_COL,
DBShopsTableConstants.SHOPS_NAME_COL,
DBShopsTableConstants.SHOPS_CITY_COL,
DBShopsTableConstants.SHOPS_ORDER_COL,
DBRulesTableConstants.RULES_ID_COL_FULL +
DBConstants.SQLAS + DBRulesTableConstants.RULES_ALTID_COL,
DBRulesTableConstants.RULES_AISLEREF_COL,
DBRulesTableConstants.RULES_PRODUCTREF_COL,
DBRulesTableConstants.RULES_NAME_COL,
DBRulesTableConstants.RULES_USES_COL,
DBRulesTableConstants.RULES_PROMPT_COL,
DBRulesTableConstants.RULES_ACTON_COL,
DBRulesTableConstants.RULES_PERIOD_COL,
DBRulesTableConstants.RULES_MULTIPLIER_COL
};
String joinclauses = DBConstants.SQLLEFTJOIN +
DBProductsTableConstants.PRODUCTS_TABLE +
DBConstants.SQLON +
DBProductusageTableConstants.PRODUCTUSAGE_PRODUCTREF_COL + " = " +
DBProductsTableConstants.PRODUCTS_ID_COL_FULL + " " +
DBConstants.SQLLEFTJOIN +
DBAislesTableConstants.AISLES_TABLE +
DBConstants.SQLON +
DBProductusageTableConstants.PRODUCTUSAGE_AISLEREF_COL + " = " +
DBAislesTableConstants.AISLES_ID_COL_FULL +
DBConstants.SQLLEFTJOIN +
DBShopsTableConstants.SHOPS_TABLE +
DBConstants.SQLON +
DBAislesTableConstants.AISLES_SHOPREF_COL + " = " +
DBShopsTableConstants.SHOPS_ID_COL_FULL +
DBConstants.SQLLEFTJOIN +
DBRulesTableConstants.RULES_TABLE +
DBConstants.SQLON +
DBProductusageTableConstants.PRODUCTUSAGE_PRODUCTREF_COL + " = " +
DBRulesTableConstants.RULES_PRODUCTREF_COL +
DBConstants.SQLAND +
DBProductusageTableConstants.PRODUCTUSAGE_AISLEREF_COL + " = " +
DBRulesTableConstants.RULES_AISLEREF_COL
;
String ruleexistoption = DBRulesTableConstants.RULES_ID_COL_FULL;
if (rulesexist) {
ruleexistoption = ruleexistoption + DBConstants.SQLISNOTNULL;
} else {
ruleexistoption = ruleexistoption + DBConstants.SQLISNULL;
}
String whereclause = DBProductusageTableConstants.PRODUCTUSAGE_BUYCOUNT_COL +
" = ?" +
DBConstants.SQLAND + ruleexistoption +
DBConstants.SQLAND +
"(" + DBConstants.CALCULATED_RULEPERIODINDAYS + " / ?) > 0" +
DBConstants.SQLAND +
DBProductusageTableConstants.PRODUCTUSAGE_BUYCOUNT_COL + " > ?";
if (minimumbuycount > 0) {
--minimumbuycount;
}
String[] whereargs = new String[] {
"0",
Integer.toString(minimumruleperiodindays),
Integer.toString(minimumbuycount)
};
return db.query(DBProductusageTableConstants.PRODUCTUSAGE_TABLE + joinclauses,
columns,whereclause,whereargs,null,null,null);
}
在SQLite Manager中创建的基本SQL,用作构建方法的指南(看起来好得多,恕我直言,比在调试中从游标中提取的SQL): -
注意! 0 AS _ID
用于使CursorAdapter
使用游标(即CursorAdapters需要名为_ID的列)
SELECT
0 AS _id,
productusage.productusageproductref,
productusage.productusageaisleref,
productusage.productusageorder,
productusage.productusagecost,
productusage.productusagebuycount,
productusage.productusagefirstbuydate,
productusage.productusagelatestbuydate,
productusage.productusagerulesuggestflag,
productusage.productusagechecklistflag,
productusage.productusagechecklistcount,
/*********************************************************************************************************************************
Calculate the period in days from between the firstbuydate and the latestbuydate
*********************************************************************************************************************************/
(productusagelatestbuydate - productusagefirstbuydate) / (1000 * 60 * 60 * 24) AS periodindays,
products.productname,
aisles.aislename,
aisles.aisleorder,
aisles.aisleshopref,
shops.shopname,
shops.shopcity,
shops.shoporder,
rules._id AS rule_id,
rules.rulename,
rules.ruleuses,
rules.ruleprompt,
rules.ruleacton,
rules.ruleperiod,
rules.rulemultiplier
FROM productusage
LEFT JOIN products ON productusageproductref = products._id
LEFT JOIN aisles ON productusageaisleref = aisles._id
LEFT JOIN shops ON aisles.aisleshopref = shops._id
LEFT JOIN rules ON productusageaisleref = rules.ruleaisleref AND productusageproductref = rules.ruleproductref
WHERE productusagebuycount > 0 AND rules._id IS NULL AND (periodindays / 2) > 0 AND productusage.productusagebuycount > 0
答案 4 :(得分:-2)
public HashMap<String, String> get_update_invoice_getdata(String gen) {
// TODO Auto-generated method stub
HashMap<String, String> wordList;
wordList = new HashMap<String, String>();
Cursor cur_1 = ourDataBase
.rawQuery(
"SELECT * FROM Invoice i JOIN Client c ON i.Client_id=c.Client_id JOIN TAX t ON i.Tax_id=t.Tax_id JOIN Task it ON i.Task_id=it.Task_id WHERE i.Inv_no=?",
new String[] { gen });
int intext = cur_1.getColumnIndex(C_ORG_NAME);
int intext5 = cur_1.getColumnIndex(TA_NAME);
int intext6 = cur_1.getColumnIndex(TA_RATE);
int intext7 = cur_1.getColumnIndex(TA_QTY);
int intext8 = cur_1.getColumnIndex(TA_TOTAL);
if (cur_1.moveToFirst()) {
do {
wordList.put("Org_name", cur_1.getString(intext));
wordList.put("client_id", cur_1.getString(2));
wordList.put("po_number", cur_1.getString(4));
wordList.put("date", cur_1.getString(3));
wordList.put("dis_per", cur_1.getString(7));
wordList.put("item_name", cur_1.getString(intext5));
wordList.put("item_rate", cur_1.getString(intext6));
wordList.put("item_cost", cur_1.getString(intext7));
wordList.put("item_total", cur_1.getString(intext8));
} while (cur_1.moveToNext());
}
return wordList;
}