SQLite视图不能替代计算列,但能通过封装SELECT表达式动态计算实现等效效果;它不支持GENERATED ALWAYS AS语法,也不存储结果,仅在查询时实时计算。
不能直接替代,但能实现等效效果。SQLite本身不支持像PostgreSQL那样的GENERATED ALWAYS AS计算列语法,也没有存储计算结果的能力;但视图可以封装SELECT表达式,在查询时动态计算——这正是最常用、最轻量的模拟方式。
关键不是“定义列”,而是把计算逻辑写进视图的SELECT字段里。比如有表orders含price和qty,想模拟total列:
CREATE VIEW orders_with_total ASSELECT *, price * qty AS totalFROM orders;
之后查询SELECT * FROM orders_with_total就能看到total字段,且每次都是实时计算的。
SELECT *或显式列出所有原表字段,否则会丢失原始列ORDER BY或LIMIT——它们在视图定义中被忽略(除非加OFFSET 0强制物化,但不推荐)_view或_with_*,避免和基表混淆能,SQLite优化器通常会将视图外层的WHERE条件自动下推到基表扫描,只要表达式不含不可下推项(如子查询、某些函数)。例如:
SELECT * FROM orders_with_total WHERE total > 100;
SQLite实际执行的是SELECT *, price * qty AS total FROM orders WHERE price * qty > 100(或等价形式),不会先算出全部total再过滤。
CASE或COALESCE等函数,下推仍有效;但若用了strftime()处理非索引日期字段,可能无法利用索引CREATE INDEX idx_orders_price_qty ON orders(price, qty)
CAST(... AS TEXT)之类包装原字段——它可能阻止索引使用因为视图是只读逻辑层,SQLite默认禁止对包含表达式、*、聚合或连接的视图做DML操作。即使简单如price * qty AS total,也会让视图变为non-updatable。
SELECT id, name FROM users
CREATE TRIGGER)在INSERT/UPDATE时填充真实列,而不是依赖视图UPDATE ... SET total = 200会报错:attempt to assign to non-updatable column
真正要“模拟计算列”并支持写入,得放弃视图,改用真实列+触发器维护,或者在应用层保证写入一致性——视图只负责读取侧的干净接口。