代码之家  ›  专栏  ›  技术社区  ›  Kevin Buchan

如何识别视图中的pk列

  •  1
  • Kevin Buchan  · 技术社区  · 15 年前

    我以前用“getSchemaTable”来读取架构信息,但它缺少一些“东西”,所以我编写了一个大型查询,引用其他列、sys.columns、sys.index_columns和sys.indexes(以及其他表),以返回我从getSchemaTable获得的相同信息,并返回我想要的其他信息。

    问题是,GetSchemaTable将告诉我从视图返回的列是否是基础表中的键列,但我的新查询没有。对于桌子,它会给我一整天正确的答案,而不是视图。

    有人能解决这个问题吗?当我检查一个视图时,我不想为了那一点信息而回到getSchemaTable。(另外,理想情况下,我只需要一个基于SQL的解决方案。)

    谢谢!

    1 回复  |  直到 15 年前
        1
  •  1
  •   Aaron Bertrand    15 年前

    不幸的是,在SQL Server 2005中,这并不容易。我已经讨论过这个问题了,它非常接近,但它依赖于这样一个事实,即您在视图中命名的列与在基表中命名的列完全相同。这是因为现在不推荐使用的SQL-Server-2008视图sys.sql_依赖项没有正确存储引用列_id,因此无法将其与视图中的实际列匹配。我认为SQL Server2008将为您提供更好的选项,因为它们再次引入了一组新的依赖对象。我也没有用信息“schema.key”列“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;