如何识别视图中的PK列

时间:2009-11-12 21:51:48

标签: sql-server-2005

我曾经使用'GetSchemaTable'来读取架构信息,但它缺少一些'东西',所以我写了一个大的查询,引用了其他列,sys.columns,sys.index_columns和sys.indexes(和其他表格)返回我以前从GetSchemaTable获取的相同信息,并返回我想要的其他信息。

问题是GetSchemaTable会告诉我从视图返回的列是否是基础表中的Key列,但我的新查询不是。它会整天给我正确的答案表,但不是为了观点。

有没有人有解决方案?当我正在检查一个视图时,我不想仅仅为了那一点信息而回到GetSchemaTable。 (另外,我真的只想要一个基于SQL的解决方案。)

谢谢!

1 个答案:

答案 0 :(得分:1)

不幸的是,在SQL Server 2005中,这并不容易。我已经玩过这个了,它非常接近,但它依赖于你在视图中命名列与在基表中命名的列完全相同的事实。这是因为现在不推荐使用的SQL-Server-2008视图sys.sql_dependencies没有正确存储引用column_id,因此无法将其与视图中的实际列进行匹配。我认为SQL Server 2008将为您提供更好的选择,因为它们再次引入了一组新的依赖项对象。我也没有使用INFORMATION_SCHEMA.KEY_COLUMN_USAGE追踪任何路径,但由于这些视图仅依赖于名称而不是任何类型的ID,因此您可能在同一个pickle中。所以也许这可能是你的开始,但就像我说的那样,这只会涵盖简单的案例。如果您对列进行别名,那么您将失去运气。也许其他人对于如何引用这些东西的复杂性有一些了解会拉出一只兔子并弄清楚如何引用不匹配的列......

-- very simple; one-column key:

CREATE TABLE dbo.boo
(
    far INT PRIMARY KEY
);
GO

CREATE VIEW dbo.view_boo
AS
    SELECT far FROM dbo.boo;
GO

-- slightly more complex.  Two-column key,
-- not all columns are in key, view columns
-- are in different order:

CREATE TABLE dbo.foo
(
    splunge INT,
    a INT,
    mort INT,
    PRIMARY KEY(splunge, mort)
);
GO

CREATE VIEW dbo.view_foo
AS
    SELECT
        splunge,
        mort,
        a
    FROM
        dbo.foo;
GO

SELECT 
    QUOTENAME(OBJECT_SCHEMA_NAME(v.[object_id])) + '.' 
    + QUOTENAME(v.name) + '.' + QUOTENAME(vc.name) 
    + ' references ' 
    + QUOTENAME(OBJECT_SCHEMA_NAME(t.[object_id]))
    + '.' + QUOTENAME(t.name) + '.' + QUOTENAME(tc.name)
FROM 
    sys.views AS v
INNER JOIN
    sys.sql_dependencies AS d
    ON v.[object_id] = d.[object_id]
INNER JOIN
    sys.tables AS t
    ON d.referenced_major_id = t.[object_id]
INNER JOIN
    sys.columns AS tc
    ON tc.[object_id] = t.[object_id]
INNER JOIN
    sys.index_columns AS ic
    ON tc.[object_id] = ic.[object_id]
    AND tc.column_id = ic.column_id
    AND tc.column_id = d.referenced_minor_id
INNER JOIN
    sys.columns AS vc
    ON vc.[object_id] = v.[object_id]
    AND vc.name = tc.name -- the part I don't like
INNER JOIN
    sys.indexes AS i
    ON ic.[object_id] = i.[object_id]
    AND i.is_primary_key = 1
ORDER BY
    t.name,
    ic.key_ordinal;

GO

DROP VIEW dbo.view_boo, dbo.view_foo;
DROP TABLE dbo.foo, dbo.boo;