SQLite06-常用对象

文章目录

SQLite06-常用对象

1、视图(View)

(1)概念
  • 虚拟表定义
    • 视图是基于预定义 SELECT 查询的虚拟表,不存储实际数据。
    • 数据动态生成:每次查询视图时实时执行底层 SQL 语句。
  • 核心用途
    • 简化复杂查询:封装多表连接或聚合操作。
    • 数据安全:限制用户访问敏感字段(如隐藏薪资列)。
    • 逻辑抽象:为应用层提供统一数据接口。
  • 只读限制
    • 不支持直接修改:无法在视图上执行 INSERT/UPDATE/DELETE
    • 替代方案:通过 INSTEAD OF 触发器间接实现数据更新(需自定义逻辑)。
(2)视图创建
  • 语法
sql 复制代码
-- 基础语法
CREATE VIEW [IF NOT EXISTS] 视图名称 AS  
SELECT 列1, 列2, ...  
FROM 表名  
[WHERE 条件]  
[GROUP BY 分组]  
[HAVING 过滤条件];  
  • 示例 1:简化多表关联查询
sql 复制代码
-- 创建视图:客户订单视图  
CREATE VIEW customer_orders AS  
SELECT customers.name, orders.product, orders.order_date  
FROM customers  
JOIN orders ON customers.id = orders.customer_id;  
  • 示例 2:隐藏敏感字段
sql 复制代码
-- 创建视图:公开员工信息(隐藏薪资)  
CREATE VIEW employee_public AS  
SELECT id, name, department FROM employees;  
(3)视图查询
  • 语法
sql 复制代码
-- 与查询普通表语法相同  
SELECT * FROM 视图名称 [WHERE 条件];  
  • 示例:查询订单视图
sql 复制代码
-- 筛选 2023 年后的订单  
SELECT * FROM customer_orders  
WHERE order_date > '2023-01-01';  
(4)视图删改
  • 语法
sql 复制代码
-- 删除视图  
DROP VIEW IF EXISTS 视图名称;  
 
-- 更新视图(需删除后重建)  
DROP VIEW IF EXISTS employee_public;  
CREATE VIEW employee_public AS  
SELECT id, name, department, hire_date FROM employees;  -- 新增入职日期列  
(5)综合案例
  • 场景:整合 products(产品表)、sales(销售表)生成月度销售汇总视图。
sql 复制代码
-- 创建视图:月度销售汇总  
CREATE VIEW monthly_sales_report AS  
SELECT 
    strftime('%Y-%m', sale_date) AS month,  -- 按月分组 
    products.name AS product_name,
    SUM(sales.quantity) AS total_quantity,
    SUM(sales.quantity * products.price) AS total_revenue
FROM sales  
JOIN products ON sales.product_id = products.id  
GROUP BY month, product_name;  
  • 查询视图:
sql 复制代码
-- 获取 2024 年销售额最高的产品  
SELECT product_name, total_revenue  
FROM monthly_sales_report  
WHERE month LIKE '2024-%'  
ORDER BY total_revenue DESC  
LIMIT 5;  
(6)注意事项
  • 只读限制
sql 复制代码
-- 错误示例:禁止通过视图插入数据  
INSERT INTO customer_orders VALUES ('Alice', 'Laptop', '2025-07-15');  -- 报错!
  • 性能优化:避免嵌套多层视图(如 VIEW_A 依赖 VIEW_B),可能导致查询效率下降。

2、索引(Index)

(1)概念
  • 核心定义
    • 索引是数据库中的特殊数据结构,类似于书籍的目录。它通过建立字段值与数据位置的映射关系,避免全表扫描,显著提升查询效率。
    • 类比:通过字典拼音目录查字,无需逐页翻阅。
  • 核心价值
    • ✅ 加速查询:对 WHEREJOINORDER BY 等操作优化明显。
    • ❌ 副作用:增加存储空间,降低 INSERT/UPDATE/DELETE 速度(需同步维护索引)
(2)索引创建
  • 单列索引
sql 复制代码
-- 基础语法 
CREATE INDEX [IF NOT EXISTS] 索引名 
ON 表名(列名);
 
-- 示例:为 employees 表的 salary 列创建索引 
CREATE INDEX idx_salary ON employees(salary);
  • 唯一索引
sql 复制代码
-- 强制列值的唯一性 
CREATE UNIQUE INDEX [IF NOT EXISTS] 索引名 
ON 表名(列名);
 
-- 示例:防止 users 表的 email 重复 
CREATE UNIQUE INDEX uq_email ON users(email);
  • 组合索引
sql 复制代码
-- 基于多列的联合查询优化 
CREATE INDEX 索引名 
ON 表名(列1, 列2);
 
