PHP课程 - 第3.2课 - 使用 MySQL 数据库。INSERT INTO 插入数据与 SELECT 查询数据。
在上一课中,我们为我们的网站创建了一个数据库表。在本课中,我们将改进该表,并开始与数据库交互:向其中插入数据以及从表中读取数据。我想这并不复杂,所以让我们开始吧。
首先,我建议改进一下我们的 messages 表。目前表中已经有了数据字段,但我们还需要一个用于记录编号的字段。如果你打开 Drupal 的数据库,会发现 node 表中有一个 nid 字段,用来编号节点。同样,我们也需要在 messages 表中添加这样的编号字段。
让我们进入 phpMyAdmin(在 Denwer 中为 http://localhost/tools/phpmyadmin)并编辑表格。在表的开头添加一列,如下图所示:
将列命名为 mid(message id),数据类型为 INT(整数),长度 11 个字符。同时勾选 AUTO_INCREMENT(自动递增),表示该列将自动编号。最后,将索引类型设置为 PRIMARY,即表的主键。
如果你还记得,我们为 simpleCMS 类创建了一个单独的方法来创建表。现在我们需要修改这个方法,让它同时添加 mid 字段。进入 messages 表并点击 Export(导出):
这样我们就进入了表的导出页面。导出以 SQL 查询的形式进行,用于创建或修改表。如果我们在 phpMyAdmin 中更改了表结构,就可以复制生成的 SQL 语句,非常方便。
在导出页面保持默认设置并点击“OK”。PhpMyAdmin 会将 SQL 查询显示在浏览器中或下载为文件,这两种方式都可以。我们需要复制如下 SQL 代码:
注意,这里使用的是反引号(`),这是 phpMyAdmin 的语法;而在 PHP 中我们可以使用普通的单引号。现在把这段 SQL 复制到 buildDB() 方法中:
public function buildDB(){ $sql = "CREATE TABLE IF NOT EXISTS 'messages' ( 'mid' int(11) NOT NULL AUTO_INCREMENT, 'title' varchar(150) DEFAULT NULL, 'bodytext' text, 'created' varchar(100) DEFAULT NULL, PRIMARY KEY ('mid') ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"; return mysql_query($sql); }
现在让我们检查一下效果。删除 messages 表:
确认删除后,当我们运行 index.php 时,buildDB() 方法会被执行,表将被重新创建。
public function buildDB(){ $sql = "CREATE TABLE Messages ( mid int NOT NULL AUTO_INCREMENT, PRIMARY KEY(mid), title varchar(15), bodytext text, created int(11) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1"; $result = mysql_query($sql); print_r($result); }
现在运行 index.php,我们的 Messages 表会重新出现在数据库中。
INSERT INTO 插入查询
数据库已经创建好,现在我们来实现写入与输出消息的方法。首先从插入数据开始。打开 write() 方法,我们将修改它。
向表中插入数据使用 INSERT INTO 操作符,语法如下:
public function write($p) { // 写入消息的方法 $sql = 'INSERT INTO Messages (title, bodytext, created) VALUES ("'. $p["title"] . '", "' . $p["bodytext"] . '", ' . time() . ')'; return mysql_query($sql); }
让我们来解析一下插入语句的结构。正如前面提到的,SQL 插入语句以 INSERT INTO 开头,后跟表名 Messages。接着指定要插入值的列名。注意我们没有写 mid,因为它是自动递增字段,由 MySQL 自动赋值。然后使用 VALUES 指定要插入的值。字段的顺序和数值的顺序必须一一对应。
如果插入的是字符串值,必须用引号包裹。要注意不要混淆 SQL 语句和 PHP 中的引号。例如:
"'. $p["title"] . '"
引号的顺序是:双引号、单引号、连接符(点)、变量、连接符(点)、单引号、双引号。
一个例子足够了,后面还会有更多示例。如果没完全理解也没关系,多练习几次就会明白。现在我们可以尝试在表中插入几条记录。将 write() 方法替换为上面的版本即可。
SELECT 查询
添加几条记录后,在 phpMyAdmin 中查看:
接下来我们使用 display_public() 方法从数据库中读取并显示这些记录。查询语句使用 SELECT 操作符,先从最基本的开始:
public function display_public() { // 输出消息方法 $content = ''; $sql = 'SELECT * FROM Messages'; // 查询语句 $result = mysql_query($sql); // 将查询结果保存到变量中 while($row = mysql_fetch_array($result)){ // 使用 mysql_fetch_array() 处理结果集 print '<div class="post">'; // 包裹记录的 div print '<span class="time">#' . $row['mid'] . ' 于 ' . date('d-m-Y', $row['created']) . '</span><h2>' . $row['title'] . '</h2>'; // 输出时间和标题 print '<p>' . $row['bodytext'] . '</p>'; // 输出正文 print '</div>'; // 结束 div } $content .= '<p><a href="/index.php?admin=1">添加消息</a></p>'; return $content; }
我已完全替换了 display_public() 的实现,现在所有消息都从数据库中输出。让我们分析这个示例。查询语句从 SELECT 开始,后面跟星号(*),表示选择表中所有字段。如果我们写成:
$sql = 'SELECT mid,title FROM Messages'; // 查询语句 $result = mysql_query($sql);
则只会选择 mid 和 title,而不会选择 bodytext 和 created。
在 * 之后是操作符 FROM,用于指定要查询的表名。
mysql_query() 的执行结果要保存到变量中(这里是 $result),因为稍后要用 mysql_fetch_array() 来处理该结果。
假设查询返回 3 条记录,mysql_fetch_array() 每次调用会返回一条记录的数组。第一次调用返回第一条,第二次返回第二条,直到没有记录时返回 false。因此我们用 while 循环逐条输出,直到没有数据。
这在一开始可能有点难理解,但随着练习会越来越熟悉。SQL 的操作符并不多,很快就能掌握。
SELECT 查询与 ORDER BY 排序
可以通过 ORDER BY 操作符对查询结果排序。默认按升序排序,例如:
$sql = 'SELECT * FROM Messages ORDER BY mid';
这样结果将按 mid 升序排列。若要降序排列,可使用 DESC:
$sql = 'SELECT * FROM Messages ORDER BY mid DESC';
相反地,若要显式指定升序,可使用 ASC:
$sql = 'SELECT * FROM Messages ORDER BY mid ASC';
不过升序是默认排序方式。
SELECT 查询与 WHERE 条件
除了排序,还可以通过 WHERE 条件筛选查询结果:
$sql = 'SELECT * FROM Messages WHERE mid<3 ORDER BY mid DESC';
这样我们只会输出前两条记录(mid=1 和 mid=2),前提是这些记录存在。还可以使用逻辑操作符 AND(与)和 OR(或)连接多个条件。当使用 AND 时,所有条件都必须满足;使用 OR 时,只需满足其中一个条件即可。
$limit_time = time() - 3600; // 一小时前的时间 $sql = 'SELECT * FROM Messages WHERE mid<3 AND created>' . $limit_time . ' ORDER BY mid DESC'; // 查询语句
这样我们就增加了一个条件:只输出在一小时内创建的记录。关于查询操作目前就讲到这里,接下来进入下一课。