PHP 数据库操作

172 阅读2分钟

PHP操作数据库的2种形式

  1. 使用 PDO 扩展类库(推荐)

  2. 使用 Mysqli 扩展类库(这是Mysql类库的升级版,但已经不推荐使用)

PDO 扩展包含哪三个类

  1. PDO

  2. PDOStatement

  3. PDOException

PDO 与 Mysqli 区别

  • PDO 可以支持多种数据库,而且操作方法一致

  • Mysqli 只支持Mysql数据库

如何使用PDO连接数据库?什么是DSN?如何关闭连接?

  • 通过new PDO()来连接数据库,其中必须传入DSN

    数据源名称

    try { db=newPDO(db = new PDO(dsn, user,user, password);} catch (PDOException e) {echo 'Connection failed: ' . e->getMessage();}

  • DSN(数据源名称)是告诉PDO使用哪款驱动来连接数据库,每一种数据库DSN都不同

Mysql的DSN mysql:host=localhost;dbname=test
oracle的DSN oci:dbname=//localhost:232/mydb;charset=utf-8

  • 关闭连接: $db = null;

PDO 与连接相关的选项如何设置?

  • 设置连接选项的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()方法配套

PDO 错误处理模式该如何设置?

  • 错误处理模式有哪三种?

1、PDO::ERRMODE_SILENT (默认,不提示,需要结合errorCode()与errorInfo())
2、PDO::ERRMODE_WARNING (警告)
3、PDO::ERRMODE_EXCEPTION (报异常,推荐使用)

  • 一般使用案例

    try { db=newPDO(db = new PDO(dsn,user,user,password); db -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);} catch (PDOException e) {echo 'Connection failed: ' . $e->getMessage();}

PDO 执行SQL有哪些方法?

  • exec() ----不推荐,后面会有解释

exec() 主要:执行无结果集的SQL语句

增删改创建

返回影响行数

  • query() ----不推荐,后面会有解释

query() 主要:执行有结果集的SQL语句

查询

返回PDOStatement对象

对于某些SQL 既不是操作,也没有返回结果,使用上面某种方法都可以
  • prepare() ----推荐,后面会有解释

PDO 事务如何实现?

  1. 操作的Mysql的数据表必须是InnoDB

  2. 关闭自动提交 $db->setAttribute(PDO::ATTR_AUTOCOMMIT, 0);

  3. 开启事务 $db->beginTransaction();

  4. 手动提交 $db->commit();

  5. 事务回滚 $db->rollBack();

事务完成后,最好把自动提交开启 $db->setAttribute(PDO::ATTR_AUTOCOMMIT, 1);

什么是SQL注入?SQL注入如何防止?

  • SQL注入其实就是用户输入的数据带有攻击成分,所以用户输入的信息都是不可靠的

由于以上原因,导致之前exec()和query()方法不常用,因为不安全,但只要不是用过用户数据生成的SQL都可以使用exec()和query()

  • 使用预处理语句来防止SQL注入

    try{//只是将这个语句放到数据库上,编译后等待,没有执行 stmt=stmt = db -> prepare('insert into user(name,pwd,age) values(?,?,?)');//绑定参数(?) stmt>bindParam(1,stmt -> bindParam(1,name); stmt>bindParam(2,stmt -> bindParam(2,pwd); stmt>bindParam(3,stmt -> bindParam(3,age); name=wwww;name = 'wwww'; pwd = '12112'; age=18;//执行存储在数据库中的语句age = 18;//执行存储在数据库中的语句 stmt -> execute(); name=bbb;name = 'bbb'; pwd = 'ad22121'; age=20;//执行存储在数据库中的语句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 < ?');

PDO 预处理语句如何增删改查?

  • 增删改

    try{ db=newPDO(db = new PDO(dsn,name,name,pwd); db -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);}catch(PDOException e){echo 'Connection failed: ' . e->getMessage();}try{ stmt = db>prepare(insertintouser(name,pwd,age)values(?,?,?));db -> prepare('insert into user(name,pwd,age) values(?,?,?)'); stmt -> execute(array('wtao','23232',14)); count=count = stmt -> rowCount();if(count===0)thrownewPDOException();count === 0){throw new PDOException(); } id = db -> lastInsertId();}catch(PDOException e){echo 'Connection failed: ' . $e->getMessage();}

  • try{ db=newPDO(db = new PDO(dsn,name,name,pwd); db -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);}catch(PDOException e){echo 'Connection failed: ' . e->getMessage();}try{ stmt = db>prepare(SELECTname,age,titleFROMfruitWHEREid<?);db -> prepare('SELECT name, age, title FROM fruit WHERE id < ?'); stmt -> execute(array(14));while(list(name,name,age,title)=title) = stmt->fetch(PDO::FETCH_NUM)){ }}catch(PDOException e){echo 'Connection failed: ' . e->getMessage();}

注意事项

  • $stmt -> execute()的返回值,如果在异常模式下,可以不用处理返回值的,只有在不是异常处理的模式下才需要判断处理

  • $db -> prepare(); 准备预处理语句都是单独的,返回PDOStatement对象也就是单独的,如果某个功能需要执行多条SQL语句,请先准备好多个PDOStatement对象,然后分别执行

    attachments-2020-10-pVDnzV115f9b6c8fef414.jpg来源:segmentfault.com/a/119000001…