A colleague asked me to help them to identify the views in a database that have one or more computed columns. The database has hundreds of views so they're trying to find an automated way to accomplish this task. I am not seeing the results in the database that I was expecting. Here is an example:
--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'
As you can see from this simple example, SQL Server does not seem to be storing the value in the is_computed column.
What am I missing? How can we find the computed columns in views?
I know it's not ideal, I don't think a fool-proof solution exists for this problem, but depending on your naming conventions you could do a join to the tables sys view on column names so see which columns exist and don't exist in there.
for example:
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
Returns:
Schema | table_name | column_name
----------------------------------------
dbo | uvw_Products | InventoryValue
And if your views contain the source table in its name like 'uvw_Products' you could also use that in your join to avoid columns in other tables getting in the way.
Again its not ideal but a relatively simple solution to narrow the search
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With