PHP MySQL 预处理语句学习笔记

 更新时间:2016年11月25日 16:34  点击:1718
预处理语句对于防止 MySQL 注入了,我们在mssql中通常会通过存储过程来进行过滤了,但在mysql与php中并不能样处理 ,下面我们一起来看看PHP MySQL 预处理语句学习笔记,希望例子能够对各位有帮助。


预处理语句及绑定参数

 

预处理语句用于执行多个相同的 SQL 语句,并且执行效率更高。

 

预处理语句的工作原理如下:

 

预处理:创建 SQL 语句模板并发送到数据库。预留的值使用参数 "?" 标记 。例如:INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)

数据库解析,编译,对SQL语句模板执行查询优化,并存储结果不输出
执行:最后,将应用绑定的值传递给参数("?" 标记),数据库执行语句。应用可以多次执行语句,如果参数的值不一样。

相比于直接执行SQL语句,预处理语句有两个主要优点:

预处理语句大大减少了分析时间,只做了一次查询(虽然语句多次执行)
绑定参数减少了服务器带宽,你只需要发送查询的参数,而不是整个语句
预处理语句针对SQL注入是非常有用的,因为 参数值发送后使用不同的协议,保证了数据的合法性。
MySQLi 预处理语句

以下实例在 MySQLi 中使用了预处理语句,并绑定了相应的参数:

实例 (MySQLi 使用预处理语句)

<?php

$servername = "localhost";

$username = "username";

$password = "password";

$dbname = "myDB";

// 创建连接

$conn = new mysqli($servername, $username, $password, $dbname);

// 检测连接

if ($conn->connect_error) {

    die("Connection failed: " . $conn->connect_error);

}

// prepare and bind

$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)");

$stmt->bind_param("sss", $firstname, $lastname, $email);

// 设置参数并执行

$firstname = "John";

$lastname = "Doe";

$email = "john@example.com";

$stmt->execute();

$firstname = "Mary";

$lastname = "Moe";

$email = "mary@example.com";

$stmt->execute();

$firstname = "Julie";

$lastname = "Dooley";

$email = "julie@example.com";

$stmt->execute();

echo "New records created successfully";

$stmt->close();

$conn->close();

?>
解析以下实例的每行代码:
"INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)"

在 SQL 语句中,我们使用了问号 (?),在此我们可以将问号替换为整型,字符串,双精度浮点型和布尔值。
接下来,让我们来看下 bind_param() 函数:
$stmt->bind_param("sss", $firstname, $lastname, $email);
该函数绑定了 SQL 的参数,且告诉数据库参数的值。 "sss" 参数列处理其余参数的数据类型。s 字符告诉数据库该参数为字符串。


参数有以下四种类型:

 

i - integer(整型)
d - double(双精度浮点型)
s - string(字符串)
b - BLOB(布尔值)
每个参数都需要指定类型。
通过告诉数据库参数的数据类型,可以降低 SQL 注入的风险。
Note 注意: 如果你想插入其他数据(用户输入),对数据的验证是非常重要的。
PDO 中的预处理语句

以下实例我们在 PDO 中使用了预处理语句并绑定参数:


实例 (PDO 使用预处理语句)

<?php

$servername = "localhost";

$username = "username";

$password = "password";

$dbname = "myDBPDO";

try {

    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);

    // 设置 PDO 错误模式为异常

    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // 预处理 SQL 并绑定参数

    $stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) 

    VALUES (:firstname, :lastname, :email)");

    $stmt->bindParam(':firstname', $firstname);

    $stmt->bindParam(':lastname', $lastname);

    $stmt->bindParam(':email', $email);

    // 插入行

    $firstname = "John";

    $lastname = "Doe";

    $email = "john@example.com";

    $stmt->execute();

    // 插入其他行

    $firstname = "Mary";

    $lastname = "Moe";

    $email = "mary@example.com";

    $stmt->execute();

    // 插入其他行

    $firstname = "Julie";

    $lastname = "Dooley";

    $email = "julie@example.com";

    $stmt->execute();

    echo "New records created successfully";

    }

catch(PDOException $e)

    {

    echo $sql . "<br>" . $e->getMessage();

    }

$conn = null;

?>

连接redis数据库与mysql连接也是差不多了,我们下面整理了一些关于连接redis并且一些操作例子,具体的操作例子如下所示.


