0

0

PHPMySQL查询怎么写_PHPMySQL数据库查询语句使用教程

看不見的法師

看不見的法師

发布时间:2025-09-25 19:23:01

|

959人浏览过

|

来源于php中文网

原创

PHP连接MySQL查询的核心是使用PDO或mysqli扩展建立连接并执行SQL。推荐使用PDO,因其支持预处理语句防止SQL注入、具备数据库抽象层、统一API及异常处理机制,更安全灵活;mysqli适用于仅操作MySQL且追求轻量的场景,但PDO在可维护性和扩展性上更具优势。

phpmysql查询怎么写_phpmysql数据库查询语句使用教程

PHP连接MySQL进行查询,核心在于利用PHP提供的数据库扩展(如mysqliPDO)建立与数据库的连接,然后构造并执行SQL语句,最后处理返回的结果集。这整个过程,从连接到数据获取,都需要细致的步骤和对潜在问题的考量。

解决方案

在PHP中进行MySQL数据库查询,我个人更倾向于使用PDO(PHP Data Objects),因为它提供了一个统一的接口来访问多种数据库,并且在处理预处理语句方面做得非常出色,这对于防止SQL注入至关重要。当然,mysqli扩展也是一个非常有效的选择,尤其当你只专注于MySQL时。

使用PDO进行查询

这是我推荐的方式,因为它更现代,也更安全。

