如何写数据库查询脚本

wen 实用脚本 27

本文目录导读:

如何写数据库查询脚本

  1. 第一部分:核心基础(SQL 标准语法)
  2. 第二部分:不同数据库的特定语法差异
  3. 第三部分:真实场景脚本示例
  4. 第四部分:最佳实践与注意事项
  5. 总结步骤

编写数据库查询脚本是数据管理和分析的核心技能,为了给你最实用、专业的指导,我将从基础语法不同数据库的差异以及最佳实践三个层面来讲解。


第一部分:核心基础(SQL 标准语法)

无论你使用 MySQL、PostgreSQL、SQL Server 还是 Oracle,以下语法是通用的。

基本查询结构

-- 注释:单行注释用两个短横线,多行用 /* */
SELECT 列名1, 列名2, ...  -- 指定你要查询哪些列
FROM 表名               -- 指定从哪个表查
WHERE 条件              -- 筛选行(可选)
GROUP BY 列名           -- 分组聚合(可选)
HAVING 聚合条件          -- 对分组结果筛选(可选)
ORDER BY 列名 [ASC|DESC]; -- 排序(可选)

常用子句详解

  • SELECT:你可以用 选择所有列,但生产环境中强烈建议显式列出列名,以提高性能。

    -- 不推荐
    SELECT * FROM users;
    -- 推荐
    SELECT id, username, email, signup_date FROM users;
  • WHERE:用于过滤记录。

    -- 精确匹配
    SELECT * FROM orders WHERE status = 'paid';
    -- 范围查询
    SELECT * FROM products WHERE price BETWEEN 10 AND 100;
    -- 模糊匹配
    SELECT * FROM customers WHERE name LIKE '%张%';  -- % 表示任意字符
    -- 多条件
    SELECT * FROM employees WHERE department = 'IT' AND salary > 5000;
    SELECT * FROM products WHERE category = 'A' OR category = 'B';
  • JOIN:连接多张表(这是查询最强大的功能之一)。

    -- 内连接:返回两张表中匹配的记录
    SELECT u.username, o.order_amount
    FROM users u
    INNER JOIN orders o ON u.id = o.user_id;
    -- 左外连接:返回左表所有记录,右表无匹配则显示 NULL
    SELECT u.username, o.order_amount
    FROM users u
    LEFT JOIN orders o ON u.id = o.user_id;
    -- 右外连接:与 LEFT JOIN 相反
    -- 全外连接:MySQL 不支持但其他支持,表示并集
  • GROUP BY 与聚合函数

    -- 常用聚合函数: COUNT, SUM, AVG, MAX, MIN
    SELECT department, AVG(salary) as avg_salary, COUNT(*) as emp_count
    FROM employees
    GROUP BY department
    HAVING avg_salary > 6000;  -- HAVING 是对分组后的结果过滤,WHERE 是对分组前过滤
  • ORDER BY 与分页

    -- 排序
    SELECT * FROM products ORDER BY price DESC, name ASC;
    -- 分页 (不同数据库语法不同)
    -- MySQL / PostgreSQL
    SELECT * FROM products LIMIT 10 OFFSET 20;  -- 第3页,每页10条
    -- SQL Server
    SELECT * FROM products ORDER BY id OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

第二部分:不同数据库的特定语法差异

写脚本时注意这些差异可以避免报错。

特性 MySQL PostgreSQL SQL Server Oracle
字符串连接 CONCAT(a, b)a \|\| b a \|\| bCONCAT() a + b (注意类型) a \|\| b
当前日期 CURDATE(), NOW() CURRENT_DATE, NOW() GETDATE() SYSDATE
文本长度 LENGTH() LENGTH()CHAR_LENGTH() LEN() LENGTH()
系统表/视图 information_schema pg_cataloginformation_schema sys.tables, INFORMATION_SCHEMA ALL_TABLES
分页语法 LIMIT x OFFSET y LIMIT x OFFSET y OFFSET...FETCH ROWNUMFETCH (12c+)
查询前N条 LIMIT 10 LIMIT 10 SELECT TOP 10 ... FETCH FIRST 10 ROWS ONLY

