💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# MySQL PHP 教程 > 原文: [http://zetcode.com/databases/mysqlphptutorial/](http://zetcode.com/databases/mysqlphptutorial/) 这是针对 MySQL 数据库的 PHP 编程教程。 它涵盖了使用 PHP 进行 MySQL 编程的基础。 它使用通用 mysql 模块。 这些示例是在 Ubuntu Linux 上创建和测试的。 在 ZetCode 上有类似的 [MySQL C API 教程](/db/mysqlc/), [MySQL MySQL 教程](/db/mysqlpython/), [MongoDB PHP 教程](/db/mongodbphp/)和 [PostgreSQL PHP 教程](/db/postgresqlphp/)。 如果您需要重新了解 PHP 语言,可以在 ZetCode 上找到完整的 [PHP 教程](/lang/php/)。 ## 关于 MySQL 数据库 MySQL 是领先的开源数据库管理系统。 它是一个多用户,多线程的数据库管理系统。 MySQL 在网络上特别流行。 它是非常流行的 _LAMP_ 平台的组成部分之一。 Linux,Apache,MySQL 和 PHP。 目前,MySQL 由 Oracle 拥有。 MySQL 数据库在最重要的 OS 平台上可用。 它可以在 BSD Unix,Linux,Windows 或 Mac OS 上运行。 维基百科和 YouTube 使用 MySQL。 这些站点每天管理数百万个查询。 MySQL 有两个版本:MySQL 服务器系统和 MySQL 嵌入式系统。 ## 开始之前 我们需要安装几个包来执行本教程中的示例:`php5-cli`,`php5-mysql`,`mysql-server`和`mysql-client`。 `php5-cli`是 PHP5 编程语言的命令行解释器。 本教程中的所有示例均在控制台上创建。 我特意跳过了 Web 界面,以使示例更简单,仅关注 PHP 和 MySQL。 如果您尚未安装 MySQL,则必须安装它。 ```php $ sudo apt-get install mysql-server ``` 此命令将安装 MySQL 服务器和其他各种包。 在安装包时,提示我们输入 MySQL 根帐户的密码。 接下来,我们将创建一个新的数据库用户和一个新的数据库。 我们使用`mysql`客户端。 ```php $ service mysql status mysql start/running, process 1238 ``` 我们检查 MySQL 服务器是否正在运行。 如果没有,我们需要启动服务器。 在 Ubuntu Linux 上,可以使用`service mysql start`命令来完成。 ```php $ sudo service mysql start ``` 如果我们已经从包中安装了 MySQL 数据库,则上述命令是启动 MySQL 的常用方法。 ```php $ sudo -b /usr/local/mysql/bin/mysqld_safe ``` 上面的命令使用 MySQL 服务器启动脚本启动 MySQL 服务器。 我们启动 MySQL 服务器的方式可能有所不同。 这取决于我们是否从源代码或包安装了 MySQL,也取决于 Linux 发行版。 有关更多信息,请查阅 [MySQL 的第一步](http://zetcode.com/databases/mysqltutorial/firststeps/)或您的 Linux 发行版信息。 接下来,我们将创建一个新的数据库用户和一个新的数据库。 我们使用`mysql`客户端。 ```php $ mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 30 Server version: 5.0.67-0ubuntu6 (Ubuntu) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | +--------------------+ 2 rows in set (0.00 sec) ``` 我们使用 mysql 监视器客户端应用连接到服务器。 我们使用根帐户连接到数据库。 我们用`SHOW DATABASES`语句显示所有可用的数据库。 ```php mysql> CREATE DATABASE mydb; Query OK, 1 row affected (0.02 sec) ``` 我们创建一个新的`mydb`数据库。 在整个教程中,我们将使用此数据库。 ```php mysql> CREATE USER user12@localhost IDENTIFIED BY '34klq*'; Query OK, 0 rows affected (0.00 sec) mysql> USE mydb; Database changed mysql> GRANT ALL ON mydb.* to user12@localhost; Query OK, 0 rows affected (0.00 sec) mysql> quit; Bye ``` 我们创建一个新的数据库用户。 我们授予该用户`mydb`数据库所有表的所有特权。 ## php5-mysql 为了从 PHP 语言连接到 MySQL 数据库,我们必须安装`php5-mysql`包。 这是 Debian / Ubuntu Linux 的包名称。 在其他衍生产品上,名称可能有所不同。 该包包含三个模块。 它们也称为扩展。 * `mysql`模块 * `mysqli`模块 * `pdo_mysql` 通用`mysql`模块是 MySQL 数据库的原始 PHP API。 我们的教程涵盖了该模块。 API 是程序性的。 该模块不提供较新的 MySQL 数据库的所有最新功能。 MySQL 改进的`mysqli`模块是 MySQL 4.1.3 或更高版本的推荐模块。 它提供了面向对象的 API 和过程 API。 与原始的`mysql`模块相比,它具有一些优点和增强。 PHP 数据对象模块`pdo_mysql`是 PHP 应用的数据库抽象层。 如果我们编写可移植的数据库 PHP 脚本,则此模块非常有用。 ## 第一个脚本 以下脚本是一个简单的 PHP 脚本。 如果此小脚本运行正常,则说明我们已安装了所有必需的东西。 ```php <?php $host = "localhost"; $user = "user12"; $pass = "34klq*"; $r = mysql_connect($host, $user, $pass); if (!$r) { echo "Could not connect to server\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Connection established\n"; } echo mysql_get_server_info() . "\n"; mysql_close(); ?> ``` 我们连接到数据库并获取有关 MySQL 服务器的一些信息。 ```php $host = "localhost"; $user = "user12"; $pass = "34klq*"; ``` 这是三个变量,分别包含主机名,用户名和密码。 连接到 MySQL 数据库时需要这些变量。 ```php $r = mysql_connect($host, $user, $pass); ``` 我们使用`mysql_connect()`函数连接到数据库。 该函数返回一个布尔值,指示是否成功创建连接。 该函数具有 3 个参数。 第一个是安装服务器的主机。 第二和第三个参数是用户名和用户密码。 ```php if (!$r) { echo "Could not connect to server\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Connection established\n"; } ``` 现在我们检查`$r`变量。 如果它包含布尔值`false`,则表示未创建与数据库的连接。 我们调用`trigger_error()`函数来生成错误消息。 第一条通用消息发送给用户。 记录通过`trigger_error()`函数生成的更具体的错误消息。 ```php echo mysql_get_server_info() . "\n"; ``` `mysql_get_server_info()`返回 MySQL 服务器版本。 ```php mysql_close(); ``` `mysql_close()`函数关闭与数据库的连接。 在本例中,不需要关闭连接,因为在脚本执行结束时,非持久性打开链接会自动关闭。 但是,这是一种好的编程习惯。 ```php $ php version.php 5.1.41-3ubuntu12.6 5.3.2-1ubuntu4.5 ``` 在我的系统上,我得到以下输出。 我们有一个类似的脚本。 ```php <?php $host = "localhost"; $user = "user12"; $pass = "34klq*"; $r = mysql_connect($host, $user, $pass); if (!$r) { echo "Could not connect to server\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Connection established\n"; } $query = "SELECT VERSION()"; $rs = mysql_query($query); if (!$rs) { echo "Could not execute query: $query\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Query: $query executed\n"; } $row = mysql_fetch_row($rs); echo "Version: $row[0]\n"; mysql_close(); ?> ``` 我们检查 MySQL 数据库的版本。 这次使用 SQL 查询。 ```php $query = "SELECT VERSION()"; ``` 这是 SQL `SELECT`语句。 它返回数据库的版本。 `VERSION()`是内置的 MySQL 函数。 ```php $rs = mysql_query($query); ``` `mysql_query()`函数在数据库上执行 SQL 查询。 这是一个`SELECT`查询,因此结果是一个包含一些数据的结果集。 ```php if (!$rs) { echo "Could not execute query: $query\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Query: $query executed\n"; } ``` 如果发生错误,我们会生成一条错误消息。 否则,我们将打印执行的 SQL 查询。 ```php $row = mysql_fetch_row($rs); ``` 我们从结果集中获取一行。 `$row`变量是一个包含数据的数组。 ```php echo "Version: $row[0]\n"; ``` 我们从数组中打印数据。 根据查询的性质,我们知道数组只有一项,即 MySQL 版本字符串。 ```php $ php version2.php Connection established Query: SELECT VERSION() executed Version: 5.1.62-0ubuntu0.11.10.1 ``` 脚本在我们系统上的输出。 ## 创建并填充表 接下来,我们将创建一个数据库表并用数据填充它。 ```php <?php $host = "localhost"; $user = "user12"; $pass = "34klq*"; $db = "mydb"; function execute_query($query) { $r = mysql_query($query); if (!$r) { echo "Cannot execute query: $query\n"; trigger_error(mysql_error()); } else { echo "Query: $query executed\n"; } } $r = mysql_connect($host, $user, $pass); if (!$r) { echo "Could not connect to server\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Connection established\n"; } $r2 = mysql_select_db($db); if (!$r2) { echo "Cannot select database\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Database selected\n"; } $query = "DROP TABLE IF EXISTS Cars"; execute_query($query); $query = "CREATE TABLE Cars(Id INT PRIMARY KEY, Name TEXT, Price INT) ENGINE=InnoDB"; execute_query($query); $query = "INSERT INTO Cars VALUES(1,'Audi',52642)"; execute_query($query); $query = "INSERT INTO Cars VALUES(2,'Mercedes',57127)"; execute_query($query); $query = "INSERT INTO Cars VALUES(3,'Skoda',9000)"; execute_query($query); $query = "INSERT INTO Cars VALUES(4,'Volvo',29000)"; execute_query($query); $query = "INSERT INTO Cars VALUES(5,'Bentley',350000)"; execute_query($query); $query = "INSERT INTO Cars VALUES(6,'Citroen',21000)"; execute_query($query); $query = "INSERT INTO Cars VALUES(7,'Hummer',41400)"; execute_query($query); $query = "INSERT INTO Cars VALUES(8,'Volkswagen',21600)"; execute_query($query); mysql_close(); ?> ``` 在上面的代码示例中,我们创建具有 8 行的`Cars`表。 ```php function execute_query($query) { $r = mysql_query($query); if (!$r) { echo "Cannot execute query: $query\n"; trigger_error(mysql_error()); } else { echo "Query: $query executed\n"; } } ``` 我们创建了一个自定义`execute_query()`函数,该函数将为每个`INSERT`语句调用。 ```php $r2 = mysql_select_db($db); ``` 在使用数据库表之前,我们必须选择一个数据库。 使用`mysql_select_db()`函数选择一个数据库。 ```php if (!$r2) { echo "Cannot select database\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Database selected\n"; } ``` 数据库选择过程的错误处理。 ```php $query = "DROP TABLE IF EXISTS Cars"; execute_query($query); ``` 第一个查询将删除`Cars`表(如果已存在)。 ```php $query = "CREATE TABLE Cars(Id INT PRIMARY KEY, Name TEXT, Price INT) ENGINE=InnoDB"; execute_query($query); ``` 这是创建`Cars`表的 SQL 语句。 ```php $query = "INSERT INTO Cars VALUES(1,'Audi',52642)"; execute_query($query); ``` 一辆汽车被插入表。 ```php if (!$ok) { echo mysql_error(); die("Cannot execute query. \n"); } ``` 如果发生错误,我们将打印错误消息并终止脚本。 ```php $ php create_fill.php Connection established Database selected Query: DROP TABLE IF EXISTS Cars executed Query: CREATE TABLE Cars(Id INT PRIMARY KEY, Name TEXT, Price INT) ENGINE=InnoDB executed Query: INSERT INTO Cars VALUES(1,'Audi',52642) executed Query: INSERT INTO Cars VALUES(2,'Mercedes',57127) executed Query: INSERT INTO Cars VALUES(3,'Skoda',9000) executed Query: INSERT INTO Cars VALUES(4,'Volvo',29000) executed Query: INSERT INTO Cars VALUES(5,'Bentley',350000) executed Query: INSERT INTO Cars VALUES(6,'Citroen',21000) executed Query: INSERT INTO Cars VALUES(7,'Hummer',41400) executed Query: INSERT INTO Cars VALUES(8,'Volkswagen',21600) executed ``` 执行`create_fill.php`脚本。 ```php mysql> SELECT * FROM Cars; +----+------------+--------+ | Id | Name | Price | +----+------------+--------+ | 1 | Audi | 52642 | | 2 | Mercedes | 57127 | | 3 | Skoda | 9000 | | 4 | Volvo | 29000 | | 5 | Bentley | 350000 | | 6 | Citroen | 21000 | | 7 | Hummer | 41400 | | 8 | Volkswagen | 21600 | +----+------------+--------+ 8 rows in set (0.00 sec) ``` 数据插入到`Cars`表中。 ## 检索数据 现在我们已经将一些数据插入数据库中,我们想要取回它。 ```php <?php $host = "localhost"; $user = "user12"; $pass = "34klq*"; $db = "mydb"; $r = mysql_connect($host, $user, $pass); if (!$r) { echo "Could not connect to server\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Connection established\n"; } $r2 = mysql_select_db($db); if (!$r2) { echo "Cannot select database\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Database selected\n"; } $query = "SELECT * FROM Cars LIMIT 5"; $rs = mysql_query($query); if (!$rs) { echo "Could not execute query: $query"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Query: $query executed\n"; } while ($row = mysql_fetch_assoc($rs)) { echo $row['Id'] . " " . $row['Name'] . " " . $row['Price'] . "\n"; } mysql_close(); ?> ``` 在此示例中,我们从`Cars`表中检索五行。 ```php $query = "SELECT * FROM Cars LIMIT 5"; ``` 该 SQL 语句从`Cars`表中选择 5 行。 ```php $rs = mysql_query($query); ``` 我们使用`mysql_query()`函数执行查询并检索结果集。 ```php if (!$rs) { echo "Could not execute query: $query"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Query: $query executed\n"; } ``` 如果查询没有成功,我们将生成一条错误消息。 ```php while ($row = mysql_fetch_assoc($rs)) { echo $row['Id'] . " " . $row['Name'] . " " . $row['Price'] . "\n"; } ``` 我们遍历结果集并将数据打印到控制台。 `mysql_fetch_assoc()`函数返回与提取的行相对应的字符串关联数组,如果没有更多行,则返回`FALSE`。 换句话说,函数调用从结果集中返回一行。 该行采用关联数组的形式。 列名称是关联数组的键。 当结果集中没有更多行时,该函数将返回`FALSE`,而`while`循环终止。 ```php $ php query.php Connection established Database selected Query: SELECT * FROM Cars LIMIT 5 executed 1 Audi 52642 2 Mercedes 57127 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000 ``` 这是示例的输出。 在第二个示例中,我们将使用`mysql_fetch_row()`函数获取数据。 ```php <?php $host = "localhost"; $user = "user12"; $pass = "34klq*"; $db = "mydb"; $r = mysql_connect($host, $user, $pass); if (!$r) { echo "Could not connect to server\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Connection established\n"; } $r2 = mysql_select_db($db); if (!$r2) { echo "Cannot select database\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Database selected\n"; } $query = "SELECT Id, Name, Price From Cars LIMIT 5"; $rs = mysql_query($query); if (!$rs) { echo "Could not execute query: $query"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Query: $query executed\n"; } $nrows = mysql_num_rows($rs); for ($i = 0; $i < $nrows; $i++) { $row = mysql_fetch_row($rs); echo $row[0]; echo " "; echo $row[1]; echo " "; echo $row[1]; echo "\n"; } mysql_close(); ?> ``` 我们从`Cars`表中获得前 5 行。 ```php $nrows = mysql_num_rows($rs); ``` `mysql_num_rows()`函数从结果集中获取行数。 ```php for ($i = 0; $i < $nrows; $i++) { $row = mysql_fetch_row($rs); echo $row[0]; echo " "; echo $row[1]; echo " "; echo $row[1]; echo "\n"; } ``` 我们使用`for`循环遍历返回的行。 `mysql_fetch_row()`函数从结果集中以枚举数组的形式检索行。 ```php $ php query.php Connection established Query: SELECT * FROM Cars LIMIT 5 executed 1 Audi 52642 2 Mercedes 57127 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000 ``` 输出。 在下面的示例中,我们显示了如何从表中检索特定行。 ```php <?php $host = "localhost"; $user = "user12"; $pass = "34klq*"; $db = "mydb"; $r = mysql_connect($host, $user, $pass); if (!$r) { echo "Could not connect to server\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Connection established\n"; } $r2 = mysql_select_db($db); if (!$r2) { echo "Cannot select database\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Database selected\n"; } $name = "Volkswagen"; $query = sprintf("SELECT Id, Name, Price From Cars Where Name = '%s'", mysql_real_escape_string($name)); $rs = mysql_query($query); if (!$rs) { echo "Could not execute query: $query\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Query: $query executed\n"; } while ($row = mysql_fetch_object($rs)) { echo $row->Id; echo " "; echo $row->Name; echo " "; echo $row->Price; echo "\n"; } mysql_close(); ?> ``` 开发者在处理用户输入时必须考虑安全性问题。 我们必须始终处理来自外部世界的数据。 检查数据的有效性。 ```php $name = "Volkswagen"; ``` 在脚本中,我们检查`Caras`表中是否有`"Volkswagen"`。 此值可能来自 XML 文件或 Web 表单。 我们将展示如何检查它。 ```php $query = sprintf("SELECT Id, Name, Price From Cars Where Name = '%s'", mysql_real_escape_string($name)); ``` 我们使用`sprintf()`函数构建 SQL 语句。 我们使用`mysql_real_escape_string()`函数处理`$name`变量。 此函数转义字符串中的特殊字符以用于 SQL 语句。 这样可以防止 SQL 注入攻击和数据损坏。 处理完变量后,将其放入 SQL 语句字符串中。 ```php while ($row = mysql_fetch_object($rs)) { echo $row->Id; echo " "; echo $row->Name; echo " "; echo $row->Price; echo "\n"; } ``` 我们使用`mysql_fetch_object()`函数获取数据。 该函数获取结果行作为对象。 然后,我们使用对象表示法获取表列。 ```php $ php query3.php Connection established Database selected Query: SELECT Id, Name, Price From Cars Where Name = 'Volkswagen' executed 8 Volkswagen 21600 ``` 示例的输出。 我们找到了汽车,并将整行打印到控制台。 ## 转义字符 我们将有一个小示例演示如何转义字符。 有些字符在数据库环境中被认为是不安全的。 其中之一是单引号字符。 ```php mysql> CREATE TABLE IF NOT EXISTS Authors(Id INT PRIMARY KEY AUTO_INCREMENT, -> Name VARCHAR(25)) ENGINE=InnoDB; Query OK, 0 rows affected (0.09 sec) ``` 对于该示例,我们创建一个`Authors`表。 ```php <?php $host = "localhost"; $user = "user12"; $pass = "34klq*"; $db = "mydb"; $r = mysql_connect($host, $user, $pass); if (!$r) { echo "Could not connect to server\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Connection established\n"; } $r2 = mysql_select_db($db); if (!$r2) { echo "Cannot select database\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Database selected\n"; } $name = "O'Neill"; $name_es = mysql_real_escape_string($name); $query = "INSERT INTO Authors(Name) VALUES('$name_es')"; $rs = mysql_query($query); if (!$rs) { echo "Could not execute query: $query\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Query: $query executed\n"; } mysql_close(); ?> ``` 我们在`Authors`表中插入一个新作者。 作者的名字叫奥尼尔。 该名称具有不安全的单引号字符。 ```php $name_es = mysql_real_escape_string($name); ``` 这就是为什么我们使用`mysql_real_escape_string()`函数来转义此字符。 ```php $query = "INSERT INTO Authors(Name) VALUES('$name_es')"; $rs = mysql_query($query); ``` 我们创建该语句并执行它。 ```php mysql> SELECT * FROM Authors; +----+---------+ | Id | Name | +----+---------+ | 1 | O'Neill | +----+---------+ 1 row in set (0.00 sec) ``` 该名称已成功写入表中。 ## 列标题 接下来,我们将展示如何使用数据库表中的数据打印列标题。 ```php <?php $host = "localhost"; $user = "user12"; $pass = "34klq*"; $db = "mydb"; $r = mysql_connect($host, $user, $pass); if (!$r) { echo "Could not connect to server\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Connection established\n"; } $r2 = mysql_select_db($db); if (!$r2) { echo "Cannot select database\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Database selected\n"; } $query = "SELECT * From Cars LIMIT 8"; $rs = mysql_query($query); if (!$rs) { echo "Could not execute query: $query"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Query: $query executed\n"; } $cname1 = mysql_fetch_field($rs, 0); $cname2 = mysql_fetch_field($rs, 1); $cname3 = mysql_fetch_field($rs, 2); printf("%3s %-11s %8s\n", $cname1->name, $cname2->name, $cname3->name); while ($row = mysql_fetch_row($rs)) { printf("%3s %-11s %8s\n", $row[0], $row[1], $row[2]); } mysql_close(); ?> ``` 同样,我们将`Writers`表的内容打印到控制台。 现在,我们也包括列的名称。 ```php $cname1 = mysql_fetch_field($rs, 0); $cname2 = mysql_fetch_field($rs, 1); $cname3 = mysql_fetch_field($rs, 2); ``` 要获取特定的字段名称,我们利用`mysql_fetch_field()`函数。 该函数返回一个包含列信息的对象。 ```php printf("%3s %-11s %8s\n", $cname1->name, $cname2->name, $cname3->name); ``` 列名称已打印并格式化。 `name`属性包含列名。 ```php $ php columns.php Connection established Database selected Query: SELECT * From Cars LIMIT 8 executed Id Name Price 1 Audi 52642 2 Mercedes 57127 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000 6 Citroen 21000 7 Hummer 41400 8 Volkswagen 21600 ``` 脚本的输出。 ## 行和列数 以下脚本计算查询返回的字段/列和行数。 ```php <?php $host = "localhost"; $user = "user12"; $pass = "34klq*"; $db = "mydb"; $r = mysql_connect($host, $user, $pass); if (!$r) { echo "Could not connect to server\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Connection established\n"; } $r2 = mysql_select_db($db); if (!$r2) { echo "Cannot select database\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Database selected\n"; } $query = "SELECT * FROM Cars WHERE Id IN (1, 2, 3)"; $rs = mysql_query($query); if (!$rs) { echo "Could not execute query: $query\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Query: $query executed\n"; } echo "We have " . mysql_num_fields($rs) . " fields\n"; echo "We have " . mysql_num_rows($rs) . " rows\n"; print_r(mysql_fetch_row($rs)); mysql_close(); ?> ``` 我们从`Cars`表中选择三行。 我们计算查询返回的行数和列数。 ```php $query = "SELECT * FROM Cars WHERE Id IN (1, 2, 3)"; ``` 这是要执行的查询。 它从`Cars`表中选择前三行。 ```php echo "We have " . mysql_num_fields($rs) . " fields\n"; ``` `mysql_num_fields()`返回查询返回的字段数。 ```php echo "We have " . mysql_num_rows($rs) . " rows\n"; ``` `mysql_num_rows()`返回查询返回的行数。 ```php print_r(mysql_fetch_row($rs)); ``` 我们打印数组的内容。 ```php $ php fields_rows.php Connection established Database selected Query: SELECT * FROM Cars WHERE Id IN (1, 2, 3) executed We have 3 fields We have 3 rows Array ( [0] => 1 [1] => Audi [2] => 52642 ) ``` 运行脚本。 ## 写入图像 有些人喜欢将其图像放入数据库中,有些人则希望将其保留在文件系统中以供其应用使用。 当我们处理大量图像时,会出现技术难题。 图像是二进制数据。 MySQL 数据库具有一种特殊的数据类型来存储称为`BLOB`(二进制大对象)的二进制数据。 ```php mysql> CREATE TABLE Images(Id INT PRIMARY KEY AUTO_INCREMENT, Data MEDIUMBLOB); Query OK, 0 rows affected (0.06 sec) ``` 对于此示例,我们创建一个名为`Images`的新表。 ```php <?php $host = "localhost"; $user = "user12"; $pass = "34klq*"; $db = "mydb"; $r = mysql_connect($host, $user, $pass); if (!$r) { echo "Could not connect to server\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Connection established\n"; } $r2 = mysql_select_db($db); if (!$r2) { echo "Cannot select database\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Database selected\n"; } $file = "woman.jpg"; $img = fopen($file, 'r'); if (!$img) { echo "Cannot open file for writing\n"; trigger_error("Cannot open file for writing\n", E_USER_ERROR); } $data = fread($img, filesize($file)); if (!$data) { echo "Cannot read image data\n"; trigger_error("Cannot read image data\n", E_USER_ERROR); } $es_data = mysql_real_escape_string($data); fclose($img); $query = "INSERT INTO Images(Id, Data) Values(1, '$es_data')"; $rs = mysql_query($query); if (!$rs) { echo "Could not execute query: $query"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Query successfully executed\n"; } mysql_close(); ?> ``` 在上面的脚本中,我们读取 JPG 图像并将其插入到`Images`表中。 ```php $file = "woman.jpg"; ``` 这是我们从文件系统读取并写入数据库的映像名称。 它与脚本名称位于同一目录中。 ```php $img = fopen($file, 'r'); if (!$img) { echo "Cannot open file for writing\n"; trigger_error("Cannot open file for writing\n", E_USER_ERROR); } $data = fread($img, filesize($file)); if (!$data) { echo "Cannot read image data\n"; trigger_error("Cannot read image data\n", E_USER_ERROR); } ``` 我们打开并阅读图像。 `fread()`函数以字符串形式返回数据。 ```php $es_data = mysql_real_escape_string($data); ``` 我们逃避不安全的字符。 ```php fclose($img); ``` 我们关闭图像文件的句柄。 ```php $query = "INSERT INTO Images(Id, Data) Values(1, '$es_data')"; $rs = mysql_query($query); if (!$rs) { echo "Could not execute query: $query"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Query successfully executed\n"; } ``` 我们将数据插入到新创建的`Images`表中。 ## 读取图像 在前面的示例中,我们已将图像插入数据库表中。 现在,我们将从表中读取图像。 ```php <?php $host = "localhost"; $user = "user12"; $pass = "34klq*"; $db = "mydb"; $r = mysql_connect($host, $user, $pass); if (!$r) { echo "Could not connect to server\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Connection established\n"; } $r2 = mysql_select_db($db); if (!$r2) { echo "Cannot select database\n"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Database selected\n"; } $query = "SELECT Data FROM Images WHERE Id=1"; $rs = mysql_query($query); if (!$rs) { echo "Could not execute query: $query"; trigger_error(mysql_error(), E_USER_ERROR); } else { echo "Query: $query executed\n"; } $row = mysql_fetch_row($rs); $file = "woman2.jpg"; $img = fopen($file, 'wb'); if (!$img) { echo "Cannot open file for writing\n"; trigger_error("Cannot open file for writing\n", E_USER_ERROR); } $r3 = fwrite($img, $row[0]); if (!$r3) { echo "Cannot write image to file\n"; trigger_error("Cannot write image to file\n", E_USER_ERROR); } fclose($img); mysql_close(); ?> ``` 我们从`Images`表中读取了一张图像。 ```php $query = "SELECT Data FROM Images WHERE Id=1"; ``` 我们从表中选择一条记录。 ```php $row = mysql_fetch_row($rs); ``` 我们从结果集中获取一行。 只有一行包含图像数据。 ```php $file = "woman2.jpg"; ``` 我们将创建一个名为`woman2.jpg`的新图像文件。 ```php $img = fopen($file, 'wb'); if (!$img) { echo "Cannot open file for writing\n"; trigger_error("Cannot open file for writing\n", E_USER_ERROR); } ``` 我们打开一个可写的二进制文件。 ```php $r3 = fwrite($img, $row[0]); if (!$r3) { echo "Cannot write image to file\n"; trigger_error("Cannot write image to file\n", E_USER_ERROR); } ``` 我们使用`fwrite()`函数将数据写入文件系统。 现在我们在当前目录中应该有一个名为`woman2.jpg`的映像。 我们可以检查它是否与我们插入表中的图像相同。 ## 事务支持 事务是针对一个或多个数据库中数据的数据库操作的基本单位。 事务中所有 SQL 语句的影响可以全部提交给数据库,也可以全部回滚。 MySQL 数据库具有不同类型的存储引擎。 最常见的是 MyISAM 和 InnoDB 引擎。 MyISAM 是默认的。 在数据安全性和数据库速度之间需要权衡。 MyISAM 表的处理速度更快,并且不支持事务。 另一方面,InnoDB 表可以更安全地防止数据丢失。 他们支持事务。 它们处理较慢。 ```php <?php mysql_connect('localhost', 'testuser', 'test623') or die("cannot connect to database\n"); mysql_select_db("testdb") or die(mysql_error()); $r1 = mysql_query("UPDATE Writers SET Name = 'Leo Tolstoy' WHERE Id = 1") or die(mysql_error()); $r2 = mysql_query("UPDATE Writers SET Name = 'Boris Pasternak' WHERE Id = 2") or die(mysql_error()); $r3 = mysql_query("UPDATE Writer SET Name = 'Leonid Leonov' WHERE Id = 3") or die(mysql_error()); mysql_close(); ?> ``` 在此脚本中,我们尝试更新三行。 该表的存储引擎是 MyISAM。 ```php $r1 = mysql_query("UPDATE Writers SET Name = 'Leo Tolstoy' WHERE Id = 1") or die(mysql_error()); $r2 = mysql_query("UPDATE Writers SET Name = 'Boris Pasternak' WHERE Id = 2") or die(mysql_error()); ``` 在这里,我们要更改第 1 行和第 2 行的作者姓名。 ```php $r3 = mysql_query("UPDATE Writer SET Name = 'Leonid Leonov' WHERE Id = 3") or die(mysql_error()); ``` SQL 语句中有错误。 没有`Writer`表。 ```php $ php update.php Table 'testdb.Writer' doesn't exist mysql> SELECT * FROM Writers; +----+-------------------+ | Id | Name | +----+-------------------+ | 1 | Leo Tolstoy | | 2 | Boris Pasternak | | 3 | Lion Feuchtwanger | | 4 | Emile Zola | | 5 | Truman Capote | | 6 | O'Neill | +----+-------------------+ 6 rows in set (0.00 sec) ``` 运行脚本会出现错误。 但是,正如我们所看到的,前两行已经更改。 在本教程的最后一个示例中,我们将重新创建`Writers`表。 这次,该表将为 InnoDB 类型。 InnoDB MySQL 数据库表支持事务。 ```php DROP TABLE Writers; CREATE TABLE IF NOT EXISTS Writers(Id INT PRIMARY KEY AUTO_INCREMENT, Name VARCHAR(25)) ENGINE=INNODB; INSERT INTO Writers(Name) VALUES('Jack London'); INSERT INTO Writers(Name) VALUES('Honore de Balzac'); INSERT INTO Writers(Name) VALUES('Lion Feuchtwanger'); INSERT INTO Writers(Name) VALUES('Emile Zola'); INSERT INTO Writers(Name) VALUES('Truman Capote'); ``` 这是`writers.sql`文件。 它用于重新创建`Writers`表。 ```php mysql> source writers.sql Query OK, 0 rows affected (0.03 sec) Query OK, 0 rows affected (0.10 sec) Query OK, 1 row affected (0.02 sec) Query OK, 1 row affected (0.03 sec) Query OK, 1 row affected (0.02 sec) Query OK, 1 row affected (0.02 sec) Query OK, 1 row affected (0.02 sec) ``` 我们可以使用`source`命令来加载和执行 SQL 脚本。 ```php <?php mysql_connect('localhost', 'testuser', 'test623') or die("cannot connect to database\n"); mysql_select_db("testdb") or die(mysql_error()); mysql_query("SET AUTOCOMMIT=0"); mysql_query("START TRANSACTION"); $r1 = mysql_query("DELETE FROM Writers WHERE Id = 3") or die(mysql_error()); $r2 = mysql_query("DELETE FROM Writers WHERE Id = 4") or die(mysql_error()); $r3 = mysql_query("DELETE FROM Writer WHERE Id = 5") or die(mysql_error()); if ($r1 and $r2 and $r3) { mysql_query("COMMIT"); } else { mysql_query("ROLLBACK"); } mysql_close(); ?> ``` 现在,我们将执行上面的脚本。 我们要从表中删除三行。 第三个 SQL 语句有一个错误。 ```php mysql_query("START TRANSACTION"); ``` `START TRANSACTION`语句开始一个新的事务。 必须使用`COMMIT`语句将所有更改永久化,或使用`ROLLBACK`语句将其忽略。 ```php if ($r1 and $r2 and $r3) { mysql_query("COMMIT"); } else { mysql_query("ROLLBACK"); } ``` 仅当所有三个 SQL 语句都返回`True`时,才提交语句。 否则,我们将它们回滚。 在我们的情况下,`$r3`变量为`False`,因此不会使语句成为永久语句,也不会从表中删除行。 ```php $ php transaction.php Table 'testdb.Writer' doesn't exist mysql> SELECT * FROM Writers; +----+-------------------+ | Id | Name | +----+-------------------+ | 1 | Jack London | | 2 | Honore de Balzac | | 3 | Lion Feuchtwanger | | 4 | Emile Zola | | 5 | Truman Capote | +----+-------------------+ 5 rows in set (0.00 sec) ``` 在将更改提交到数据库之前,发生了错误。 调用`ROLLBACK`语句,并且没有发生删除。 [Tweet](https://twitter.com/share) 这是 MySQL PHP 教程。 您可能也对 [MySQL C API 教程](/db/mysqlc/), [MySQL Python 教程](/db/mysqlpython/)或 [MySQL Visual Basic 教程](/db/mysqlvb/)感兴趣。