如何将view的sys.columns连接到它在T-SQL中引用的表的sys.columns?

时间:2012-10-30 07:44:40

标签: sql-server tsql

我正在尝试将 sys.columns 中的记录连接到视图, sys.columns 中的记录,因为我需要这些值在视图中选择的列的 is_nullable is_computed default_object_id 列。

视图的 sys.columns 记录具有“不正确”值,您可以通过运行以下示例查询来观察这些值:

CREATE TABLE TestTable (
    FieldA int NOT NULL,
    FieldB int DEFAULT (1),
    FieldC as CONVERT(INT, FieldA + FieldB),
    FieldD int NOT NULL
)
GO

CREATE VIEW TestView WITH SCHEMABINDING AS
SELECT  FieldA, FieldC as TestC, FieldB + FieldC as TestD
FROM dbo.TestTable WHERE FieldD = 1
GO

SELECT  OBJECT_NAME(c.object_id) as ViewName, c.name as ColumnName,
        c.is_nullable as Nullable, c.is_computed as Computed,
   cast(CASE WHEN c.default_object_id > 0 THEN 1 ELSE 0 END as bit) as HasDefault
FROM sys.columns c
WHERE object_id = OBJECT_ID('TestTable')
GO

SELECT  OBJECT_NAME(c.object_id) as ViewName, c.name as ColumnName,
        c.is_nullable as Nullable, c.is_computed as Computed,
   cast(CASE WHEN c.default_object_id > 0 THEN 1 ELSE 0 END as bit) as HasDefault
FROM sys.columns c
WHERE object_id = OBJECT_ID('TestView')
GO

我已尝试使用系统视图加入依赖项,但它们没有向我们提供有关视图中哪一列引用表中哪一列的信息:

-- dm_sql_referenced_entities gives us all columns referenced, but all records
-- have referencing_minor_id 0, so we do not know which column refers to what
SELECT * FROM sys.dm_sql_referenced_entities('dbo.TestView', 'OBJECT')
GO

-- sql_dependencies gives us all columns referenced, but all records has
-- column_id 0 so we can not use this either of joining the columns
SELECT * FROM sys.sql_dependencies WHERE object_id = OBJECT_ID('TestView')
GO

-- sql_expression_dependencies just tells us what table we are referencing 
-- if view is not created WITH SCHEMABINDING. If it is, it will return columns,
-- but with referencing_minor_id 0 for all records, so not able use this either
SELECT * FROM sys.sql_expression_dependencies
    WHERE referencing_id = OBJECT_ID('TestView')
GO

有人提交的关于social.msdn的未答复帖子似乎是同一个问题: http://social.msdn.microsoft.com/Forums/en-US/transactsql/thread/4ae5869f-bf64-4eef-a952-9ac40c932cd4

3 个答案:

答案 0 :(得分:1)

你说“我需要知道TestView TestC是指计算列”。 SQL Server 2008 R2不支持此功能(虽然2012年不确定,但我对此表示怀疑)。

首先,您可以查询sys.columns或INFORMATION_SCHEMA.COLUMNS,但是找不到您想要的内容。

如果你深入挖掘,你很可能会尝试sys.sql_expression_dependencies和sys.dm_sql_referenced_entities(N'dbo.TestView',N'OBJECT'),但你可以在那里找到表列映射,而不是列列。 SQL Server通过“高级”对象(表,触发器......)存储依赖性信息,而不是通过其详细信息(列)。您将在sys.sysdepends中找到相同的内容。事实上,依赖信息在SQL服务器中是不可靠的。

最后,你唯一的可能就是自己解析视图体。它可以在sys.sql_modules中找到:

SELECT m.definition
FROM 
    sys.objects o
    JOIN sys.sql_modules m 
        ON m.object_id = o.object_id
WHERE 
    o.object_id = object_id('dbo.TestView')
    and o.type = 'V'

解析T-SQL 非常很难,它可以真正推动你的努力极限。例如,从视图中获取表引用或从表列中获取表引用应该或多或少,特别是如果视图是模式绑定的。但如果它不是,那么......只要想一下引用OUTER APPLY的星号,它引用递归CTE ...

无论如何,祝你好运!

答案 1 :(得分:1)

目前,在创建视图时,有两个操作在高级别发生 - 解析&捆绑。解析基本上是检查语句的语法,关键字&这样。绑定是将语句中的标识符(对象名称,列名称)映射到相应对象(表,视图,函数,列等)的过程。类型的推导。此外,如果视图类似于SELECT语句,您可以选择在SELECT列表中或视图名称后面别名列引用和表达式(例如:创建视图v1(a)作为从t中选择i)。

绑定后,我们只保留列别名&元数据中的派生类型,因为视图在逻辑上是从查询表达式派生的表。因此,目前无法确定列别名映射到的表达式或其包含的内容(列或函数或文字等)  获取所需信息的唯一方法是解析视图定义&执行自己的绑定。我相信我们已经有一个跟踪功能请求的错误,以便在视图定义中公开有关别名到列表达式映射的更丰富的依赖关系信息。

最后,SQL Server Developer Studio或Visual Studio Database Project使用托管T-SQL解析器来跟踪此类引用,以便您可以使用项目进行重构或重命名。   希望这有助于澄清问题/当前实施。

答案 2 :(得分:-1)

似乎误解是假设object_id是sys.columns中的主键。它不是。 sys.columns中的object_id与sys.objects中的object_id相关。 所以:

SELECT C.*
FROM sys.objects T
INNER JOIN sys.columns C
ON T.object_id = C.object_id
WHERE T.type in ('S','U') -- System Tables and User Tables
AND T.name = 'Address' -- Table Name
order by C.Column_ID

将返回AdventureWorks中“地址”表中的列。