heavstar 2019-06-21
使用 PDO 扩展类库
(推荐)
使用 Mysqli 扩展类库
(这是Mysql类库的升级版,但已经不推荐使用)
PDO
PDOStatement
PDOException
PDO
可以支持多种数据库,而且操作方法一致
Mysqli
只支持Mysql数据库
通过new PDO()来连接数据库,其中必须传入DSN数据源名称
try { $db = new PDO($dsn, $user, $password); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); }
DSN(数据源名称)是告诉PDO
使用哪款驱动来连接数据库,每一种数据库DSN都不同
Mysql的DSN
mysql:host=localhost;dbname=testoracle的DSN
oci:dbname=//localhost:232/mydb;charset=utf-8
关闭连接: $db = null;
设置连接选项
的2种方式
1、new PDO()的第四参数
//设置持久数据库连接必须使用这种方式,否则无效 $opt = array( PDO::ATTR_PERSISTENT => true, PDO::ATTR_TIMEOUT => 3600, PDO::ATTR_AUTOCOMMIT => true ); try { $db = new PDO($dsn,$user,$password,$opt); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); }
2、使用PDO对象的setAttribute()方法
try { $db = new PDO($dsn,$user,$password); $db -> setAttribute(PDO::ATTR_TIMEOUT, 3600); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); } //与getAttribute()方法配套
错误处理模式有哪三种?
1、PDO::ERRMODE_SILENT
(默认,不提示,需要结合errorCode()与errorInfo())
2、PDO::ERRMODE_WARNING
(警告)
3、PDO::ERRMODE_EXCEPTION
(报异常,推荐使用)
一般使用案例
try { $db = new PDO($dsn,$user,$password); $db -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { echo 'Connection failed: ' . $e->getMessage(); }
exec() ----不推荐,后面会有解释
exec() 主要:执行无结果集
的SQL语句 增删改创建 返回影响行数
query() ----不推荐,后面会有解释
query() 主要:执行有结果集
的SQL语句 查询 返回PDOStatement对象
对于某些SQL 既不是操作,也没有返回结果,使用上面某种方法都可以
prepare() ----推荐,后面会有解释
操作的Mysql的数据表
必须是InnoDB
关闭自动提交 $db->setAttribute(PDO::ATTR_AUTOCOMMIT, 0);
开启事务 $db->beginTransaction();
手动提交 $db->commit();
事务回滚 $db->rollBack();
事务完成后,最好把自动提交开启 $db->setAttribute(PDO::ATTR_AUTOCOMMIT, 1);
SQL注入
其实就是用户输入的数据带有攻击成分,所以用户输入的信息都是不可靠的
由于以上原因,导致之前exec()和query()方法不常用,因为不安全,但只要不是用过用户数据生成的SQL都可以使用exec()和query()
使用预处理语句来防止SQL注入
try{ //只是将这个语句放到数据库上,编译后等待,没有执行 $stmt = $db -> prepare('insert into user(name,pwd,age) values(?,?,?)'); //绑定参数(?) $stmt -> bindParam(1,$name); $stmt -> bindParam(2,$pwd); $stmt -> bindParam(3,$age); $name = 'wwww'; $pwd = '12112'; $age = 18; //执行存储在数据库中的语句 $stmt -> execute(); $name = 'bbb'; $pwd = 'ad22121'; $age = 20; //执行存储在数据库中的语句 $stmt -> execute(); }catch(PDOException $e){ echo $e->getMessage(); exit(); }
简化模式:
try{ //只是将这个语句放到数据库上,编译后等待,没有执行 $stmt = $db -> prepare('insert into user(name,pwd,age) values(?,?,?)'); //执行存储在数据库中的语句 $stmt -> execute(array('wwww','12112',18)); }catch(PDOException $e){ echo $e->getMessage(); exit(); }
2种占位符:命名占位符
和问号占位符
问号占位符就是上面那种
命名占位符,如下,推荐使用命名控制符
try{ //只是将这个语句放到数据库上,编译后等待,没有执行 $stmt = $db -> prepare('insert into user(name,pwd,age) values(:name,:pwd,:age)'); //绑定参数(?) $stmt -> bindParam(1,$name); $stmt -> bindParam(2,$pwd); $stmt -> bindParam(3,$age); $name = 'wwww'; $pwd = '12112'; $age = 18; //执行存储在数据库中的语句 $stmt -> execute(); $name = 'bbb'; $pwd = 'ad22121'; $age = 20; //执行存储在数据库中的语句 $stmt -> execute(); }catch(PDOException $e){ echo $e->getMessage(); exit(); }
注意事项
参数绑定不能应用到表名上
//错误 $sth = $dbh->prepare('SELECT name, colour, calories FROM ? WHERE calories < ?'); //正确 $sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE calories < ?');
参数绑定不能应用到列名
//错误 $sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE ? < ?'); //正确 $sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE calories < ?');
增删改
try{ $db = new PDO($dsn,$name,$pwd); $db -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); }catch(PDOException $e){ echo 'Connection failed: ' . $e->getMessage(); } try{ $stmt = $db -> prepare('insert into user(name,pwd,age) values(?,?,?)'); $stmt -> execute(array('wtao','23232',14)); $count = $stmt -> rowCount(); if($count === 0){ throw new PDOException(); } $id = $db -> lastInsertId(); }catch(PDOException $e){ echo 'Connection failed: ' . $e->getMessage(); }
查
try{ $db = new PDO($dsn,$name,$pwd); $db -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); }catch(PDOException $e){ echo 'Connection failed: ' . $e->getMessage(); } try{ $stmt = $db -> prepare('SELECT name, age, title FROM fruit WHERE id < ?'); $stmt -> execute(array(14)); while(list($name,$age,$title) = $stmt->fetch(PDO::FETCH_NUM)){ } }catch(PDOException $e){ echo 'Connection failed: ' . $e->getMessage(); }
$stmt -> execute()的返回值,如果在异常模式下,可以不用处理返回值的,只有在不是异常处理的模式下才需要判断处理
$db -> prepare(); 准备预处理语句都是单独的,返回PDOStatement对象也就是单独的,如果某个功能需要执行多条SQL语句,请先准备好多个PDOStatement对象,然后分别执行