选择何时使用每个选项
SQL Server 可编程性对象提供了在数据库中封装和重用逻辑的不同方法。 每个对象类型(视图、 存储过程、 函数和 触发器)都提供不同的用途,并提供独特的功能。
比较选项
下表总结了每种对象类型的关键功能和限制:
| 能力 | Views | 存储过程 | Functions | Triggers |
|---|---|---|---|---|
| 接受参数 | 否 | 是的 | 是的 | 否 |
| 修改数据 | 受限制 | 是的 | 否 | 是的 |
| 返回结果集 | 是的 | 是的 | 是 (TVFs) | 否 |
用于 SELECT/JOIN |
是的 | 否 | 是的 | 否 |
| 事务控制 | 否 | 是的 | 否 | 是的 |
| 自动执行 | 否 | 否 | 否 | 是的 |
| 执行计划缓存 | 否 | 是的 | 多种多样 | 是的 |
仅当更改影响单个基表时,视图才能修改数据。 内联表值函数受益于计划缓存,因为优化器将它们直接扩展到查询计划中。 多语句表值函数 (TVF) 和标量函数被视为“黑匣子”,优化器看不到它们的内部,通常会导致行数估计不准确,进而生成不佳的计划。
根据要求进行选择
正确的可编程性对象取决于您需要完成的工作。 使用此决策框架指导你的选择:
在需要时选择视图:
- 简化对复杂联接或常用筛选数据的访问
- 通过控制列和行可见性提供安全层
- 创建可能更改的基础表的稳定接口
- 在不接受参数或修改值的情况下呈现数据
在需要时选择存储过程:
- 使用多个语句执行复杂的业务逻辑
- 在单个事务中跨多个表修改数据
- 接受输入参数并返回输出参数或结果集
- 实现错误处理和事务控制
在需要以下情况下选择函数:
- 执行可重用计算,以返回在查询中使用的值
- 返回参数化结果集(表值函数)
- 在
SELECT、WHERE或JOIN子句中直接嵌入逻辑 - 确保索引的确定性结果(针对特定函数类型)
需要时选择触发器:
- 自动响应数据修改事件
- 强制实施超出约束的复杂业务规则
- 维护数据更改的审核日志
- 自动跨表同步相关数据
应用决策情景
请考虑以下常见方案和针对每个方案的建议方法:
| Scenario | 推荐对象 | 为什么 |
|---|---|---|
| 简化多个报表使用的 5 表联接 | 视图 | 封装复杂性;不需要任何参数 |
| 处理订单:验证库存、插入订单、更新库存 | 存储过程 | 在一次事务中进行的多次修改 |
| 根据重量和目标计算发货成本 | 标量函数 | 查询中的可重用计算 |
| 返回日期范围内客户的所有订单 | Table-valued 函数 | 参数化的结果集可用 JOIN |
记录Salary列的所有更改 |
Trigger | 自动化且透明的审计日志 |
| 在没有 SSN 的情况下提供对员工数据的只读访问权限 | 视图 | 安全层用于隐藏敏感列 |
避免常见错误
选择可编程性对象时,请观察以下陷阱:
在大型表的子句中使用
WHERE标量函数 - 该函数针对每一行执行,从而降低性能。 请考虑使用内联表值函数或重新编写逻辑。为存储过程更好地处理的逻辑创建触发器 — 触发器隐式执行且难以调试。 仅在自动执行至关重要时使用它们。
构建嵌套其他视图的复杂视图 - 深度嵌套视图难以优化和维护。 使视图定义保持专注和浅表。
当函数可以更好地集成时选择存储过程 — 如果需要
SELECT语句中的结果,函数提供的语法比EXEC的临时表更简洁。
通过了解每个可编程性对象的优缺点和权衡,可以为数据库设计和实现任务选择适当的工具。