mysql总结与预处理

一、连接到MySQL:

$dbc = mysqli_connect(host,user,password,databasename); 
等价于:
$dbc = mysqli_connect(host,user,pwd);
mysqli_select_db($dbc,db_name);

如果发生错误,可以调用:mysqli_connect_error() 返回错误信息,不带参数。
$dbc = @mysqli_connect(host,user,pwd,db) or die(‘无法连接到mysql:‘.mysqli_connect_error());

@是错误控制运算符,防止在web浏览器显示php错误。此外,@也可以放在mysqli_query前面。上面是一种首选做法,因为错误将由or die处理。die()会终止脚本执行。

可以将连接文件放在路径外。

设置编码:mysqli_query("set names gb2312");

二、执行查询: 
不管是select, delete, update,insert 查询都是用:
$result=mysqli_query($dbc,SQL); 
对于insert ,delete,update等查询不会返回结果,$result将返回true或false,因此可以用这个来判断下一步:
$result = mysqli_query($dbc,sql);
if($result) {//susses}

如果查询没有成功,必定发生某种mysql错误,可能调用
mysqli_error($dbc)    //注意和mysqli_connect_error()区别

三、关闭连接: 
mysqli_close($dbc) 这不是必需要的,php会在脚本最后自动关闭,但最好写上。

四、多条查询: 
mysqli_multi_query() 允许同时执行多条查询。但语法更复杂一点。特别是当返回结果时。

五、检索select查询结果: 
mysqli_fetch_array($result [, type]) 是最常用的,以数组格式一次返回一行数据。由它来配合while() 来遍历返回数据。带有一个可选参数type,用于指定返回的数组类型:关联的还是索引的,或二者均可。参数类型如下:
MYSQLI_ASSOC    示例:$rows[‘columnName‘]
MYSQLI_NUM 示例:$rows[0] ,这一种效率较高一点。
MYSQLI_BOTH 示例:$rows[0]或$rows[‘columnName‘]

当使用mysqli_fetch_array($result [, type]) 后,可以采取一个可选步聚的是:一旦查询结果完成了工作,即可释放这些信息,来消除$result占用的系统内存开销。这一步是可选的,PHP同样也在会结果时自动清理:
mysqli_free_result($result)    //注意参数是不是$rows!
流程如下:
while($rows=mysqli_fetch_array($result))   //或while($rows=mysqli_fetch_array($result,MYSQLI_ASSOC))
{//遍历
   .......code do something.......
   echo $rows[0]
   mysqli_free_result($result)

注意: 
mysqli_fetch_array()和mysqli_fetch_array($result,MYSQLI_NUM)等价。
mysqli_fetch_assoc()和mysqli_fetch_array($result,MYSQLI_ASSOC)等价。

六、确保sql安全,使用转义函数: 
mysqli_real_escape_string($dbc,para) 
该函数接收字符串作为参数,用于检验用户提交的并将组合到sql查询语句的变量值,它将转义那些有可能无意或带恶意的字符。如单引号,在外国人的姓名有可能会包含该符号(如O‘Toole),这时就需要用它。
案例:
$name = $_POST[‘name‘];
$name = mysqli_real_escape_string($dbc,$name);
$query = "Select ... From tb where name=‘$name‘"; //这样可以确保带入sql 时参数的安全。
注意:如果在使用php6之前的版本,若启用MAGIC QUOTES魔法引用时,那么在使用mysqli_real_escape_string前,需要用stripslashes(para)删除魔法引用添加的任何斜杠,如下:
$fn = mysqli_real_escape_string($dbc,trim(stripslashes($_POST[‘firstName‘])));

备注:

在PHP5.3版本之前, mysqli_real_escape_string()函数存在路径泄漏问题,远程攻击者可以利用漏洞获得服务器端脚本的实际路径。即如果传递的参数值为数组而不是字符串的情况下会发出警告,警告消息中会包含有当前服务端运行脚本的完整路径信息。
 测试方法:
http://localhost/cms/sqlfilter/sqlsanatizer.php?params []= 
Warning: mysqli_real_escape_string() expects parameter 1 to be string, 
array given in /var/www/vhosts/cms/sqlfilter/sqlsanatizer.php 

七、统计select返回的记录数:
 
使用mysqli_num_rows($result)统计select 返回的结果行数。$num=mysqli_num_rows($r),对于上面所说的while流程,可以更改成以下更严谨的写法,而不只是分析查询是否成功,因为如果数据库为空的话,就不会出错。
$sql = "select * from tb where id=$id";
$r = @mysqli_query($dbc,$sql);
$num = mysqli_num_rows($r);
if($num>0){ //这样比if($r)更准确。不是仅仅分析是否成功运行。
     // Do something;
     
     mysqli_free_result($r)
}
mysqli_close($dbc);

八、返回insert ,update,delete受影响行数: 
和上面不同的是,如果查询不是select则用mysqli_affected_rows()函数返回受影响行数。用法如下:
$num = mysqli_affected_rows($dbc); //注意参数是$dbc;
如:
$q = "update tb set pass=SHA1(‘$newpassword‘) where id=$row[0]";
$r = @myslqi_query($dbc,$q);
if(mysqli_affected_rows($dbc)==1){
      //Do something
}else{
     echo mysqli_error($dbc);
     exit(); //终止脚本。

注意:
1、如果使用truncate tb清空表时,则mysqli_affected_rows()会返回0,即使查询成功执行并且删除了每一行。
2、如果用update查询时,但实质上没有更改任何列的值,比如用相同的密码代替一个旧密码,则也会返回0。

九、批量查询:预处理语句(第12章第4节:P311) 
版本:MYSQL 4.1开始添加预处理。php5可以使用。

预处理的好处:
1、更大安全性。2、更好性能。3、批量查询。

对于预处理语句,只会把查询本身发送给mysql,并且只会解析一次,然后单独把值发送给mysql。
$q = ‘Insert into tb(num) values (?)‘;
$stmt = mysqli_prepare($dbc,$q);
mysqli_stmt_bind_param($stmt,‘i‘,$n);
for($n=1;$n<=100;$n++)
{
    mysqli_stmt_execute($stmt);

可以通过insert , update , delete , select 查询创建预处理,步骤:
1、定义查询:
$q = "select firstname,lastname from users where uid = ?";   //(正常则是uid=$id)
2、将查询传给mysql预处理:
$stmt = mysqli_prepare($dbc,$q);   //此时mysql会解析查询,但不会执行。
3、将变量绑定到查询占位符"?",如下:
mysqli_stmt_bind_param($stmt,‘i‘,$id); 
其中‘i‘的含义是mysql_stmt_bind_param函数期望接收到的值为int类型,共有以下几种:
--------------------------------------------------------------------------------
字母                    表示绑定的值类型
d                             Decimal
i                               Integer
b                              Blob (二进制类型)
s                               所有其它类型
----------------------------------------------------------------------------------
如果查询语句有多个变量,如:
$q = "select uid,firstname from users where email=? AND pass=SHA1(?)"; //注意这里都没有对?问号加单引号,即使是字符型。这是和标准查询的区别。
多个变量直接在绑定时按顺序在引号内列出即可。如下:
$stmt = mysqli_prepare($dbc,$q);
mysqli_stmt_bind_param($stmt,‘ss‘,$e,$p);
还需要注意的时,在调用绑定函数前,可以不需要先对变量定义设置,如上面的$e,$p在下面才设置,这不会出错。
4、完成绑定后,可以给php变量赋值(如果还没有值的话)。然后执行语句。
$id=15;
mysqli_stmt_execute($stmt);
5、关闭预处理:
mysqli_stmt_close($stmt);
6、关闭连接
mysqli_close($dbc);
执行预处理时,如有出错则用mysqli_stmt_error($stmt)调用。

示例:
$dbc =mysqli_connect(‘localhost‘,‘username‘,‘pwd‘,‘forum‘);
$q = ‘insert into messages(forumid,parentid,userid,subject,body,forumdate) values(?,?,?,?,?,NOW())‘;
$stmt = mysqli_prepare($dbc,$q);
mysqli_stmt_bind_param($stmt,‘iiiss‘,$forumid,$parentid,$userid,$subject,$body);
$forumid = (int)$_POST[‘forumid‘];
$parentid=(int) $_POST[‘parentid‘];
$user_id =3;
$subject = strip_tags($_POST[‘subject‘]); //strip_tags
$body = strip_tags($_POST[‘body‘]);
mysqli_stmt_execute($stmt);
if(mysqli_stmt_affected_rows($stmt)==1)
{
      //do ....
}else{
     echo mysqli_stmt_error($stmt);
}
mysqli_stmt_close($stmt);
mysqli_close($dbc);

以上演示了预处理的一种语句,实际上预处理有两种语句:
1、绑定参数(bound parameter):如上面的示例
2、绑定结果(bound result):将查询结果绑定到php变量。

十、阻止sql注入:(第12章第4节:P311) 
1、验证在查询中要使用的数据,如果有可能,就可执行类型强制转换。如:
$forumid = (int)$_POST[‘forumid‘];
if($forumid>0) ....   //如果强制转换成int完=0时,则不符数据型要求。
2、使用mysqli_real_escape_string($dbc,para)
3、使用mysqli_real_escape_string($dbc,para)替代办法:预处理,参上面。

十一、早先的php和mysql连接方式: 
mysql_connect,在写法上只差上面一个字母i,但用法差不多。以下简单示例:
$conn = mysql_connect("127.0.0.1","mysqltest","123456");
mysql_select_db("shop"); //如果用$selectdb = mysql_select_db("shop");则$selectdb=1

mysql_query("set names gb2312"); //mysql_query("set names utf8"); 
$exec="select * from product";
$result=mysql_query($exec,$conn); //或:$result=mysql_query($exec);

while($rs=mysql_fetch_object($result)) 
{
echo "品名:[".$rs->pname . "] &nbsp;&nbsp;";
echo "价格:".
   $rs->price . "&nbsp;&nbsp;";
echo "入库时间:".$rs->addTime . "&nbsp;&nbsp;";
echo "<br />";
}
echo $result;

如果要进行结果判断有无再输出,则可以用:
$conn = mysql_connect("127.0.0.1","mysqltest","123456");
mysql_select_db("shop");

mysql_query("set names gb2312"); //mysql_query("set names utf8"); 
$exec="select * from product";
if($result=mysql_query($exec,$conn)){
while($rs=mysql_fetch_object($result))
{
   echo "品名:[".$rs->pname . "] &nbsp;&nbsp;";
   echo "价格:".
    $rs->price . "&nbsp;&nbsp;";
   echo "入库时间:".$rs->addTime . "&nbsp;&nbsp;";
   echo "<br />";
}
}

附:
A、在insert后取得最后一条记录:2种方法: 
1、使用mysql的:last_insert_id() 函数。“insert into ....;select last_insert_id()”
2、使用php 的 mysql_insert_id() 或mysqli_insert_id() 返回同样的值:
PHP的 mysql_insert_id ( [resource $link_identifier] ) 函数可以返回你需要的ID。 可选参数是php连接mysql的句柄。 每个连接都有不同的句柄。如:
    mysql_query("INSERT INTO mytable (product) values (‘kossu‘)");
    printf ("Last inserted record has id %d\n", mysql_insert_id());

B、几个函数: 
trim() , ltrim(), rtrim()
exit(),
strip_tags()去掉字符串中包含的任何 HTML 及 PHP 的标记字符串。若是字符串的 HTML 及 PHP 标签原来就有错,例如少了大于的符号,则也会返回错误。而本函数和 fgetss() 有着相同的功能。
$text = ‘<p>Test paragraph.</p><!-- Comment --> <a href="#fragment">Other text</a>‘;
echo strip_tags($text); //结果:Test paragraph. Other text
// 许可用 <p> and <a>
echo strip_tags($text, ‘<p><a>‘); //结果:<p>Test paragraph.</p> <a href="#fragment">Other text</a>

时间: 2024-10-26 02:51:14

mysql总结与预处理的相关文章

php中对MYSQL操作之预处理技术(2)数据库dql查询语句

<?php //预处理技术 //创建一个mysqli对象 $mysqli = new MySQLi("主机名","mysql用户名","密码","数据库名"); //判断是否链接成功 if($mysqli->connect_error){ die($mysqli->connect_error); } //创建预编译对象 $sql = "select id,name,age,qq from 表名 wh

php中对MYSQL操作之预处理技术(1)数据库dml操作语句

<?php //预处理技术 //创建一个mysqli对象 $mysqli = new MySQLi("主机名","mysql用户名","密码","数据库名"); //判断是否链接成功 if($mysqli->connect_error){ die($mysqli->connect_error); } //创建预编译对象 $sql = "insert into 表名 (name,qq,age) val

MySQL的预处理技术

所谓的预处理技术,最初也是由MySQL提出的一种减轻服务器压力的一种技术! 传统mysql处理流程 1,  在客户端准备sql语句 2,  发送sql语句到MySQL服务器 3,  在MySQL服务器执行该sql语句 4,  服务器将执行结果返回给客户端 这样每条sql语句请求一次,mysql服务器就要接收并处理一次,当一个脚本文件对同一条语句反复执行多次的时候,mysql服务器压力会变大,所以出现mysql预处理,减轻服务器压力! 预处理的基本策略: 将sql语句强制一分为二: 第一部分为前面

php连接mysql的三种方式和预处理下的sql注入

0x00 前言 学习了一下堆叠注入和这三种连接方式预处理下的SQL注入问题. 0x01 基础知识 参考: https://www.cnblogs.com/joshua317/articles/5989781.html https://www.cnblogs.com/geaozhang/p/9891338.html 1.即时 SQL 一条 SQL 在 DB 接收到最终执行完毕返回,大致的过程如下: 1. 词法和语义解析: 2. 优化 SQL 语句,制定执行计划: 3. 执行并返回结果: 如上,一条

PDO中的预处理

PDO中的基本的原理和步骤和MySQL中的预处理都是一样的,只不过就是把MySQL中的预处理所有命令行的语法封装成了PDO对象的几个公开的方法而已! 1.发送预处理语句 此时,我们需要调用pdo对象的prepare方法,得到一个PDOStatement结果对象! 2.绑定参数 调用PDOStatement对象中的bindParam方法: 3.执行预处理语句 调用PDOStatement对象中的execute方法,如果执行成功,就返回true,如果执行失败就返回false! 下面是代码 <?php

Mycat sql预处理功能分析

前言 Mycat从1.6版本开始支持预处理.目前1.6分支还是开发测试阶段.Mycat发展自Cobar,在Cobar源码里面可以看到预处理功能的影子(未完全实现,当然你如果往Cobar上面调用预处理命令,那么Cobar会返回结果,告诉你,我是不支持预处理sql的!).我在以前的公司接到需求,需要在Mycat中实现预处理,所以花了时间研究了这部分代码并以自己的思路去实现.后面我将代码贡献给社区,在社区的帮助下,修复了一些bug,最终整合到1.6分支上. Mycat预处理的使用场景不多,针对java

数据库编程5 MySQL C API 开发

[本文谢绝转载原文来自http://990487026.blog.51cto.com] 数据库编程5 MySQL C API 开发 MySQL官方文档: MySQL  环境搭建 ubuntu搭建MySQL开发环境: MySQL服务命令 检查MySQL运行状态: MySQL SQL 登陆测试 创建一个数据库 显示数据库创建过程: 创建一个使用UTF8字符集的数据库 创建一个使用UTF8字符集的数据库,带校对规则 把数据库修改成UTF8字符集 选择数据库,创建表: 查表结构: mysql中的数据类型

MYSQL 基础操作

1.MySQL基础操作 一:MySQL基础操作 1:MySQL表复制 复制表结构 + 复制表数据 create table t3 like t1; --创建一个和t1一样的表,用like(表结构也一样) insert into t3 select * from t1; --t1的数据全部拿过来,注意是表结构一致才select* ,否则选择相应的的字段列插入 create table t1( id int unsigned not null auto_increment primary key,

MySQL性能优化(二)

1.MySQL基础操作 一:MySQL基础操作 1:MySQL表复制 复制表结构 + 复制表数据 create table t3 like t1; --创建一个和t1一样的表,用like(表结构也一样) insert into t3 select * from t1; --t1的数据全部拿过来,注意是表结构一致才select* ,否则选择相应的的字段列插入 create table t1( id int unsigned not null auto_increment primary key,