如何使用 SQLite 中的预准备语句为 Android 应用程序编写 INSERT、UPDATE、DELETE、SELECT、嵌套 SELECT 命令?
How to write INSERT, UPDATE, DELETE,SELECT,Nested SELECT command using a prepared statement in SQLite for Android Application?
最近我了解到 android 中的原始查询无法防止 SQL 注入,因此我决定将 Prepared 语句中的所有查询转换为 SQL 注入预防。但是我不知道如何在Prepared Statement中转换复杂的查询。
我想转换以下查询:
1.
select
*
FROM
TableName
where
(tab1col1 in(SELECT tab2Col2 FROM MasterTable where tab2col1='Y')
or tab1col2 = CV.TRUE)
order by
tab1col3, tab1col4, tab1col5,tab1col6
2.
Select
* ,count(*) as TOTAL_COUNT ,
SUM(CASE WHEN tabCol1 LIKE '%todayDate%' THEN 1 ELSE 0 END) as TOTAL_COL1_COUNT
from
TableName
group by tabCol2;
防止SQL注入的唯一方法是使用参数。 (在某些 PHP API 中,获取参数的唯一方法是使用准备好的语句,但这不是 Android 数据库 API 中的缺点之一。)
任意字符串写?
,分别传值:
String name = ...;
String password = ...;
cursor = db.rawQuery("SELECT SomeCol FROM Users WHERE Name = ? AND Password = ?",
new String[]{ name, password });
请注意,只有当您拥有由(潜在敌对的)用户控制的字符串值时,才会发生 SQL 注入。您上面的查询看起来不像是这种情况。
您可以使用 rawQuery
通过 selectionargs(第二个参数)传递任何参数来防止注入。
SQL 注入,不适用于任何一个查询,因为它们是硬编码的并且没有用户 generated/supplied 输入。
例如您的第一个查询可能是(假设 'Y' 和 CV.TRUE 作为参数传递(即用户 generated/supplied)为了演示):-
public Cursor query1raw(String indicator1,String indicator2) {
String sql = "SELECT * " +
" FROM TableName " +
" WHERE (tab1col1" +
" IN(" +
" SELECT tab2col2 " +
" FROM MasterTable " +
" WHERE tab2col1=?)" +
" OR tab1col2=?)" +
" ORDER BY tab1col3, tab1col4,tab1col5,tab1col6";
String[] args = new String[]{indicator1,indicator2};
return mDB.rawQuery(sql,args);
}
但是,通常建议使用方便的方法而不是 rawQuery
或 execSQL
,当它们可以使用时,再次通过参数使用绑定字符串,上面,使用 query
方便方法可以是:-
public Cursor query1(String indicator1, String indicator2) {
String whereclause = "(tab1col1 IN(SELECT tab2col2 FROM MasterTable WHERE tab2col1=?) OR tab1col2=?)";
String[] whereargs = new String[] {indicator1,indicator2};
String order_columns = "tab1col3,tab1col4,tab1col5,tab1col6";
return mDB.query("TableName",null,whereclause,whereargs,null,null,order_columns);
}
您不会自己使用准备好的语句,因为它们仅限于返回单个值,而不是一行或多列的行。
不建议警告
但是,如果你真的想要,你可以使用 :-
public Cursor query1ps(String indicator1,String indicator2) {
String[] whereargs = new String[] {indicator1,indicator2};
SQLiteStatement stmnt = mDB.compileStatement("SELECT * " +
" FROM TableName " +
" WHERE (tab1col1" +
" IN(" +
" SELECT tab2col2 " +
" FROM MasterTable " +
" WHERE tab2col1=?)" +
" OR tab1col2=?)" +
" ORDER BY tab1col3, tab1col4,tab1col5,tab1col6");
stmnt.bindAllArgsAsStrings(whereargs);
Log.d("PREPAREDSQL",stmnt.toString());
String sql = stmnt.toString().replace("SQLiteProgram:","");
return mDB.rawQuery(sql,null);
}
- 如您所见,所有准备好的语句都是这样做的,正在替换参数,因此与其他方法相比没有什么好处。这也取决于 SQLIteProgram: 保持不变。
最近我了解到 android 中的原始查询无法防止 SQL 注入,因此我决定将 Prepared 语句中的所有查询转换为 SQL 注入预防。但是我不知道如何在Prepared Statement中转换复杂的查询。
我想转换以下查询:
1.
select
*
FROM
TableName
where
(tab1col1 in(SELECT tab2Col2 FROM MasterTable where tab2col1='Y')
or tab1col2 = CV.TRUE)
order by
tab1col3, tab1col4, tab1col5,tab1col6
2.
Select
* ,count(*) as TOTAL_COUNT ,
SUM(CASE WHEN tabCol1 LIKE '%todayDate%' THEN 1 ELSE 0 END) as TOTAL_COL1_COUNT
from
TableName
group by tabCol2;
防止SQL注入的唯一方法是使用参数。 (在某些 PHP API 中,获取参数的唯一方法是使用准备好的语句,但这不是 Android 数据库 API 中的缺点之一。)
任意字符串写?
,分别传值:
String name = ...;
String password = ...;
cursor = db.rawQuery("SELECT SomeCol FROM Users WHERE Name = ? AND Password = ?",
new String[]{ name, password });
请注意,只有当您拥有由(潜在敌对的)用户控制的字符串值时,才会发生 SQL 注入。您上面的查询看起来不像是这种情况。
您可以使用 rawQuery
通过 selectionargs(第二个参数)传递任何参数来防止注入。
SQL 注入,不适用于任何一个查询,因为它们是硬编码的并且没有用户 generated/supplied 输入。
例如您的第一个查询可能是(假设 'Y' 和 CV.TRUE 作为参数传递(即用户 generated/supplied)为了演示):-
public Cursor query1raw(String indicator1,String indicator2) {
String sql = "SELECT * " +
" FROM TableName " +
" WHERE (tab1col1" +
" IN(" +
" SELECT tab2col2 " +
" FROM MasterTable " +
" WHERE tab2col1=?)" +
" OR tab1col2=?)" +
" ORDER BY tab1col3, tab1col4,tab1col5,tab1col6";
String[] args = new String[]{indicator1,indicator2};
return mDB.rawQuery(sql,args);
}
但是,通常建议使用方便的方法而不是 rawQuery
或 execSQL
,当它们可以使用时,再次通过参数使用绑定字符串,上面,使用 query
方便方法可以是:-
public Cursor query1(String indicator1, String indicator2) {
String whereclause = "(tab1col1 IN(SELECT tab2col2 FROM MasterTable WHERE tab2col1=?) OR tab1col2=?)";
String[] whereargs = new String[] {indicator1,indicator2};
String order_columns = "tab1col3,tab1col4,tab1col5,tab1col6";
return mDB.query("TableName",null,whereclause,whereargs,null,null,order_columns);
}
您不会自己使用准备好的语句,因为它们仅限于返回单个值,而不是一行或多列的行。
不建议警告
但是,如果你真的想要,你可以使用 :-
public Cursor query1ps(String indicator1,String indicator2) {
String[] whereargs = new String[] {indicator1,indicator2};
SQLiteStatement stmnt = mDB.compileStatement("SELECT * " +
" FROM TableName " +
" WHERE (tab1col1" +
" IN(" +
" SELECT tab2col2 " +
" FROM MasterTable " +
" WHERE tab2col1=?)" +
" OR tab1col2=?)" +
" ORDER BY tab1col3, tab1col4,tab1col5,tab1col6");
stmnt.bindAllArgsAsStrings(whereargs);
Log.d("PREPAREDSQL",stmnt.toString());
String sql = stmnt.toString().replace("SQLiteProgram:","");
return mDB.rawQuery(sql,null);
}
- 如您所见,所有准备好的语句都是这样做的,正在替换参数,因此与其他方法相比没有什么好处。这也取决于 SQLIteProgram: 保持不变。