立即学习PHP免费学习笔记(深入)”;

  1. 建立数据库连接:

    setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 设置错误模式为抛出异常
        $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); // 默认获取关联数组
        // echo "数据库连接成功!"; // 调试用
    } catch (PDOException $e) {
        die("数据库连接失败: " . $e->getMessage());
    }
    ?>

    这里我通常会把数据库配置放在一个单独的文件里,避免直接暴露在代码中,也方便管理。ATTR_ERRMODE_EXCEPTION这个设置非常关键,它能让数据库操作的错误以异常的形式抛出,方便我们捕获和处理。

  2. 执行SELECT查询(带参数绑定): 这是最常见的查询类型,也是我最强调要使用预处理语句的地方。

    prepare("SELECT id, name, email FROM users WHERE id = :id");
    $stmt->bindParam(':id', $userId, PDO::PARAM_INT); // 绑定参数
    $stmt->execute();
    
    // 获取单条结果
    $user = $stmt->fetch();
    if ($user) {
        echo "用户ID: " . $user['id'] . ", 姓名: " . $user['name'] . ", 邮箱: " . $user['email'] . "
    "; } else { echo "未找到用户ID为 " . $userId . " 的用户。
    "; } // 获取所有结果 $stmt = $pdo->prepare("SELECT id, name, email FROM users WHERE status = :status"); $stmt->bindParam(':status', $status, PDO::PARAM_STR); $status = 'active'; // 假设我们要查询所有活跃用户 $stmt->execute(); $activeUsers = $stmt->fetchAll(); foreach ($activeUsers as $user) { echo "活跃用户ID: " . $user['id'] . ", 姓名: " . $user['name'] . "
    "; } ?>

    可以看到,preparebindParam是防止SQL注入的利器,它将SQL逻辑和数据分离,数据库在执行前会先解析SQL结构,再填充数据。

  3. 执行INSERT/UPDATE/DELETE查询: 这类操作同样建议使用预处理语句。

    prepare("INSERT INTO users (name, email) VALUES (:name, :email)");
    $stmt->bindParam(':name', $name);
    $stmt->bindParam(':email', $email);
    $stmt->execute();
    echo "新用户插入成功,ID为: " . $pdo->lastInsertId() . "
    "; // UPDATE $newName = '更新后的名字'; $updateId = 101; $stmt = $pdo->prepare("UPDATE users SET name = :name WHERE id = :id"); $stmt->bindParam(':name', $newName); $stmt->bindParam(':id', $updateId, PDO::PARAM_INT); $stmt->execute(); echo "更新了 " . $stmt->rowCount() . " 条记录。
    "; // DELETE $deleteId = 102; $stmt = $pdo->prepare("DELETE FROM users WHERE id = :id"); $stmt->bindParam(':id', $deleteId, PDO::PARAM_INT); $stmt->execute(); echo "删除了 " . $stmt->rowCount() . " 条记录。
    "; ?>

    lastInsertId()在插入操作后获取新插入记录的ID非常有用,而rowCount()则能告诉你受影响的行数。

使用mysqli进行查询

mysqli是MySQL的增强版扩展,提供了面向对象和面向过程两种风格。这里我主要展示面向对象的风格,因为它更符合现代PHP的开发习惯。

  1. 建立数据库连接:

    connect_errno) {
        die("数据库连接失败: " . $mysqli->connect_error);
    }
    // $mysqli->set_charset("utf8mb4"); // 设置字符集
    // echo "数据库连接成功!"; // 调试用
    ?>

    mysqli的错误处理通常是通过检查connect_errnoconnect_error来完成的。

  2. 执行SELECT查询(带参数绑定):

    prepare("SELECT id, name, email FROM users WHERE id = ?");
    $stmt->bind_param("i", $userId); // "i" 表示整数类型
    $stmt->execute();
    $result = $stmt->get_result(); // 获取结果集
    
    if ($result->num_rows > 0) {
        $user = $result->fetch_assoc(); // 获取关联数组
        echo "用户ID: " . $user['id'] . ", 姓名: " . $user['name'] . ", 邮箱: " . $user['email'] . "
    "; } else { echo "未找到用户ID为 " . $userId . " 的用户。
    "; } $stmt->close(); // 关闭预处理语句 // 获取所有结果 $status = 'active'; $stmt = $mysqli->prepare("SELECT id, name, email FROM users WHERE status = ?"); $stmt->bind_param("s", $status); // "s" 表示字符串类型 $stmt->execute(); $result = $stmt->get_result(); while ($user = $result->fetch_assoc()) { echo "活跃用户ID: " . $user['id'] . ", 姓名: " . $user['name'] . "
    "; } $stmt->close(); ?>

    bind_param的第一个参数是类型字符串,例如"i"代表integer,"s"代表string,"d"代表double,"b"代表blob。

  3. 执行INSERT/UPDATE/DELETE查询:

    prepare("INSERT INTO users (name, email) VALUES (?, ?)");
    $stmt->bind_param("ss", $name, $email);
    $stmt->execute();
    echo "新用户插入成功,ID为: " . $mysqli->insert_id . "
    "; $stmt->close(); // UPDATE $newName = '更新后的名字_mysqli'; $updateId = 103; $stmt = $mysqli->prepare("UPDATE users SET name = ? WHERE id = ?"); $stmt->bind_param("si", $newName, $updateId); $stmt->execute(); echo "更新了 " . $mysqli->affected_rows . " 条记录。
    "; $stmt->close(); // DELETE $deleteId = 104; $stmt = $mysqli->prepare("DELETE FROM users WHERE id = ?"); $stmt->bind_param("i", $deleteId); $stmt->execute(); echo "删除了 " . $mysqli->affected_rows . " 条记录。
    "; $stmt->close(); ?>

    mysqli中获取最后插入ID和受影响行数分别是$mysqli->insert_id$mysqli->affected_rows

无论使用哪种扩展,记得在所有数据库操作完成后,通过$pdo = null;$mysqli->close();来关闭数据库连接,释放资源。

PHP MySQL查询中如何有效防止SQL注入攻击?

SQL注入无疑是数据库安全领域最臭名昭著的漏洞之一,它能让攻击者绕过认证、窃取数据,甚至完全控制数据库。我见过太多新手因为怕麻烦或不了解而直接拼接字符串,这简直是自掘坟墓。

最有效且推荐的防御机制就是使用预处理语句(Prepared Statements)与参数绑定。无论是PDO还是mysqli,都提供了这种机制。

它的工作原理是这样的: 当你使用预处理语句时,SQL查询语句会先发送到数据库服务器进行编译。在这个阶段,SQL语句的结构是固定的,参数的位置用占位符(如?:name)表示。数据库只关心这个查询的“骨架”是什么。 随后,你再将实际的数据(参数)发送给数据库。数据库会把这些数据填充到预编译好的SQL语句中,但它不会再将这些数据当作SQL代码的一部分来解析。它只会把它们当作纯粹的值来处理。

举个例子,如果用户输入了' OR '1'='1,在没有预处理的情况下,这可能会变成SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '...',直接导致绕过认证。但如果使用了预处理,数据库会把' OR '1'='1当作一个完整的字符串值来处理,而不是解析其中的OR=,因此不会改变查询的逻辑。

XFUN
XFUN

小方智能包装设计平台

下载

PDO的预处理示例:

$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
$stmt->bindParam(':username', $inputUsername);
$stmt->bindParam(':password', $inputPassword);
$stmt->execute();

这里的:username:password就是命名占位符。

mysqli的预处理示例:

$stmt = $mysqli->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $inputUsername, $inputPassword); // "ss"表示两个字符串参数
$stmt->execute();

