惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Darknet – Hacking Tools, Hacker News & Cyber Security
Jina AI
Jina AI
博客园_首页
J
Java Code Geeks
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
Hugging Face - Blog
Hugging Face - Blog
S
SegmentFault 最新的问题
MyScale Blog
MyScale Blog
P
Proofpoint News Feed
L
Lohrmann on Cybersecurity
Forbes - Security
Forbes - Security
大猫的无限游戏
大猫的无限游戏
Vercel News
Vercel News
Y
Y Combinator Blog
Google DeepMind News
Google DeepMind News
The Register - Security
The Register - Security
N
News | PayPal Newsroom
S
Security Archives - TechRepublic
量子位
Cisco Talos Blog
Cisco Talos Blog
V
V2EX
C
Cisco Blogs
The Cloudflare Blog
Stack Overflow Blog
Stack Overflow Blog
L
LangChain Blog
Scott Helme
Scott Helme
S
Securelist
Security Latest
Security Latest
爱范儿
爱范儿
TaoSecurity Blog
TaoSecurity Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
I
Intezer
L
LINUX DO - 最新话题
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Check Point Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
美团技术团队
Know Your Adversary
Know Your Adversary
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
PCI Perspectives
PCI Perspectives
月光博客
月光博客
T
Tailwind CSS Blog
Cloudbric
Cloudbric
小众软件
小众软件
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
K
Kaspersky official blog
D
DataBreaches.Net
博客园 - 【当耐特】
有赞技术团队
有赞技术团队

博客园 - 银翼

【MySQL】Windows下如何彻底卸载MySQL? 【MySQL】Windows下如何重置root账号密码? 【Java】Task07实验4第5题解析 【辅导】Task12 类的定义与继承练习 【辅导】Task11 如何获取文件上传错误信息 PHP开发环境配置 XAMPP更换Apahce服务端口号 《Web应用开发技术(PHP)》往届学生优秀作业 【辅导】Task19 实现用户登录 主要知识点 【辅导】Task18 更新与插入删除操作 主要知识点 【辅导】Task16 使用MySQL数据库 主要知识点 【辅导】Task15 熟悉错误与异常处理 主要知识点 【辅导】Task14 使用正则表达式 主要知识点 【辅导】Task13 使用会话管理 主要知识点(2) 【辅导】Task13 使用会话管理 主要知识点(1) 【辅导】Task12 使用类和对象 主要知识点(2) 【辅导】Task12 使用类和对象 主要知识点(1) 【辅导】Task11 熟悉PHP文件操作 主要知识点 【辅导】Task10 掌握PHP表单处理 主要知识点
【辅导】Task17 查询数据 主要知识点
银翼 · 2020-05-20 · via 博客园 - 银翼

本任务以示例数据库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条件查询的实现。

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