-- 示例:优化 orders 表的 user_id 和 status 联合查询 
CREATE INDEX idx_user_status ON orders(user_id, status);
(3)索引查看
  • 查看所有索引
sql 复制代码
-- 查看当前数据库所有索引 
SELECT name, sql FROM sqlite_master WHERE type = 'index';
 
-- 查看特定表索引 
.indices 表名  -- SQLite 命令行工具专用语法 
  • 查看索引结构
sql 复制代码
-- 显示索引的创建语句 
.schema 索引名 
(4)索引删除
sql 复制代码
-- 基础语法 
DROP INDEX [IF EXISTS] 索引名;
 
-- 示例:删除无效索引 
DROP INDEX IF EXISTS idx_old;
(5)隐式索引
  • 自动创建场景:主键(PRIMARY KEY)和唯一约束(UNIQUE)会自动生成唯一索引,例如:
sql 复制代码
CREATE TABLE products (
    id INTEGER PRIMARY KEY,  -- 自动创建隐式索引 
    sku TEXT UNIQUE          -- 自动创建隐式索引 
);
(6)注意事项
  • 性能权衡
    • 适用场景:频繁的 WHEREJOINORDER BY 操作列
    • 避免场景:小表(数据量 < 1000行)、高频写入列(降低 INSERT/UPDATE 速度)
  • 组合索引优化
    • 列顺序原则:将高频查询条件列放在左侧
    • 示例:WHERE a=1 AND b=2 优先使用 (a,b) 而非 (b,a)
  • 索引维护建议
    • 定期重建:数据频繁修改后使用 REINDEX 索引名 优化性能
    • 命名规范:建议使用 idx_表名_列名 格式提升可读性

3、触发器(Trigger)

(1)概念
  • 在指定数据库事件(增/删/改)发生时自动执行预设操作,常用于:
    • 数据校验:拦截非法值(如负数的库存)
    • 级联更新:自动同步关联表数据(如订单表删除时清理明细表)
    • 审计追踪:记录关键操作日志(如用户表修改时备份旧数据)
    • 业务计算:实时更新统计字段(如订单总额变化时刷新客户总消费)
(2)类型详解
  • 按触发时机分类
类型 语法关键字 执行时机
BEFORE 触发器 BEFORE INSERT/UPDATE/DELETE 在操作生效前执行,可修改或取消操作
AFTER 触发器 AFTER INSERT/UPDATE/DELETE 在操作生效后执行,适合日志记录
  • 按触发粒度分类
类型 语法关键字 说明
行级触发器 (ROW) FOR EACH ROW 默认类型,每影响一行数据触发一次
语句级触发器 ❌ 不支持 SQLite 仅支持行级触发器
  • 重要限制:SQLite 不支持 INSTEAD OF 触发器(常用于视图更新)
(3)核心语法
  • 核心语法
sql 复制代码
-- 基础语法 
CREATE TRIGGER [IF NOT EXISTS] 触发器名  
[BEFORE | AFTER] [INSERT | UPDATE | DELETE] ON 表名  
FOR EACH ROW  -- SQLite 仅支持行级触发器  
[WHEN 条件]  
BEGIN  
    -- 触发动作(SQL 语句)  
END;  
 
