- 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/
我正在尝试学习 Fortran,并且看到了很多不同的定义,我想知道他们是否正在尝试完成同样的事情。以下有什么区别? 整数*4 整数(4) 整数(kind=4) 最佳答案 在 Fortran >=90
我以前从未编程过,最近(1 周前)才开始学习!第一门类(class)是函数式编程,使用 Haskell。 我有一项学校作业,我想通过删除一两个步骤来改进它,但我遇到了一个讨厌的错误。 基本上,我创建了
给定以下GraphQL请求和变量: 请求: query accounts($filter:AccountFilter, $first_:String, $skip_:Int) { accounts
我已经搜索了 StackOverflow,但找不到关于如何检查计算器应用程序的数字输入正则表达式的答案,该计算器应用程序将检查每个 keyup 的以下格式(jquery key up): 任何整数,例
类似于我上一篇致歉的文章,但没有那么长篇大论。基本上我想知道当每次重绘调用只重绘屏幕的一小部分时,优化重绘到 JFrame/JPanel 的最佳选择是什么。 此外,除了重绘重载之外,我并不是 100%
所以在我的教科书中有一个使用 f# 的递归函数的例子 let rec gcd = function | (0,n) -> n | (m,n) -> gcd(n % m,m);; 使用此功能,我的教科书
我有一个数据结构,例如表达式树或图形。我想添加一些“测量”功能,例如depth和 size . 如何最好地键入这些函数? 我认为以下三个变体的用处大致相同: depth :: Expr -> Int
这样写比较好 int primitive1 = 3, primitive2 = 4; Integer a = new Integer(primitive1); Integer b = new Inte
我是 Java 8 新手,想根据键对 Map 进行排序,然后在值内对每个列表进行排序。 我试图寻找一种 Java 8 方法来对键和值进行排序。HashMap>映射 map.entrySet().str
这就是我的目标... vector ,int> > var_name (x, pair (y),int>); 其中 x 是 vector var_name 的大小,y 是对内 vector 的大小。
这里是 an answer to "How do I instantiate a Queue object in java?" , Queue is an interface. You can't i
这个问题在这里已经有了答案: Weird Integer boxing in Java (12 个答案) Why are autoboxed Integers and .getClass() val
我们可以使用 C++ STL 做这样的事情吗?如果是,我将如何初始化元素?我试图这样做,但没有成功。 pair,vector>p; p.first[0]=2; 最佳答案 Can we do som
您好,我正在尝试为百分比和整数数组中的数字找到索引。假设 arraynum = ['10%','250','20%','500'] 并且用户发送一个值 15%,这个数字在哪个范围内居住?我可以使用这段
我与三列有关系:ProductName、CategoryID 和 Price。我需要选择仅那些价格高于给定类别中平均产品价格的产品。(例如,当apple(ProductName)是fruit(Cate
我已经坚持了一段时间,我正在尝试将一些数据配对在一起。这是我的代码。 #include #include using namespace std; int main() { pair data(
我收到错误:'(Int, Int)' 与 'CGPoint' 不相同 如何将 (Int, Int) 转换为 CGPoint let zigzag = [(100,100), (100,150)
我在 .cpp 文件中发现了以下代码。我不理解涉及头文件的构造或语法。我确实认识到这些特定的头文件与 Android NDK 相关。但是,我认为这个问题是关于 C++ 语法的一般问题。这些在某种程度上
我将这些输入到 Scala 解释器中: val a : Integer = 1; val b : Integer = a + 1; 我收到消息: :5: error: type mismatch;
C++:vector>v(size);当我试图打印出值时显示 0 作为值,但是当未声明 vector 大小时它显示正确的输出?为什么这样?例如: int x; cin>>x; vector>v(x);
我是一名优秀的程序员,十分优秀!