- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
正如Android文档所说,rawQuery方法的selectionArgs参数被解析为字符串。
SQLiteDatabase.rawQuery(String sql, String[] selectionArgs)
selectionArgs: You may include ?s in where clause in the query,which will be replaced by the values from selectionArgs.The values will be bound as Strings.
但是今天,我遇到了一个问题,这个问题占用了我一天的大部分时间。想象一下以下查询:
SELECT * FROM TABLE_A WHERE IFNULL(COLUMN_A, 0) >= 15
COLUMN_A 是整数。该表有大约 10 行符合该标准。在数据库编辑器上运行查询,结果总是正确的,但在智能手机上,语句总是没有返回任何行。
一段时间后,A 将查询更改为:
SELECT * FROM TABLE_A WHERE IFNULL(COLUMN_A, 0) >= '15'
并且编辑器没有返回任何行,就像 Android 一样。因此,将查询更改为:
SELECT * FROM TABLE_A WHERE CAST(IFNULL(COLUMN_A, 0) as INTEGER) >= '15'
解决了这个问题。完成的另一个测试是:
SELECT * FROM TABLE_A WHERE COLUMN_A >= '15'
同样,返回了正确的结果。
这似乎是一个问题,涉及 Android 使用 IFNULL 子句将参数绑定(bind)到查询(作为字符串)的方式。
所以,有人知道为什么会这样吗?是否有任何建议可以在不对查询使用 CAST 的情况下解决此问题?
最佳答案
将您的值绑定(bind)到查询的原因是为了防止 SQL-injection attack .
基本上,您将查询(包括占位符)发送到您的数据库并说“我的下一个查询将采用这种形式,而不是其他形式!”。当攻击者随后注入(inject)不同的查询字符串(例如,通过表单字段)时,数据库会说“嘿,这不是你说要发送的查询!”并向您抛出错误。
Since commands (which can be injected into your actual query as show in the linked article) are strings, the string-datatype is the more "dangerous" one. If a user tries to inject some code into your field which should only take numbers and you try to cast/parse the input to an integer (before putting the value into your query), you'll get an exception right away. With a string, there is no such kind security. Therefor, they have to be escaped probably. That might be the reason that the bind values are all interpreted as strings.
以上是伪造的!您绑定(bind)的参数是字符串还是整数并不重要,它们都同样危险。此外,在代码中预先检查您的值会产生大量样板代码,容易出错且不灵活!
为了防止您的应用程序遭受 SQL 注入(inject)并加速多个数据库写入 操作(使用具有不同值的相同查询),您应该使用“准备好的语句”。在 Android SDK 中写入数据库的正确类是 SQLiteStatement
.
要创建准备好的语句,您可以使用 compileStatement()
-method您的 SQLiteDatabase
-object 并使用正确的 bindXX()
-方法(继承自 SQLiteProgram
):
SQLiteDatabase db = dbHelper.getWritableDatabase();
SQLiteStatement stmt = db.compileStatement("INSERT INTO SomeTable (name, age) values (?,?)");
// Careful! The index begins at 1, not 0 !!
stmt.bindString(1, "Jon");
stmt.bindLong(2, 48L);
stmt.execute();
// Also important! Clean up after yourself.
stmt.close();
示例取自这个较旧的问题:How do I use prepared statements in SQlite in Android?
遗憾的是,SQLiteStatement
没有返回Cursor
的重载,因此您不能将它用于SELECT
语句。对于那些,您可以使用 rawQuery(String, String[])
-SQLiteDatabase
的方法:
int number = getNumberFromUser();
String[] arguments = new String[]{String.valueOf(number)};
db.rawQuery("SELECT * FROM TABLE_A WHERE IFNULL(COLUMN_A, 0) >= ?", arguments);
请注意,rawQuery()
方法采用字符串数组作为参数值。这其实没关系,SQLite 会自动转换为正确的类型。只要字符串表示形式与您在 SQL 查询中所期望的相同,就没问题。
关于android - SQLite rawQuery selectionArgs 和整数字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11320434/
我们有这两个类 MainActivity 和一个 DBHelper DBHelper创建数据库和两个表一个表,masterPW ,只有一行两列,ID和 ColPW .一旦创建并插入数据,该表将仅包含一
我正在对我的数据库进行更新,但它不起作用。这是我的代码: list.setOnItemClickListener(new OnItemClickListener() { @Overri
我一遍又一遍地寻找这个问题的答案,但你是我唯一的机会。事情是这样的: 我有一个 DBAdapter 类、MakeListActivity 和 SeeListActivity。 在DBAdapter中我
我想实现 Android Room 持久性。 这是我的 DAO 界面。 @Dao interface FoodDao { /** * Returns all data in tabl
我得到了这个方法,它应该检查数据库中的给定数据并显示包含该数据的整行。 movies 是表的名称,year 是列的名称。 我已经尝试了几个小时,但找不到原因,为什么它会抛出此错误: 11-24 19:
因此,目前在添加到我的数据库时,我执行此 select 语句获取结果并将其添加到我的数据库中的单独列中,如下所示: public void addGasLog(GasLog gasLog){
一个简单的问题,我在互联网上找不到它,可能我看错了“术语”。但是如何制作带有“if contains”的SQL查询语句 "SELECT something FROM " + TABLE_NAME +
我的准备好的 SQL 语句有一个奇怪且无法解释的错误,它没有提供与 noprepared 语句相同的结果。 这两个版本不应该返回相同的结果吗? 准备好的版本(结果错误): sb.append(" WH
当我使用正常的 13 位条码运行以下任一查询时,我的数据库返回的结果非常好。但是,当我使用 8 位条形码运行完全相同的代码时,即使结果存在于数据库中,也不会在第二个查询中找到。对我来说,这些查询看起来
为了获得查询的多个结果,我使用了 Cursor c = mydatabase.rawQuery("command", null); 然后是 while (c.moveToNext()) { ... }
我希望能够使用原始查询按升序对单词进行排序(因为我将使用游标)。但是,当我尝试按字母顺序对单词进行排序时,我的应用程序崩溃了,出现了这个错误: android.database.sqlite.SQLi
我正在使用 String.format 将 SQLite 查询构建为 String 并将其传递给 SQLiteDatabase.rawQuery。我最后传递的整数参数被硬编码为零(我正在寻找大于零的任
如何执行下面的查询 select * from regions where field1 in('word1', 'word2') 使用 sqlite rawQuery 方法? 我试过下面的代码: S
我正在尝试使用带有 simpleCursorAdapter 的 rawQuery 来显示到 ListView ,但它一直向我抛出错误 04-29 13:36:36.453: ERROR/Android
什么都试过了。此更新不起作用。没有错误或其他什么 - 它只是不更新表格。 void SetDisable (Integer ID, boolean action){ Integ
我正在使用MySQLI Wrapper如 docs 中所述关于运行 rawQuery。由于它没有任何搜索数据库的功能,所以我自己编写了。下面是正在使用的代码。 $songs = $db->Object
Android 中 SQLite 数据库的以下 rawQuery 不返回任何结果: String query = "SELECT * FROM " + "(SELECT MATCH_ID, P
我正在运行以下命令,但以下列的列名称不明确 Cursor cursor = getWritableDatabase().rawQuery("select ((odometer) - y.odomete
我正在尝试在 WHERE 中使用动态创建的列表,例如: select * from books where id in (123, 120, 125) and bookCover = 'Hardcov
我创建了这个方法来了解我的 Sqlite 数据库中是否存在联系人。 public Cursor doesContactExist(String name) { return db.rawQue
我是一名优秀的程序员,十分优秀!