♂WhiteWin♂

导航

【辅导】Task17 查询数据 主要知识点

本任务以示例数据库Sakila为例,介绍如何使用面向对象mysqli,实现对数据库的参数化查询,重点是掌握PHP预处理语句的使用。

1、面向对象mysqli

Task16已经介绍了PHP访问数据库的三种方式:面向过程mysqli面向对象mysqliPDO。建议大家使用面向对象mysqli访问MySQL数据库。在需要访问其它类型数据库的时候,建议使用PDO。

使用面向对象mysqli访问(查询)数据库的基本过程如下:

 

 

2query()方法

Mysqli类的query()方法,第2个参数默认值是MYSQLI_STORE_RESULT,另一个可选值是MYSQLI_USE_RESULT

MYSQLI_STORE_RESULT:到数据库执行查询,并将结果保存到mysqli_result类对象。之后fetch时相当于在本地取数据。

MYSQLI_USE_RESULT:启动逐行检索,实际上本次并没有查询,直到fetch时,每次向数据库请求一个结果行。

总结:MYSQLI_STORE_RESULT 将查询结果缓存,处理效率较高,但内存开销比较大;MYSQLI_USE_RESULT有较低内存需求,但处理过程中需保留数据库连接。建议,使用MYSQLI_STORE_RESULT时优化SQL查询返回尽量少的数据;在需要返回大量数据时使用MYSQLI_USE_RESULT

参阅:mysql中的MYSQLI_USE_RESULT和MYSQLI_STORE_RESULT模式分析

2SQL查询

对数据库的任何操作,不管是DQL(SELECT),还是DML(INSERT,UPDATE,DELETE),或者DDL(CREATE),只要写成SQL语句,交给mysqli类对象的query()方法就可以。因此:

可以执行简单的SELECT的查询,如查询Customer表某些列;

可以执行较为复杂的查询,如多表连接查询;

可以查询视图(因为可以把视图看成是单表);

可以执行存储过程;参看《PHP调用MYSQL存储过程实例》

也可以对数据库进行添加、更新、删除操作,下个任务会讲;

还可以建表、删表、增加或删除数据表列,等等。

只要能描述成SQL语句,都可以交给query()函数去执行。

3SQL查询时,遇到特殊列,如何处理?

本任务教学视频中提到,当有如下SQL查询时:

 

对于带有空格的列名,使用$row = $result->fetch_assoc();方法提取记录时,没有问题,可以使用$row['zip code']获取该列值。但使用$row = $result->fetch_object();方法提取记录时,使用$row->zip code或$row->zip_code都是错误的。解决办法有二:

(1)如上图所示,给列名`zip code`起别名zip_code,可以使用$row->zip_code获取该列值。

(2)直接使用$row->{'zip code'}。

4、有参数的SQL语句(参数化查询)

为什么SQL语句需要有参数?

例如:我需要查询Customer表中id号为15的客户信息,SQL语句是:$sql='SELECT first_name,last_name FROM customer WHERE customer_id=15';

但这里的客户ID号一般是由用户在网页表单上输入的,如:

$id = $_POST['id'];

这时你就要把用户输入的$id拼接在原来sql语句字符串里面,写成这样:

$sql='SELECT first_name,last_name FROM customer WHERE customer_id='.$id;

虽然PHP支持字符串里面变量转义,但在原理上是与字符串拼接是一回事的:

$sql="SELECT first_name,last_name FROM customer WHERE customer_id={$id}";

字符串拼接带来的最主要的问题是SQL注入漏洞,造成你的网站存在很大的安全问题。比如,在输入id号的文本框中用户输入的是这样的内容:

20;insert into staff(`username`,`password`) values('hacker', 'cracked')

这样,他就很轻松地在你的数据库里面增加了一个店员(管理员)了。如果你是用MySQL数据库的root账户来建立查询的,他简直就可以为所欲为了(添加一个管理员账户?改root账户密码?)

所有我们必须使用有参数的SQL语句。因为参数限定了用户输入值只能与参数对应列匹配,从而避免了SQL注入。

Mysqli的SQL语句的参数只能使用?, 对参数赋值只能按先后顺序进行赋值。PDO可以使用命名参数。

 

 

5、有参数的SQL语句,使用prepare()函数来建立预处理语句

 

注意几点:

(1)使用mysqli时,bind_param()方法绑定参数的顺序与类型一定要与sql语句中?的顺序与类型保持严格一致;

s-string, i-integer, d-double, b-blob

(2)执行Select查询时,需要使用bind_result()方法绑定结果变量,结果变量顺序与SQL语句中列名顺序一致。

(3)使用execute()方法执行查询后,要使用store_result()方法将结果缓存,保存到mysqli_stmt对象,之后使用fetch()方法才能提取到每行记录的数据。

6、掌握mysqli_stmt对象的以下方法

bind_param():绑定参数变量。

bind_result():绑定结果变量,对select查询需要。

execute():执行预处理语句定义的查询。

store_result():保存查询结果,对select查询必须。

fetch():从结果中提取记录到绑定的结果变量

7、课后练习

先参照课件,完成对Sakila数据库Customer表的参数化查询。不懂的地方再回顾视频,或者QQ上问我。

有基础以后,试试自己编写检索程序,按特定条件查询Sakila数据库其它表的数据(如查询有什么名字的影片,查询xxx主演电影有哪些,顾客中有哪些是中国的)

也可以使用自己创建的数据库,或你前期上其它课程建立的数据库,练习下PHP条件查询的实现。

考虑到大家线下练习比较困难,最近基本上没有布置实验作业,有条件的请根据上述要求做下练习。返校后,将把一些本应布置的实验作业内容整合到实训中去练习。

posted on 2020-05-20 22:27  银翼  阅读(142)  评论(0编辑  收藏  举报