对于大型网站来说,redis是非常受欢迎的,运用redis缓存之后,网站瞬间可以提速n倍。那么php如何连接redis呢,下面是一个入门的范例代码。

<?php
$redis = new Redis(); //创建一个对象
$redis->connect('127.0.0.1',6379); //连接redis
$redis->select(0); //选择数据库(默认16个数据库,0-15,这个值可以在配置文件修改。)
$redis->set('a1', 'www.daixiaorui.com'); //往redis写入一条记录
echo $redis->get('a1'); //从redis中读取一条记录
?>

Redis的PHP字符串实例

<?php
   //Connecting to Redis server on localhost
   $redis = new Redis();
   $redis->connect('127.0.0.1', 6379);
   echo "Connection to server sucessfully";
   //set the data in redis string
   $redis->set("tutorial-name", "Redis tutorial");
   // Get the stored data and print it
   echo "Stored string in redis:: " + jedis.get("tutorial-name");
?>

当执行程序时,会产生下面的结果:


Connection to server sucessfully
Stored string in redis:: Redis tutorial

Redis的PHP列表示例

<?php
   //Connecting to Redis server on localhost
   $redis = new Redis();
   $redis->connect('127.0.0.1', 6379);
   echo "Connection to server sucessfully";
   //store data in redis list
   $redis->lpush("tutorial-list", "Redis");
   $redis->lpush("tutorial-list", "Mongodb");
   $redis->lpush("tutorial-list", "Mysql");
   // Get the stored data and print it
   $arList = $redis->lrange("tutorial-list", 0 ,5);
   echo "Stored string in redis:: "
   print_r($arList);
?>

当执行程序时,会产生下面的结果:


Connection to server sucessfully
Stored string in redis::
Redis
Mongodb
Mysql

Redis的PHP键例

 
<?php
   //Connecting to Redis server on localhost
   $redis = new Redis();
   $redis->connect('127.0.0.1', 6379);
   echo "Connection to server sucessfully";
   // Get the stored keys and print it
   $arList = $redis->keys("*");
   echo "Stored keys in redis:: "
   print_r($arList);
?>

当执行程序时,会产生下面的结果:


Connection to server sucessfully
Stored string in redis::
tutorial-name
tutorial-list

就是这么简单,感觉有点像连接mysql数据库一样。运行以上代码前,请确认您的电脑是否已安装并启动redis服务;请确认php已安装redis扩展,这个具体请在phpinfo查看。如果没有安装,去官网下一个对应php版本的扩展即可。

取MONGOID对象的ID字符串值其实就像mysql中返回数据记录的ID号了,这样的做法是非常的简单了,下面我们一起来看看。


使用GridFS传文件到MongoDB,会返回一个MongoId对象,通常我们需要把这个对象中的$id值以字符串形式保存到数据库中,作为取文件的标识,那么PHP如何取出MongoID对象的ID字符串值呢?

在php中通过_id 在mongodb中查找特定记录:

查询条件需要这样写:array("_id"=>new MongoId("$id"))


这个MongoId形如:

object(MongoId)#23 (1) {
  ["$id"] => string(24) "558a7dab988d4d10140058b1"
}

我们要用PHP取出[“$id”]的值,问题是这个键名是这种形式的,用$re->$id肯定不对,所以这样取值:

//存储上传的excel到MongoDB
public function saveToMongo($file){
 $id = $this->getGridFS()->storeFile($file);
 return $id->{'$id'};
}

这样就OK了。

在php中连接mysql数据库有 mysql、mysqli、pdo三种方式了,但估计各位对于它们三个的连接与区别估计不是很理解了,下面一聚教程小编为各位介绍一下吧。


一、特性及对比

PHP的MySQL扩展是设计开发允许PHP应用与MySQL数据库交互的早期扩展。mysql扩展提供了一个面向过程 的接口,并且是针对MySQL4.1.3或更早版本设计的。因此,这个扩展虽然可以与MySQL4.1.3或更新的数据库服务端 进行交互,但并不支持后期MySQL服务端提供的一些特性。由于太过古老,又不安全,所以已被后来的mysqli完全取代。
PHP的mysqli扩展,我们有时称之为MySQL增强扩展,可以用于使用 MySQL4.1.3或更新版本中新的高级特性。其特点为:面向对象接口 、prepared语句支持、多语句执行支持、事务支持 、增强的调试能力、嵌入式服务支持 、预处理方式完全解决了sql注入的问题。不过其也有缺点, 就是只支持mysql数据库。如果你要是不操作其他的数据库,这无疑是最好的选择。
PDO是PHP Data Objects的缩写,其是PHP应用中的一个数据库抽象层规范。PDO提供了一个统一的API接口可以使得你的PHP应用不去关心具体要 连接的数据库服务器系统类型。也就是说,如果你使用PDO的API,可以在任何需要的时候无缝切换数据库服务器,比如从oracle 到MySQL,仅仅需要修改很少的PHP代码。其功能类似于JDBC、ODBC、DBI之类接口。同样,其也解决了sql注入问题,有很好的安全性。不过他也有缺点,某些多语句执行查询不支持(不过该情况很少)。

