在SQL Server视图中查找计算列

时间:2018-05-18 14:24:22

标签: sql-server

一位同事让我帮助他们识别具有一个或多个计算列的数据库中的视图。该数据库有数百个视图,因此他们试图找到一种自动完成此任务的方法。我没有在数据库中看到我期待的结果。这是一个例子:

--DROP TABLE dbo.Products

CREATE TABLE dbo.Products   
(  
    ProductID int IDENTITY (1,1) NOT NULL  
  , QtyAvailable smallint  
  , UnitPrice money   
);  

--DROP VIEW dbo.uvw_Products
CREATE VIEW dbo.uvw_Products
AS
    SELECT    ProductID
            , QtyAvailable
            , UnitPrice
            , (QtyAvailable * UnitPrice) AS InventoryValue
    FROM      dbo.Products;

-- Look at the view and find the computed column
SELECT OBJECT_SCHEMA_NAME(T.[object_id],DB_ID()) AS [Schema],   
        T.[name] AS [table_name], AC.[name] AS [column_name],   
        TY.[name] AS system_data_type, AC.[max_length],  
        AC.[precision], AC.[scale], AC.[is_nullable], AC.[is_ansi_padded], AC.[is_computed]
FROM sys.[views] AS T   
  INNER JOIN sys.[all_columns] AC ON T.[object_id] = AC.[object_id]  
 INNER JOIN sys.[types] TY ON AC.[system_type_id] = TY.[system_type_id] AND AC.[user_type_id] = TY.[user_type_id]  
WHERE T.[is_ms_shipped] = 0
AND T.[name] = 'uvw_Products'
ORDER BY T.[name], AC.[column_id]


-- Pulls up no results - no entries in sys.computed_columns
SELECT TOP 10 * 
FROM sys.computed_columns C
INNER JOIN sys.views V ON C.[object_id] = V.[object_id]
WHERE V.[name] = 'uvw_Products'

从这个简单的例子可以看出,SQL Server似乎没有将值存储在is_computed列中。

我错过了什么?我们如何在视图中找到计算列?

1 个答案:

答案 0 :(得分:0)

我知道它并不理想,我不认为这个问题存在一个万无一失的解决方案,但根据您的命名约定,您可以连接到列名称的表sys视图,看看哪些列存在并且不存在。

例如:

SELECT v.*
FROM 
(
    SELECT  [Schema]        = OBJECT_SCHEMA_NAME(t.[object_id], DB_ID())
          , [table_name]    = t.[name] 
          , [column_name]   = vc.[name]
    FROM sys.[views] t  
    JOIN sys.[all_columns] vc ON t.[object_id] = vc.[object_id]
) v
LEFT JOIN 
(
    SELECT  [Schema]        = OBJECT_SCHEMA_NAME(t.[object_id], DB_ID())
          , [table_name]    = t.[name] 
          , [column_name]   = vc.[name]
    FROM sys.[tables] t  
    JOIN sys.[all_columns] vc ON t.[object_id] = vc.[object_id]
) t
    ON t.[column_name] = v.[column_name]
WHERE t.[table_name] IS NULL

返回:

Schema | table_name    | column_name
----------------------------------------
dbo    | uvw_Products  | InventoryValue

如果你的观点在其名称中包含了源表,例如< uvw_Products'你也可以在你的联接中使用它来避免其他表中的列妨碍你。

再次它不理想,但缩小搜索范围的相对简单的解决方案