第三部分:真实场景脚本示例

假设我们有一个电商数据库。

场景 1:查询“最近30天活跃用户及其订单总额”

-- 目标:找出活跃用户及其消费能力
SELECT
    u.id,
    u.username,
    COUNT(o.id) AS order_count,          -- 下单次数
    SUM(o.total_amount) AS total_spent   -- 总消费金额
FROM
    users u
INNER JOIN
    orders o ON u.id = o.user_id
WHERE
    o.created_at >= CURRENT_DATE - INTERVAL '30' DAY  -- 最近30天
GROUP BY
    u.id, u.username
HAVING
    COUNT(o.id) >= 2                      -- 至少下过2单
ORDER BY
    total_spent DESC
LIMIT 20;                                  -- 只看前20名

场景 2:检查数据库性能(查询慢查询或索引状态)

-- MySQL 查看当前运行的查询
SHOW FULL PROCESSLIST;
-- 查看是否有表锁 (MySQL)
SHOW OPEN TABLES WHERE In_use > 0;
-- SQL Server 查看当前阻塞
SELECT * FROM sys.dm_exec_requests WHERE blocking_session_id != 0;

场景 3:数据清洗(查找重复数据)

-- 找出 email 重复的用户
SELECT
    email,
    COUNT(*) AS cnt
FROM
    users
GROUP BY
    email
HAVING
    COUNT(*) > 1;
-- 删除重复数据(保留 ID 最小的那一条,谨慎操作)
DELETE FROM users
WHERE id NOT IN (
    SELECT MIN(id)
    FROM users
    GROUP BY email
);

第四部分:最佳实践与注意事项

  1. 安全第一:不要直连生产库写脚本

    • 测试数据库只读副本上验证脚本正确性。
    • 执行 UPDATEDELETE 语句前,先转成 SELECT 看一眼结果。
  2. 性能优化(索引与执行计划)

    • WHERE 子句中的列尽量有索引。
    • 避免在 WHERE 中对列使用函数(如 WHERE DATE(create_time) = '2023-01-01',应改为 WHERE create_time >= '2023-01-01' AND create_time < '2023-01-02')。
    • 使用 EXPLAIN 命令(如 EXPLAIN SELECT ...)查看查询执行计划,找出慢的原因。
  3. 可读性

    • SQL 关键字使用大写,表名/列名使用小写(团队约定)。
    • 复杂查询使用 CTE(公用表表达式,WITH 子句)拆分逻辑。
    -- 使用 CTE 的可读性更好
    WITH active_users AS (
        SELECT user_id, COUNT(*) as cnt
        FROM orders
        WHERE created_at > '2023-01-01'
        GROUP BY user_id
        HAVING cnt > 5
    )
    SELECT u.name, a.cnt
    FROM users u
    INNER JOIN active_users a ON u.id = a.user_id;
  4. 参数化查询

    • 如果你在代码(如 Python、Java)中拼接查询字符串,务必使用参数占位符,防止 SQL 注入。
    # Python 示例(错误做法)
    cursor.execute("SELECT * FROM users WHERE name = '" + name + "'")
    # Python 示例(正确做法)
    cursor.execute("SELECT * FROM users WHERE name = %s", (name,))

总结步骤

  1. 明确需求:我需要哪几张表的哪些列?筛选条件是什么?
  2. 从单表开始:先写 SELECT ... FROM ... WHERE ... 跑通看数据对不对。
  3. 逐步加 JOIN:确认连接键(通常为主外键)是否正确。
  4. 加入聚合与排序GROUP BY 后再 ORDER BY
  5. 调试与优化EXPLAIN 检查性能,加索引。
  6. 安全上线:在非生产环境测试无误后,再在生产环境执行。

如果你有具体的数据库类型(如 MySQL 8.0 还是 PostgreSQL 15)或者特定的业务场景,可以告诉我,我能提供更精确的脚本示例。

抱歉,评论功能暂时关闭!