SQL Server视图定义中禁止使用OPTION(RECOMPILE),因其在DDL解析阶段即被语法拒绝;必须在调用视图的外部查询中添加该提示,如SELECT * FROM my_view OPTION(RECOMPILE)。

SQL Server视图定义里不能写 OPTION(RECOMPILE)
因为语法层面直接禁止——CREATE VIEW 的 SELECT 子句明确不支持 OPTION 子句。执行 CREATE VIEW v AS SELECT * FROM t OPTION(RECOMPILE) 会报错:Msg 156, Level 15, State 1,提示关键字 'option' 附近有语法错误。
这不是优化器限制,也不是版本问题,而是 SQL Server 解析器在 DDL 阶段就拒绝了该结构。官方文档明确列出 OPTION 属于视图定义中「不允许出现」的语法项之一。
外部查询加 OPTION(RECOMPILE) 才是合法且有效的做法
视图本身只是命名的 SELECT 语句,真正执行时它被内联展开为底层查询树。所以提示必须加在「调用视图」的位置,而不是定义位置。
-
SELECT * FROM my_view WHERE status = @status OPTION(RECOMPILE)是合法的,且能解决参数嗅探导致的计划劣化 - 如果视图含多个表 JOIN,
OPTION(RECOMPILE)作用于整个查询,不是只影响某个表 - 注意编译开销:对毫秒级高频查询,反复编译可能比次优计划更伤性能
FORCESEEK 等表提示也必须写在外部查询中
视图定义里不能写 WITH (FORCESEEK),但可以在查询视图时对别名加提示:
SELECT * FROM my_view v WITH (FORCESEEK) WHERE v.create_time > '2024-01-01'
不过要注意:
-
WITH (FORCESEEK)只作用于v对应的基表,不影响 JOIN 的其他表 - 若视图底层用了计算列(如
CONVERT(VARCHAR, create_time, 120)),即使加了FORCESEEK也无法触发 Seek,因为索引已不可 SARGable -
WITH (INDEX=...)容易失效,优先用FORCESEEK或FORCESCAN这类行为级提示
QUERY_STORE_HINTS 是绕过代码修改的替代方案
如果你无法改应用层 SQL(比如视图被硬编码在报表工具里),又需要稳定计划,QUERY_STORE_HINTS 是更现实的选择:
- 它不依赖修改原始 SQL,而是通过系统视图
sys.query_store_plan关联 hint 注入 - 仅适用于 SQL Server 2022+ / Azure SQL,老版本只能靠计划指南(Plan Guide),但后者维护成本高
- 提示内容仍受限制:比如不能给视图内部加
RECOMPILE,但可以对外部调用加USE HINT('DISABLE_PARAMETER_SNIFFING')
真正容易被忽略的是:视图一旦嵌套多层,或参与跨链接服务器查询,基数估计就会崩成固定值 10000,这时候光加提示没用,得先重构视图逻辑或补统计信息。