官文对于三者之间也做了列表性的比较: 


























































PHP的mysqli扩展
PDO (使用PDO MySQL驱动和MySQL Native驱动)PHP的mysql扩展
引入的PHP版本5.05.03.0之前
PHP5.x是否包含
MySQL开发状态活跃在PHP5.3中活跃仅维护
在MySQL新项目中的建议使用程度建议 - 首选建议不建议
API的字符集支持
服务端prepare语句的支持情况
客户端prepare语句的支持情况
存储过程支持情况
多语句执行支持情况大多数
是否支持所有MySQL4.1以上功能大多数

 

从官方给出的这份结果上来看,优先推荐msqli,其次是pdo 。而“民间”给出的结果很多是倾向于使用PDO,因为其不担有跨库的优点,更有读写速度快的特点。
51cto上的给出了相关的测试结果(有点老,2011年的测试结果)。
二、模块安装及调用
以ubuntu及其衍生版为例,通过sudo apt-get install mysqlnd 即可增加php对pdo和mysqli的支持(源码安装的可以选择phpize程序进行动态扩展)。具体可以通过phpinfo页面打开查看,其中在mysqlnd项下,可以看到如下内容:

API Extensions  mysql,mysqli,pdo_mysql

mysqli和PDO连接方法

// PDO
$pdo = new PDO("mysql:host=localhost;dbname=database", 'username', 'password');
// mysqli, 面向过程方式
$mysqli = mysqli_connect('localhost','username','password','database');
// mysqli, 面向对象
$mysqli = new mysqli('localhost','username','password','database');

mysqli通过配置文件进行查询的示例:

配置文件

yang@crunchbang:/var/www/t$ cat config.ini.php

查询代码

yang@crunchbang:/var/www/t$ cat mysqlquery.php
query("set names $charName");
    //3、处理结果
    $res= $mysqliObj->query($sql);
    //var_dump($res);
    //fetch_assoc \fetch_array \fetch_object
    while($row=$res->fetch_row()){
 //       print_r($row);
        foreach($row as $val){
            echo '--'.$val;
        }
        echo '                        '
    }
    //4、关闭资源
    $res->free();
    $mysqliObj->close();
?>        

pdo方式进行的查询

setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$r = $dbh->query('SELECT * FROM user');
var_dump($r);
foreach($r as $v) {
    var_dump($v);
}
?>

总结:
像discuz、phpcms、akcms等程序一般都会提供两种连接方式mysqli或pdo-mysql(前提是你的部署环境要支持),具体在使用到类以于以上的php程序时,可以根据自己的情况而定。

用过dedecms系统的朋友都会看到在后台的数据表管理中我们可以在后台看到表的数据表结构及字符长度了,下面我也整理了一个PHP生成MySQL数据字典 数据表结构例子,大家一起来看看。

程序代码如下

 代码如下 复制代码


<?php
/**
 * 生成mysql数据字典
 */
// 配置数据库
$database = array();
$database['DB_HOST'] = '127.0.0.1';
$database['DB_NAME'] = 'test';
$database['DB_USER'] = 'testuser';
$database['DB_PWD'] = '123456';


