我开始知道使用 MySQLi 和 PDO 时准备好的语句是如何工作的,第一步,我启用了 MySQL 查询监控,如下所述:How can I view live MySQL queries? .然后我创建了以下测试:
使用mysqli:
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username =?")) {
$stmt->bind_param("i", $user);
$user = "''1''";
服务器日志:
130802 23:39:39 175 Connect ****@localhost on testdb 175 Prepare SELECT * FROM users WHERE username =? 175 Execute SELECT * FROM users WHERE username =0 175 Quit
使用 PDO:
$user = "''1''";
$sql = 'SELECT * FROM user WHERE uid =?';
$sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->bindParam(1, $user, PDO::PARAM_INT);
服务器日志:
130802 23:41:42 176 Connect ****@localhost on testdb 176 Query SELECT * FROM user WHERE uid ='\'\'1\'\'' 176 Quit
但是,两者提供相同的结果:
uid: 0
username: admin
role: admin
注意:uid = 0 是正确的,因为 intval("''1''") = 0
这里重要的是:
SELECT * FROM user WHERE uid ='\'\'1\'\''
我在 PHP 手册中只找到一个指示:http://www.php.net/manual/en/pdo.prepare.php
Note:
Emulated prepared statements does not communicate with the database server so PDO::prepare() does not check the statement.
但我不确定 MySQL 如何处理此查询并将 '\'\'1\'\'' 替换为 0。在这种情况下,如果使用 PDO,监控查询将不准确,同时,使用 PDO 可以更好地了解发送到 MySQL 而不是 MySQLi 的确切查询。
更新: 将参数类型从整数更改为字符串后:
MySQLi 日志:
188 Prepare SELECT * FROM awa_user WHERE username =? 188 Execute SELECT * FROM awa_user WHERE username ='\'\'1\'\'' 188 Quit
PDO 日志:
189 Query SELECT * FROM awa_user WHERE userame ='\'\'1\'\'' 189 Quit
这意味着 MySQLi 和 PDO 在使用字符串时在发送到 MySQL 之前转义数据,而对于整数,mysqli 在发送查询之前应用 intval() 或类似的东西,Bill 的回答也是正确的。
最佳答案
您的 PDO 配置为模拟准备好的查询,而 mysqli 使用的是真正的准备好的查询。
准备好的查询将字符串 ''1'' 绑定(bind)为整数参数值。 PHP 使用 intval() 之类的方法将其强制转换为整数。任何具有非数字前导字符的字符串都被 PHP 解释为 0,因此在 prepare 之后发送的参数值为值 0。
伪造的准备好的查询使用字符串插值(而不是绑定(bind))将字符串''1''添加到SQL 查询之前 MySQL 解析它。但结果是相似的,因为 SQL 也将整数上下文中具有非数字前导字符的字符串视为值 0。
唯一的区别是当参数在准备之前与准备之后绑定(bind)时,一般查询日志中的最终结果是什么。
您还可以使 PDO 使用真正准备好的查询,因此在这种情况下它应该像 mysqli 一样工作:
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
PS:这可以很好地说明为什么习惯上将 id 值从 1 而不是 0 开始。
关于php - PDO 向 MySQL 发送原始查询,而 Mysqli 发送准备好的查询,两者产生相同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18026088/
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=
文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co
我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时
s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成
我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin
我在Rails上使用带有ruby的solr。一切正常,我只需要知道是否有任何现有代码来清理用户输入,比如以?开头的查询。或* 最佳答案 我不知道执行此操作的任何代码,但理论上可以通过查看parsingcodeinLucene来完成并搜索thrownewParseException(只有16个匹配!)。在实践中,我认为您最好只捕获代码中的任何solr异常并显示“无效查询”消息或类似信息。编辑:这里有几个“sanitizer”:http://pivotallabs.com/users/zach/blog/articles/937-s
我正在为锦标赛开发一个Rails应用程序。我在这个查询中使用了三个模型:classPlayertruehas_and_belongs_to_many:tournamentsclassTournament:destroyclassPlayerMatch"Player",:foreign_key=>"player_one"belongs_to:player_two,:class_name=>"Player",:foreign_key=>"player_two"在tournaments_controller的显示操作中,我调用以下查询:Tournament.where(:id=>params