索引
索引看着挺高大上的一个名字,说白了就是我们书最新面的目录。
假如你用新华字典来查找“张”这个汉字,不使用目录的话,你可能要从新华字典的第一页找到最后一页,可能要花二个小时。字典越厚呢,你花的时间就越多。现在你使用目录来查找“张”这个汉字,张的首字母是z,z开头的汉字从900多页开始,有了这条线索,你查找一个汉字可能只要一分钟,由此可见索引的重要性。
索引用于快速找出在某个列中有一特定值的行。
不使用索引,MySQL必须从第1条记录开始然后读完整个表直到找出相关的行。表越大,花费的时间越多。如果表中查询的列有一个索引,MySQL能快速到达一个位置去搜寻到数据文件的中间,没有必要看所有数据。
当然索引也不易过多,索引越多写入,修改的速度越慢。因为,写入修改数据时,也要修改索引。
MySQL的索引类型
索引类型 功能说明
普通索引 最基本的索引,它没有任何限制
唯一索引 某一行企用了唯一索引则不准许这一列的行数据中有重复的值。针对这一列的每一行数据都要求是唯一的
主键索引 它是一种特殊的唯一索引,不允许有空值。一般是在建表的时候同时创建主键索引,常用于用户ID。类似于书中的页码
全文索引 对于需要全局搜索的数据,进行全文索引
注意:以下部份请学习完12.7后再进行学习。
普通索引
类型 详细说明
基本语法 alter table 表 add index(字段)
示例 ALTER TABLE money ADD INDEX(username);
示例解释 为money表的username字段增加索引
唯一索引
类型 详细说明
基本语法 alter table 表 add UNIQUE(字段)
示例 ALTER TABLE money ADD UNIQUE(email);
示例解释 为money表的email字段增加唯一索引
全文索引
类型 详细说明
基本语法 alter table 表 add FULLTEXT(字段)
示例 ALTER TABLE money ADD FULLTEXT(content);
示例解释 为money表的content字段增加唯一索引
主键索引
类型 详细说明
基本语法 alter table 表 add PRIMARY KEY(字段)
示例 ALTER TABLE money ADD PRIMARY KEY(id);
示例解释 为money表的id字段增加主键索引
创建表时也可以声明索引
创建表时可在创建表语句后加上对应的类型即可声明索引:
PRIMARY KEY(字段) INDEX [索引名] (字段) FULLTEXT [索引名] (字段) UNIQUE[索引名] (字段)
注:中括号中的索引名,代表可选。
整体示例如下:
CREATE TABLE test ( id INT NOT NULL , username VARCHAR(20) NOT NULL , password INT NOT NULL , content INT NOT NULL , PRIMARY KEY (id), INDEX pw (password), UNIQUE (username), FULLTEXT (content) ) ENGINE = InnoDB;
DCL语句
创建库用户
添加权限
类别 详细解示
基本语法 grant 权限 on 库.表 to '用户'@'主机' identified by '密码';
示例grant select, insert on test.* to 'liwenkai'@'localhost' identified by '4311';
示例说明 给予liwenkai用户,在本机连接test库所有表的权限。操作的这些表具有查询和写入权限
注:可以针对一个用户增加多条权限。
删除权限
类别 详细解示
基本语法 revoke 权限 on 库.表 from '用户'@'主机';
示例 revoke select, insert on test.* to 'liwenkai'@'localhost' identified by '4311';
示例说明 给予liwenkai用户,在本机连接test库所有表的权限。操作的这些表具有查询和写入权限
参数说明
符号 说明
grant all 在grant后接all说明给予所有权限
revoke all 在revoke后接all说明删除所有权限
权限 on . . 所明给予所有库所有表的操作权限
‘用户’@‘主机’ 主机里面若为%。任意来源的主机均可以使用这个用户来访问
创建数据库用户liwenkai ,具有对test数据库中所有标的 select / insert 权限
示例:增加权限
mysql> grant select, insert on test.* to 'liwenkai'@'localhost' identified by '4311'; Query OK, 0 rows affected (0.00 sec)
示例:移除权限
mysql> revoke insert on test.* from 'liwenkai'@'localhost'; Query OK, 0 rows affected (0.30 sec)
注:
上面的一些语句用的较少。你可以将知识点的掌握级别设置为了解级别。
更多的时候,权限设置项特别多,人们往往记不住具体的命令。更多 的时候人们使用专门的工具来操作权限。
PHP操作mysql数据库
通过上一章的学习,我们学习完了MySQL。PHP向MySQL发送数据、PHP操作MySQL数据库是重点中的重点。
为大家举一些例子:
要注册一个用户,是将表单的数据POST发送给PHP写入数据库
购买一个商品,是将商品信息和用户信息通过PHP写入到数据库
在线付费,是将用户的充值信息通过PHP写入数据库
修改头像上传的头像地址得到后,通过PHP修改数据库里头像字段的值
... ...太多太多的应用场景。从网页、移动端、QQ微信公众号都在使用PHP连接数据库进行操作。
为了更方便大家的学习,我们将连接数据库的知识进行了步骤化。你会发现,你很轻松的就学会了PHP连接数据库的知识。
我们准备的数据库连接的知识,几乎适用于所有的数据库连接的方式。
您也可以使用这一套方案和步骤用于PDO,PgSQl等数据库连接函数使用。
在正式开始学习前,我们需要开启mysqli扩展,使用phpinof()你可以看到如下展示就说明开启成功:
若没有mysqli这个扩展模块。在《10.PHP图像处理》章节跟大家一起学习过,若没有看到mysqli扩展在windows服务器下,打开php.ini文件,将php_mysqli.dll打开即可。
注意:
*从PHP7开始默认不再支持mysql扩展,即不再支持mysql_系列函数。请使用mysqli连接数据库。
mysqli即支持php5也支持php7。
php数据库连接步骤
我们为大家将数据库连接整理成了最重要的8个步骤,我戏称它为:“数据库连接天龙八步”。
这八个步骤如下,并且将每一步使用的函数都做了说明:
第一步: 连接数据库服务器
类型 说明 函数 mysqli_connect 功能 连接到mysql数据库服务器 参数1 主机 参数2 数据库服务器登陆名 参数3 密码 参数4 数据库的名称 参数5 数据库服务器端口不填默认3306 若参数4,数据库名称在此步已填并择,不需要执行第三步。
第二步: 判断错误
类型 说明 函数 mysqli_errno 功能 返回连接错误号,无错误返回0 参数1 传入mysqli_connect返回的资源 类型 说明 函数 mysqli_error 功能 返回连接错误字符串 参数1 传入mysqli_connect返回的资源
第三步: 选择数据库
类型 说明 函数 mysqli_select_db 功能 选择本连接中的数据库 参数1 传入mysqli_connect返回的资源 参数2 需要连接的数据库名 若在第一步已填数据库,不需要更换成其他数据库,则不需要执行第三步。
第四步: 设置字符集
类型 说明 函数 mysqli_set_charset 功能 设置与mysql服力器连接,结果,校验字符集 参数1 传入mysqli_connect返回的资源 参数2 字符集类型 更多注意项,请关注本书《13.6 数据显示乱码终极解决方案》
第五步: 准备SQL语句
其实就是一个SQL语句的字符串。
例如:
<?php $sql = "insert into user(username,password) values('$username','$password')"; $con = mysql_connect("localhost","peter","abc123"); if (!$con) { die('Could not connect: ' . mysql_error()); } // some code ?>
我们通常要把变量赋值在SQL语句中使用。可是变量或者SQL语句出错了,非常不好排查。
我们根据实际工作经验增加了这一步。
如果在执行此步的时候报错了,我们可以把SQL语句打印出来,粘贴到phpMyAdmin或者相关工具中。
排错时,如果执行成功就说明不是SQL语句的问题。如果执行失败,请仔细检查SQL语句。
第六步: 发送SQL语句
类型 说明 函数 mysqli_query 功能 发送SQL语句 参数1 传入mysqli_connect返回的资源 参数2 传入发送的SQL语句
SQL语句准备完成,需要通过mysqli_query将SQL语句发送给MySQL服务器。
MySQL服务器会执行发送过来的SQL语句进行执行。
第七步: 判断是否执行正常或者遍历数据
读取
第6步中,发送的是select类别的语句,通常需要将结果输出显示出来。就需要用到遍历显示数据的函数。
类型 说明
函数 mysqli_fetch_array
功能 得到result结果集中的数据,返回数组进行便利
参数1 传入查询出来的结果变量
参数2 传入MYSQLI_NUM返回索引数组,MYSQLI_ASSOC返回关联数组,MYSQLI_BOTH返回索引和关联
类型 说明
函数 mysqli_fetch_assoc
功能 得到result结果集中的数据,返回关联数组进行便利
参数1 传入查询出来的结果变量
类型 说明
函数 mysqli_fetch_row
功能 得到result结果集中的数据,返回索引数组进行便利
参数1 传入查询出来的结果变量
类型 说明
函数 mysqli_fetch_object
功能 得到result结果集中的数据,返回对象进行遍历
参数1 传入查询出来的结果变量
类型 说明
函数 mysqli_num_rows
功能 返回查询出来的结果总数
参数1 传入查询出来的结果变量
类型 说明
函数 mysqli_num_rows
功能 返回查询出来的结果总数
参数1 传入查询出来的结果变量
注 实际工作中用得非常少,了解
写入
第6步中,如果发送的是insert的语句,通常需要得到是否执行成功,或者同时拿到自增的ID。
类型 说明
函数 mysqli_fetch_field
功能 遍历数据行
参数1 传入查询出来的结果变量
修改和删除
第6步中,如果发送的是update和delete类别的语句。只需要判断是否执行成功即可。
我们将这些常用函数列出数据表给给大家查看。
第八步: 关闭数据库
类型 说明
函数 mysqli_close
功能 关闭数据库连接
参数1 传入mysqli_connect返回的资源
数据库连接是一个资源类型。我们在之前的章节中讲解资源类型的时候跟大家说过。凡是涉及到数资源类型的有打开就有关闭。这样能够保证PHP更高效的处理和回收资源。
因此,数据库连接成功后,不需要使用的时候。我们可以关闭这个连接。
其他:显示服务器信息函数
类型 说明
函数 mysqli_get_server_info
功能 返回服务器信息
参数1 传入mysqli_connect返回的资源
类型 说明
函数 mysqli_get_server_version
功能 返回服务器版本
参数1 传入mysqli_connect返回的资源
注意:
mysqli只学过程化的方法即可。在面向对象阶段实际工作中完全抛弃了mysqli的对象用法,而是使用的是PDO对象连接数据库的方式。
案例:用户注册
我们做一个最简单的注册页面。注册页面中有三个参数:
1.用户名
2.密码
3.重复密码
用户写好三个参数后,点击提交的时候向connect.php页面中传入POST记录。
我们可以把POST记录处理后写入到MySQL数据库中,即完成了用户注。
代码如下:
<form action="connect.php" method="post"> 用户名:<input type="text" name="username"><br /> 密码:<input type="password" name="password"><br /> 重复密码:<input type="password" name="repassword"><br /> <input type="submit" value="提交"> </form>
为了更快的表现我们的代码界面没有进行美化。以最快的速度带大家完成用户注册。
一、 判断重复密码
由于有重复密码,如果用户两次输入的密码不一致也就是有没有进行下一步的任何意义。
在网页中很多地方还是使用到了重复密码。因为,害怕的是用户产生手误。将密码填写出错。
用户在输入密码的时候可能在左右两边多打两个空格。因此,我们会使用trim将密码和重复密码的两边去掉空格。
if(trim($_POST['password']) != trim($_POST['repassword'])){ exit('两次密码不一致,请返回上一页'); }
二、 准备好写入的数据
我们需要把用户的输入数据和隐藏的数据都写入到数据库。
可见数据有:
变量 说明
$_POST['username'] 用户名 $_POST['password'] 密码
我们需要把用户名去掉两边的空格,这样避免输入不必要的这些信息。
在mysql这一章节我们讲过,用户的密码不要让包括公司内部人员可见。保证密码是不可逆向的。在初级阶段大家学习一下MD5即可。以后我们再教大家其他的加密方式。
不可见数据有: 变量 说明 $time 用户的注册时间 $_SERVER['REMOTE_ADDR'] 用户的注册IP 1.time返回的unix时间戳 2.REMOTE_ADDR返回的是IP地址,我们可以用ip2long将其转为整型存储。 $username = trim($_POST['username']); $password = md5(trim($_POST['password'])); $time = time(); $ip = ip2long($_SERVER['REMOTE_ADDR']);
三、连接数据库、判断错误、选择库和字符集
1.我们使用mysqli_connect连接到数据库服务器。
2.如果有错误,使用mysqli_errno得到错误号
3.如何时存在错误mysqli_error打印出所有的错误,并且退出程序执行
4.选择数据库并且设置字符集为utf8.
//连接数据库 $conn = mysqli_connect('localhost','root','123456'); //如果有错误,存在错误号 if(mysqli_errno($conn)){ echo mysqli_error($conn); exit; } mysqli_select_db($conn,'user'); mysqli_set_charset($conn,'utf8');
四、组合SQL语句
我们需要把得到的信息写入到数据库里面去,用户名、密码、创建时间、IP我们都得到了。
将对应的变量插入到SQL语句中即可。组合出来的SQL语句如下:
$sql = "insert into user(username,password,createtime,createip) values('" . $username . "','" . $password . "','" . $time . "','" . $ip . "')";
而我们的创建表的语句如下:
CREATE TABLE IF NOT EXISTS user ( id int(11) NOT NULL, username varchar(30) NOT NULL, password char(32) NOT NULL, createtime int(11) NOT NULL, createip int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
表的格式(字段对应说明):
id username password createtime createip
用户编号 用户名 密码 创建时间 创建IP
五、发送语句,判断状态
mysqli_query我们在上面说过,需要传入两个参数:
连接的资源,在这里对应的变量是$conn。
发送的SQL语句。在上面已经准备好了$sql。
SQL语句可以通过mysqli_query发送给MySQL服务器。发送成功$result则为true。否则为false。
成功的话,我们就可以提示用户注册成功啦。
有些情况下,可能还需要使用到mysqli_insert_id()。在这里把自增的主键ID打印出来。
大家记住这个知识点,避免以后需要的时候忘记了。
mysqli_insert_id应用场景:新加的一个行的数据。我们需要得到自动增长的ID值,将这个ID值插入到另外一个表里面去时。就需要用到这个函数。
mysqli_insert_id() 函数返回最后一个查询中自动生成的 ID(通过 AUTO_INCREMENT 生成)。
$result = mysqli_query($conn,$sql); if($result){ echo '注册成功'; }else{ echo '注册失败'; } echo '当前用户插入的ID为'.mysqli_insert_id($conn);
六、关闭数据库连接
将资源变量传到到mysqli_close这个函数里面即可。
mysqli_close($conn);
用户注册的基本实现代码就写完了。我们上面讲的都是代码片段。
我们整实现的connect.php代码如下:
<?php if (trim($_POST['password']) != trim($_POST['repassword'])) { exit('两次密码不一致,请返回上一页'); } $username = trim($_POST['username']); $password = md5(trim($_POST['password'])); $time = time(); $ip = $_SERVER['REMOTE_ADDR']; $conn = mysqli_connect('localhost', 'root', '123456'); //如果有错误,存在错误号 if (mysqli_errno($conn)) { echo mysqli_error($conn); exit; } mysqli_select_db($conn, 'book'); mysqli_set_charset($conn, 'utf8'); $sql = "insert into user(username,password,createtime,createip) values('" . $username . "','" . $password . "','" . $time . "','" . $ip . "')"; $result = mysqli_query($conn, $sql); if ($result) { echo '成功'; } else { echo '失败'; } echo '当前用户插入的ID为' . mysqli_insert_id($conn); mysqli_close($conn); ?>
别忘了 设置id主键 设置自增----大坑!!!!
案例:做一个列表显示
上一章我们按照我们的“数据库连接天龙八步”,很顺利的就完成了用户注册。
我们来做一个后台的用户列表展示。在实际的管理过程当中,我们通过后台,可以个修改用户的密码和用户的相关资料。
在后台需要将所有用户以表格的形式展示出来就是用户列表。
一、连接数据库、判断错误和设置字符集
连接、错误判断和字符集选择都在上面已经讲过。老规矩,第一步使用mysqli_connect连接数据库。在第一节我们讲过,可以在第四个参数中加上库选择。就可以不用使用mysqli_select_db函数在后面再次选择一个数据库了。
返回的类型就是一个连接资源。我们在mysqli_errno、mysqli_error和mysqli_set_charset都要传入资源,才能确定我们操作的是哪个连接。
$conn = mysqli_connect('localhost', 'root', 'secret', 'book'); if (mysqli_errno($conn)) { mysqli_error($conn); exit; } mysqli_set_charset($conn, 'utf8');
二、准备并发送SQL语句
我们需要查询的的将候将用户ID,用户名、时间和IP都查出来。并且使用order by id 进行降序排序。
按照人的思维人们一般喜欢看最新注册的一批用户。而ID自增,也就是ID在越大,就是时间注册越新的用户。因此我们在写SQL语句的时写上的是order by id desc。
$sql = "select id,username,createtime,createip from user order by id desc"; $result = mysqli_query($conn, $sql);
三、判断结果
查询出来的结果只要SQL语句正确结果变量$result就为真。因此,在实现的时候我们需要多加一步判断,不仅判断$result。而且,判断查询出来的行数。
查询出来的行数可以使用mysqli_num_rows。这个函数要求传入$result查询的结果变量。
如果有结果则显示列表,如果没有结果我们产生一句提示即可。
代码片段如下:
if($result && mysqli_num_rows($result)){ //显示列表代码段 }else{ //提示没有结果的代码段 }
四、循环显示数据
所有结果我们需要使用列表的形式展示出来。表格的行和列和数据表的行和列是一样的。所示展示起来很方便。
先声明一个表格,每次循环的时候输出一行。将结果展示到各个列里面。
使用到的函数是mysqli_fetch_assoc,返回的会是一个关联数组。
这个函数读取一个结果集,会向后移动一次。读取到最后没有结果的时候会返回bool值的false。因此,我们选择while来配合mysqli_fetch_assoc。
每次循环的结果赋值给$row,$row中是关联数组。因此我在这次循环中,可以将行和列都显示出来。
echo '<table width="800" border="1">'; while ($row = mysqli_fetch_assoc($result)) { echo '<tr>'; echo '<td>' . $row['username'] . '</td>'; echo '<td>' . date('Y-m-d H:i:s', $row['createtime']) . '</td>'; echo '<td>' . long2ip($row['createip']) . '</td>'; echo '</tr>'; } echo '</table>';
五、增加编辑和删除控制
1.在删除的时候我们分为单选删除和多选删除。
2.而编辑的时候,我们会选择一个用户
我们在上一步的代码中增加几个小东西就在页面中实现了删除和编编。
我们来看**看实际的效果图,**来推理具体的实现过程,效果如下:
在实现过程当中有几个要点:
1.单选择删除和编辑时需使用get方法传入ID,我们才知道要编辑或者删除的是哪个用户。
2.多选删除时,需要使用传入多个用户。因此,我们可以使用form表单,使用post方法来提交这批用户ID。
单选删除我们可以在delete.php后面我们跟上?加上id和值就点击时进行删除请求即可。
echo '<td><a href="delete.php?id=' . $row['id'] . '">删除用户</a></td>';
编辑用户也是同理,我们在edit.php加上?写上id和值,点击时就知道是需要编辑的哪个用户了。
echo '<td><a href="edit.php?id=' . $row['id'] . '">编辑用户</a></td>';
而多选删除,我们需要使用到html中的checkbox,传入多个用户ID的时候需要在name 后加上id[]。使用form表单将表格包起来,在表格外加上一个submit标签就实现了多选删除。
<form action="delete.php" method="post"> echo '<td><input type="checkbox" name="id[]" value="' . $row['id'] . '" /></td>'; echo '<input type="submit" value="删除" />'; echo '</form>';
代码如下:
echo '<form action="delete.php" method="post">'; echo '<table width="800" border="1">'; while ($row = mysqli_fetch_assoc($result)) { echo '<tr>'; echo '<td><input type="checkbox" name="id[]" value="' . $row['id'] . '" /></td>'; echo '<td>' . $row['username'] . '</td>'; echo '<td>' . date('Y-m-d H:i:s', $row['createtime']) . '</td>'; echo '<td>' . long2ip($row['createip']) . '</td>'; echo '<td><a href="edit.php?id=' . $row['id'] . '">编辑用户</a></td>'; echo '<td><a href="delete.php?id=' . $row['id'] . '">删除用户</a></td>'; echo '</tr>'; } echo '</table>'; echo '<input type="submit" value="删除" />'; echo '</form>';
六、关闭数据库连接
我们操作完数据库,关闭掉这个数据库连接。
mysqli_close($conn);
表list.php完整代码
我们整实现的用户列表list.php代码如下:
<?php $conn = mysqli_connect('localhost', 'root', 'secret', 'book'); if (mysqli_errno($conn)) { mysqli_error($conn); exit; } mysqli_set_charset($conn, 'utf8'); $sql = "select id,username,createtime,createip from user order by id desc"; $result = mysqli_query($conn, $sql); if ($result && mysqli_num_rows($result)) { echo '<table width="800" border="1">'; while ($row = mysqli_fetch_assoc($result)) { echo '<tr>'; echo '<td>' . $row['username'] . '</td>'; echo '<td>' . date('Y-m-d H:i:s', $row['createtime']) . '</td>'; echo '<td>' . long2ip($row['createip']) . '</td>'; echo '<td><a href="edit.php?id=' . $row['id'] . '">编辑用户</a></td>'; echo '<td><a href="delete.php?id=' . $row['id'] . '">删除用户</a></td>'; echo '</tr>'; } echo '</table>'; } else { echo '没有数据'; } mysqli_close($conn); ?>
在form表单中显示用户信息的源代码
<?php if (is_numeric($_GET['id'])) { $id = (int) $_GET['id']; } $sql = "select id,username from user where id = " . $id; $result = mysqli_query($conn, $sql); $data = mysqli_fetch_assoc($result); ?> <form action="update.php" method="post"> 用户名:<input type="text" name="username" value="<?php echo $data['username'];?>"><br /> 密码:<input type="password" name="password"><br /> <input type="hidden" value="<?php echo $data['id'];?>" name="id" /> <input type="submit" value="提交"> </form> <?php mysqli_close($conn); ?>
update.php修改的源代码
<?php include 'connection.php'; $id = (int) $_POST['id']; if (trim($_POST['password'])) { $password = md5(trim($_POST['password'])); $sql = "update user set password='" . $password . "' where id = $id"; } else { echo '修改成功'; } $result = mysqli_query($conn, $sql); if ($result) { echo '修改成功'; }
php数据库操作之数据显示乱码终极解决办法
php连接mysql乱码是开发过程当中,这是开发中新手经常遇到的问题。 根据实际大家遇到的问题,将乱码的问题,总结成了9个要点来彻底解决连接后乱码的问题。
解决乱码问题的核心思想,就是:一定要多个不同的文件系统中一定要统一编码。
这9个要点分别是:
1.html编码与MySQL编码一致
2.PHP编码与MySQL编码一致
3.若有header头发送字符集,请与数据库一样
4.<meta http-equiv=“Content-Type”content=“text/html; charset=utf-8” />
要和页面的文字编码一致
5.数据库建库的字符集要统一
6.表的字符集要统一
7.列的字符集要统一(表设了,列就默认写表的)
8.连接,校验的字符集要统一