$mysql_conn = @mysql_connect("{$database['DB_HOST']}", "{$database['DB_USER']}", "{$database['DB_PWD']}") or die("Mysql connect is error.");
mysql_select_db($database['DB_NAME'], $mysql_conn);
$result = mysql_query('show tables', $mysql_conn);
mysql_query('SET NAME GBK', $mysql_conn);
// 取得所有表名
while ($row = mysql_fetch_array($result))
{
 $tables[]['TABLE_NAME'] = $row[0];
}
// 循环取得所有表的备注及表中列消息
foreach($tables as $k => $v)
{
 $sql = 'SELECT * FROM ';
 $sql .= 'INFORMATION_SCHEMA.TABLES ';
 $sql .= 'WHERE ';
 $sql .= "table_name = '{$v['TABLE_NAME']}' AND table_schema = '{$database['DB_NAME']}'";
 $table_result = mysql_query($sql, $mysql_conn);
 while ($t = mysql_fetch_array($table_result))
 {
  $tables[$k]['TABLE_COMMENT'] = $t['TABLE_COMMENT'];
 }
 $sql = 'SELECT * FROM ';
 $sql .= 'INFORMATION_SCHEMA.COLUMNS ';
 $sql .= 'WHERE ';
 $sql .= "table_name = '{$v['TABLE_NAME']}' AND table_schema = '{$database['DB_NAME']}'";

 $fields = array();
 $field_result = mysql_query($sql, $mysql_conn);
 while ($t = mysql_fetch_array($field_result))
 {
  $fields[] = $t;
 }
 $tables[$k]['COLUMN'] = $fields;
}
mysql_close($mysql_conn);