-- 删除触发器 
DROP TRIGGER IF EXISTS 触发器名;
  • 关键特性:
    • 行级触发:每行数据变更都会激活触发器(FOR EACH ROW 必选)
    • 临时表访问:
      • NEW.列名 → 获取 插入/更新后 的值
      • OLD.列名 → 获取 更新前/删除前 的值
    • 异常处理:用 RAISE() 抛出错误(如 RAISE(ABORT, '错误消息')
(4)案例演示
  • ✅ 案例 1:数据验证(阻止非法操作)
sql 复制代码
-- 禁止插入未来入职日期的员工 
CREATE TRIGGER validate_hire_date  
BEFORE INSERT ON employees  
FOR EACH ROW  
WHEN NEW.hire_date > date('now')  
BEGIN  
    RAISE(ABORT, '入职日期不能是未来时间');  
END;
  • 效果:插入 hire_date = '2025-12-31' 时触发报错。
  • ✅ 案例 2:自动审计日志
sql 复制代码
-- 记录薪资变更历史 
CREATE TRIGGER log_salary_changes  
AFTER UPDATE ON salaries  
FOR EACH ROW  
BEGIN  
    INSERT INTO salary_audit(emp_id, old_salary, new_salary, change_time)  
    VALUES (OLD.emp_id, OLD.amount, NEW.amount, datetime('now'));  
END;
  • 效果:每次薪资更新时自动记录变更前后的值。
  • ✅ 案例 3:级联删除关联数据
sql 复制代码
-- 删除员工时同步删除相关记录 
CREATE TRIGGER cascade_employee_delete  
AFTER DELETE ON employees  
FOR EACH ROW  
BEGIN  
    DELETE FROM salaries WHERE emp_id = OLD.id;  
    DELETE FROM titles WHERE emp_id = OLD.id;  
END;
  • 效果:删除员工后自动清理薪资和职位表。
  • ✅ 案例 4:自动计算字段
sql 复制代码
-- 更新库存金额(数量 × 单价)
CREATE TRIGGER update_inventory_value  
AFTER UPDATE OF quantity, price ON inventory  
FOR EACH ROW  
BEGIN  
    UPDATE inventory  
    SET total_value = NEW.quantity * NEW.price  
    WHERE id = NEW.id;  
END;
  • 效果:修改数量或单价时自动重算总金额。
(5)注意事项
  • 只读性限制:SQLite 不支持通过触发器修改 NEW 值(不同于 MySQL)。
  • 性能影响:避免在频繁更新的表上创建复杂触发器,可能拖慢写入速度。
  • 递归触发:确保触发器逻辑不会循环调用自身(如 A 触发器 → 更新表 → 激活 A 触发器)。
  • 临时表作用域:OLD/NEW 仅在行级触发器中有效,语句级触发器不可用。

4、临时表(Temporary)

(1)概念
  • SQLite中的临时表是一种特殊的表,用于临时存储中间数据,其生命周期与数据库连接绑定,连接断开后自动删除,无需手动清理。
  • 核心特点
    • 自动删除:数据库连接断开后,临时表自动删除,无需手动执行DROP TABLE命令
    • 命名空间:在SQLite中,临时表会存储在temp命名空间下,查看时显示为temp.tablename
    • 会话隔离:临时表仅对创建它的连接可见,其他连接无法访问
  • 作用意义
    • 提高查询效率:对于复杂查询,将中间结果存储在临时表中,可以避免重复计算
    • 减少主表压力:避免对主表进行多次扫描
    • 简化逻辑:将复杂查询拆分为多个步骤,提高可读性
    • 数据隔离:确保临时数据不会影响主表数据
(2)创建语法
  • SQLite创建临时表的语法如下:
sql 复制代码
CREATE TEMPORARY TABLE tablename (
    dataname datatype
);
  • 例如:
sql 复制代码
CREATE TEMPORARY TABLE temp_sales (
    sale_id INTEGER PRIMARY KEY,
    amount DECIMAL(10, 2)
);
  • 使用示例
sql 复制代码
-- 创建临时表
CREATE TEMPORARY TABLE temp_products (
    product_id INTEGER PRIMARY KEY,
    product_name TEXT,
    price DECIMAL(10, 2)
);

-- 插入数据
INSERT INTO temp_products VALUES (1, 'Laptop', 999.99);
INSERT INTO temp_products VALUES (2, 'Smartphone', 599.99);

-- 查询临时表
SELECT * FROM temp_products;

-- 临时表在当前连接结束时自动删除,无需DROP
(3)使用场景
  • 临时存储中间结果:在复杂查询中存储中间结果,避免重复计算
  • 数据处理:处理大数据集时分步处理,减少内存压力
  • 数据隔离:在会话中隔离临时数据,避免污染主表
(4)临时表 vs 常规表
特性 临时表 常规表
生命周期 仅当前连接存在 持久存储
作用域 仅创建它的连接可见 所有连接可见
删除方式 自动删除 需手动DROP
存储位置 临时文件 数据库文件
(5)临时表 vs 子查询
  • SQLite中也可以使用子查询作为临时表(派生表),例如:
sql 复制代码
SELECT * FROM (
    SELECT product_id, price 
    FROM products 
    WHERE price > 500
) AS temp_table;
  • 这种子查询方式创建的"临时表"仅在当前查询中有效,而CREATE TEMPORARY TABLE创建的临时表可以在后续多个查询中重复使用。
相关推荐
兆子龙2 小时前
React useTransition:让 UI 更新更丝滑的并发特性
java·javascript
无名-CODING2 小时前
java基础面试知识点
java·python·面试
晔子yy2 小时前
【JAVA探索之路】简单聊聊Kafka
java·开发语言
lclcooky2 小时前
【postgresql】分区表管理
java·数据库·postgresql
NineData2 小时前
TB级数据手工校验要多久?用NineData仅需小时级别
数据库
东离与糖宝2 小时前
Jakarta EE新规范解读:Java+AI在微服务与云原生中的落地实战(附代码示例)
java·人工智能
zzb158010 小时前
RAG from Scratch-优化-query
java·数据库·人工智能·后端·spring·mybatis
一只鹿鹿鹿10 小时前
信息安全等级保护安全建设防护解决方案(总体资料)
运维·开发语言·数据库·面试·职场和发展
堕27410 小时前
MySQL数据库《基础篇--数据库索引(2)》
数据库·mysql