这里的?是匿名占位符。

除了预处理语句,还有一些辅助措施可以增加安全性:

  • 输入验证和过滤: 尽管预处理是主要防线,但对用户输入进行类型检查、长度限制、特殊字符过滤等仍然是好习惯。例如,如果期望一个整数,就确保它真的是整数。
  • 最小权限原则: 数据库用户应该只拥有其完成任务所需的最小权限。不要用root用户来运行Web应用。
  • 错误信息隐藏: 生产环境中不要直接向用户显示详细的数据库错误信息,这可能会泄露数据库结构或凭据。

总之,防止SQL注入,预处理语句是基石,务必掌握并坚持使用。

处理大量MySQL查询结果时,PHP有哪些优化策略?

在处理大量数据时,如果不加思索地一股脑儿全部取出来,PHP应用很容易遇到内存耗尽或执行超时的问题。我以前就吃过这样的亏,一个不小心就导致服务器OOM。所以,优化策略是必须的。

  1. 分页查询(LIMITOFFSET): 这是最直接也是最常用的方法。不要一次性查询所有数据,而是分批次获取。

    SELECT * FROM articles ORDER BY publish_date DESC LIMIT 20 OFFSET 0; -- 第一页,取20条
    SELECT * FROM articles ORDER BY publish_date DESC LIMIT 20 OFFSET 20; -- 第二页,取20条

    在PHP中,你可以根据用户请求的页码和每页显示的条数来动态计算OFFSET

    $page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
    $limit = 20;
    $offset = ($page - 1) * $limit;
    
    $stmt = $pdo->prepare("SELECT id, title, author FROM articles ORDER BY publish_date DESC LIMIT :limit OFFSET :offset");
    $stmt->bindParam(':limit', $limit, PDO::PARAM_INT);
    $stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
    $stmt->execute();
    $articles = $stmt->fetchAll();

    这能显著减少每次查询的数据量,减轻数据库和PHP应用的内存压力。

  2. 只选择必要的字段: 避免使用SELECT *。只查询你真正需要的列。

    -- 不推荐
    SELECT * FROM users;
    -- 推荐
    SELECT id, username, email FROM users;

    减少数据传输量,数据库也不需要处理不必要的字段。

  3. 合理使用索引:WHERE子句、JOIN条件和ORDER BY子句中经常使用的列创建索引。索引能大幅提升查询速度,尤其是在数据量大的情况下。

    ALTER TABLE users ADD INDEX idx_username (username);

    但也要注意,过多的索引会增加写入(INSERT/UPDATE/DELETE)操作的开销,所以要权衡。

  4. 使用yield关键字处理大数据集(PHP生成器): 如果你确实需要遍历一个非常大的结果集,但又不想一次性加载到内存,PHP的生成器(Generator)是一个非常优雅的解决方案。它允许你在需要时才获取下一条数据,而不是一次性全部加载。

    function getLargeResultSet(PDO $pdo) {
        $stmt = $pdo->query("SELECT id, data FROM very_large_table");
        while ($row = $stmt->fetch()) {
            yield $row; // 每次只返回一行数据
        }
    }
    
    // 遍历时,内存占用会非常小
    foreach (getLargeResultSet($pdo) as $item) {
        // 处理 $item
        echo $item['id'] . ": " . $item['data'] . "
    "; }

    这在处理日志文件、大数据导出等场景下特别有用。

  5. 考虑数据库连接池和持久连接: 虽然不是直接针对查询结果的优化,但连接的建立和关闭也是开销。在某些高并发场景下,使用持久连接(PDO::ATTR_PERSISTENT => true)或连接池可以减少连接建立的开销。但这需要谨慎使用,因为持久连接可能会带来一些意外的状态管理问题。

  6. 查询缓存(如果适用): MySQL有自己的查询缓存机制,但它在MySQL 8.0中已被移除,因为它在高并发场景下表现不佳。现在更推荐在应用层使用缓存,例如Redis或Memcached,来缓存频繁查询且不常变动的数据。这能极大减轻数据库的压力。

这些策略并非相互独立,通常是组合使用,才能在处理大量数据时达到最佳效果。

在PHP应用中,选择mysqli还是PDO扩展进行MySQL数据库操作更具优势?

这是一个老生常谈的问题,也是很多开发者在项目初期会纠结的点。在我看来,虽然两者都能完成MySQL数据库操作,但PDO在大多数现代PHP应用中更具优势

我个人偏向PDO,原因如下:

  1. 数据库抽象层(Database Abstraction Layer, DAL): PDO最大的特点是它是一个数据库抽象层。这意味着如果你有一天需要从MySQL切换到PostgreSQL、SQLite或其他数据库,你只需要修改连接字符串和一些配置,而核心的查询逻辑代码几乎不需要改动。这对于需要支持多种数据库或未来可能需要切换数据库的项目来说,是一个巨大的优势。mysqli则只能用于MySQL。

  2. 统一的API: PDO提供了一致的、面向对象的API来处理所有支持的数据库。一旦你掌握了PDO,你就可以用同样的方式操作不同的数据库。这简化了学习曲线,也减少了代码的复杂性。

  3. 更强大的预处理和参数绑定: 虽然mysqli也支持预处理语句,但PDO的实现通常被认为更灵活和易用。它支持命名占位符(如:name),这使得SQL语句在有多个参数时更具可读性。mysqli只支持匿名占位符(?),需要你严格按照顺序绑定参数,这在参数多的时候容易出错。

  4. 更灵活的错误处理: PDO允许你设置不同的错误模式。我通常会设置PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION,这样数据库错误就会以异常的形式抛出,这与现代PHP的错误处理机制(try-catch)完美结合,使得错误捕获和处理更加清晰和优雅。mysqli的错误处理通常需要手动检查错误码和错误信息。

  5. 更好的安全性: 虽然两者都支持预处理,但PDO的默认行为和设计哲学在一定程度上鼓励更安全的编码实践。

当然,mysqli也有它的优点,特别是在一些特定场景下:

  • 性能: 在某些基准测试中,mysqli在纯粹的MySQL操作上可能会略微快于PDO,因为它更直接地与MySQL API交互,开销可能更小。但对于大多数Web应用来说,这种性能差异微乎其微,通常不会成为瓶颈。
  • MySQL特有功能: 如果你的应用需要大量使用MySQL的特定高级功能(例如存储过程、多语句查询等),mysqli可能会提供更直接或更完整的支持。

总结一下我的建议:

对于新的PHP项目,尤其是那些需要考虑未来扩展性、维护性和代码整洁度的项目,我强烈推荐使用PDO。它的抽象能力、统一API和优秀的错误处理机制,能够帮助你构建更健壮、更灵活的应用。

如果你正在维护一个历史项目,并且它已经大量使用了mysqli,那么继续使用mysqli可能更实际,因为重构的成本可能很高。但即使如此,也要确保你充分利用了mysqli的预处理语句来防止SQL注入。

最终的选择,还是取决于你的项目需求、团队熟悉度以及对未来发展的考量。但从现代PHP开发趋势来看,PDO无疑是更主流和推荐的选择。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2789

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1688

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1548

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

1036

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1485

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1256

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1589

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1307

2023.11.13

C++ 高级模板编程与元编程
C++ 高级模板编程与元编程

本专题深入讲解 C++ 中的高级模板编程与元编程技术,涵盖模板特化、SFINAE、模板递归、类型萃取、编译时常量与计算、C++17 的折叠表达式与变长模板参数等。通过多个实际示例,帮助开发者掌握 如何利用 C++ 模板机制编写高效、可扩展的通用代码,并提升代码的灵活性与性能。

4

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 14.2万人学习

Node.js 教程
Node.js 教程

共57课时 | 9.2万人学习

CSS3 教程
CSS3 教程

共18课时 | 4.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号