$html = '';
// 循环所有表
foreach($tables as $k => $v)
{
 $html .= '<table border="1" cellspacing="0" cellpadding="0" align="center">';
 $html .= '<caption>表名:' . $v['TABLE_NAME'] . ' ' . $v['TABLE_COMMENT'] . '</caption>';
 $html .= '<tbody><tr><th>字段名</th><th>数据类型</th><th>默认值</th><th>允许非空</th><th>自动递增</th><th>备注</th></tr>';
 $html .= '';

 foreach($v['COLUMN'] AS $f)
 {
  $html .= '<td class="c1">' . $f['COLUMN_NAME'] . '</td>';
  $html .= '<td class="c2">' . $f['COLUMN_TYPE'] . '</td>';
  $html .= '<td class="c3">' . $f['COLUMN_DEFAULT'] . '</td>';
  $html .= '<td class="c4">' . $f['IS_NULLABLE'] . '</td>';
  $html .= '<td class="c5">' . ($f['EXTRA'] == 'auto_increment'?'是':' ') . '</td>';
  $html .= '<td class="c6">' . $f['COLUMN_COMMENT'] . '</td>';
  $html .= '</tr>';
 }
 $html .= '</tbody></table></p>';
}
// 输出
echo '<html>
    <meta charset="utf-8">
    <title>自动生成数据字典</title>
    <style>
        body,td,th {font-family:"宋体"; font-size:12px;} 
  table,h1,p{width:960px;margin:0px auto;}
        table{border-collapse:collapse;border:1px solid #CCC;background:#efefef;} 
        table caption{text-align:left; background-color:#fff; line-height:2em; font-size:14px; font-weight:bold; } 
        table th{text-align:left; font-weight:bold;height:26px; line-height:26px; font-size:12px; border:1px solid #CCC;padding-left:5px;} 
        table td{height:20px; font-size:12px; border:1px solid #CCC;background-color:#fff;padding-left:5px;} 
        .c1{ width: 150px;} 
        .c2{ width: 150px;} 
        .c3{ width: 80px;} 
        .c4{ width: 100px;} 
        .c5{ width: 100px;} 
        .c6{ width: 300px;}
    </style>
    <body>';
echo '<h1 style="text-align:center;">数据字典</h1>';
echo '<p style="text-align:center;margin:20px auto;">生成时间:' . date('Y-m-d H:i:s') . '</p>';
echo $html;
echo '<p style="text-align:left;margin:20px auto;">总共:' . count($tables) . '个数据表</p>';
echo '</body></html>';

?>

111

 

[!--infotagslink--]

相关文章

  • php上传图片学习笔记与心得

    我们在php中上传文件就必须使用#_FILE变量了,这个自动全局变量 $_FILES 从 PHP 4.1.0 版本开始被支持。在这之前,从 4.0.0 版本开始,PHP 支持 $HTTP_POST_FILES 数组。这...2016-11-25
  • Smarty模板学习笔记之Smarty简介

    1、简介Smarty是一个使用PHP写出来的模板PHP模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目...2014-05-31
  • php Observer观察者模式之学习笔记

    当我们在星际中开地图和几家电脑作战的时候,电脑的几个玩家相当于结盟,一旦我们出兵进攻某一家电脑,其余的电脑会出兵救援。 那么如何让各家电脑知道自己的盟友被攻击了...2016-11-25
  • PHP 日期函数 学习笔记介绍

    举一个简单的date例子 我将使用echo命令把内容输出到我们的客户端(浏览器)。我将使用下面的代码做为基础代码。 代码如下 复制代码 <!DOCTY...2016-11-25
  • Android学习笔记之多界面切换实例

    一篇Android学习笔记之多界面切换实例,希望对各位朋友有所帮助。 用过VB 、 VC#的朋友都知道,在VB或VC#里要进行窗口(界面)切换很容易 例如在VB、C#里: 有 Fom1、...2016-09-20
  • php中的变量引用传值学习笔记

    引用:意思是将原始对象在内存中的地址传递给目标对象,就相当于原始对象和目标对象指向的是同一个内存地址。此时,如果对目标对象或者原始对象进行修改,内存中的数据也会改...2016-11-25
  • PHP中的cURL请求及示例学习笔记

    cURL是php中一个很强大的功能,可以模仿各种用户请求,如模仿用户登录,发送php cookie等等操作,下面我来整理一些相关的方法与各位同学看看 备注:使用curl_init函数,必须...2016-11-25
  • 那些年,我还在学习C# 学习笔记

    那些年学了ASP.NET后,才开始学习C#,说来也怪,怎么学了ASP.NET才来学习C#,其实没有什么的...2020-06-25
  • YII2 WIDGET的学习笔记

    CWidget是所有Widget的基类。CWidget是自包含组件,可以看出是MVC的简略版,CWidget相比Controller,既没有actions,也没有filters widget,英文意思为小工具,小挂件,在程序...2016-11-25
  • metasploit调用nexpose扫描学习笔记

    Metasploit是一个免费的、可下载的框架,通过它可以很容易地获取、开发并对计算机软件漏洞实施攻击。它本身附带数百个已知软件漏洞的专业级漏洞攻击工具 nexpose安...2016-11-25
  • php学习笔记之PHP扩展开发教程

    PHP扩展开发不是所有开发者都会操作的一个东西,下面我来演示一个关于PHP扩展开发实现过程,各位同学有需要可进入参考。 我们先假设需要这样一个扩展,提供一个叫tao_s...2016-11-25
  • C#预处理器指令的用法实例分析

    这篇文章主要介绍了C#预处理器指令的用法,以实例形式较为详细的分析了预处理器指令的原理与相应的用法,有助于深入理解C#程序的运行原理,需要的朋友可以参考下...2020-06-25
  • Yii2学习笔记之汉化yii设置表单的描述

    小编推荐的这篇文章介绍了Yii2学习笔记之汉化yii设置表单的描述,非常实用,有兴趣的同学快来看看吧。 一:汉化框架&#8195;&#8195;框架汉化在这里设置,如果不生效,前台后...2017-07-06
  • php Builder建造器模式学习笔记

    星际里面有不少的任务关,也可以自己编辑地图,画面上有各种地形,建筑和部队,存在一个问题,初始化画面的流程很乱。待解决的问题:完成初始化画面的工作,同时尽量减少各种绘制...2016-11-25
  • php中session学习笔记

    Session指的就是用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间。从上述的定义中我们可以看到,Session实际上是一个...2016-11-25
  • PHP单例模式学习笔记详解

    单例模式是php中一个为了简化大家开发及重复调用的一个功能,下面我来给各位朋友详细介绍单例模式用法。 1.单例模式的概念 顾名思义,单例模式只有一个实例,而且自行...2016-11-25
  • python 删除excel表格重复行,数据预处理操作

    这篇文章主要介绍了python 删除excel表格重复行,数据预处理操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-07
  • php正则表达式子模式的反向引用学习笔记

    本文章给大家分享一篇php正则表达式子模式的反向引用学习笔记,希望此教程对各位朋友有帮助哦。 需要用正则表达式获取字符串的标题。标题标签是h1~h6。 使用正则...2016-11-25
  • php 适配器模式的学习笔记

    适配器模式许多和php程序员都没有碰到关于适配器的应用了,这里小编整理了两个关于适配器的使用例子,下面我们就一起来看看吧,希望各位有帮助。 【目的】:将一个类的...2016-11-25
  • pytorch 图像预处理之减去均值,除以方差的实例

    今天小编就为大家分享一篇pytorch 图像预处理之减去均值,除以方差的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-05-02