视图引用表计算列时sys.columns的is_computed属性异常解决方案求助
问题本质说明
这是SQL Server的预设设计,sys.columns里的is_computed字段针对视图时,仅标记视图本身定义时生成的计算列,不会继承基表列的计算列属性,所以sp_refreshview也不会同步这个属性,属于正常设计而非缺陷。
解决方案
方案1:使用系统依赖函数优化查询效率
你之前用到的sys.dm_exec_describe_first_result_set需要动态解析查询执行计划,性能开销高,可以改用SQL Server内置的依赖解析函数直接关联元数据,查询速度提升非常明显,示例代码如下:
DECLARE @viewname SYSNAME = 'your_view_name', @colum_name SYSNAME = 'target_column_name'; SELECT TOP 1 c.is_computed FROM sys.columns vc -- 关联视图列对应的基表依赖 CROSS APPLY sys.dm_sql_referenced_entities(OBJECT_SCHEMA_NAME(vc.object_id) + '.' + OBJECT_NAME(vc.object_id), 'OBJECT') re INNER JOIN sys.columns c ON c.object_id = re.referenced_id AND c.name = re.referenced_minor_name WHERE vc.object_id = OBJECT_ID(@viewname) AND vc.name = @colum_name AND re.referenced_minor_id > 0 -- 仅筛选列级依赖 AND c.is_computed = 1;
该方案不需要动态执行查询,完全基于系统元数据表关联,执行效率比原有写法高1-2个数量级,适合单次查询场景。
方案2:预构建元数据缓存视图
如果需要高频查询所有视图的列是否继承自基表的计算列,可以预先构建一个缓存所有视图列属性的视图,也可以加索引做成索引视图进一步提升性能:
CREATE VIEW dbo.vw_ViewColumnComputedFlag AS SELECT view_object_id = vc.object_id, view_name = OBJECT_NAME(vc.object_id), view_column_name = vc.name, base_table_is_computed = ISNULL(c.is_computed, 0) FROM sys.columns vc INNER JOIN sys.views v ON vc.object_id = v.object_id OUTER APPLY sys.dm_sql_referenced_entities(OBJECT_SCHEMA_NAME(v.object_id) + '.' + v.name, 'OBJECT') re LEFT JOIN sys.columns c ON c.object_id = re.referenced_id AND c.name = re.referenced_minor_name AND re.referenced_minor_id > 0 WHERE re.referenced_entity_name IS NOT NULL;
之后查询时直接过滤view_name和view_column_name即可,毫秒级返回结果。
方案3:显式在视图中定义计算列(不推荐)
如果必须让视图的sys.columns.is_computed直接返回1,可以在视图定义时重复写一遍计算列的逻辑,比如基表的计算列是col AS a + b,视图里写为col AS a + b而不是直接引用基表的col,此时视图层面的is_computed会被标记为1,但会造成逻辑冗余,基表计算列逻辑变更时需要同步修改视图定义,维护成本高,仅适合特殊场景使用。
内容的提问来源于stack exchange,提问作者Modestas Dromantas
相关产品推荐
相关产品推荐

