使用sys.tables匹配视图列到表列

时间:2015-04-14 08:12:50

标签: sql-server sql-server-2008

我正在使用SQL Server 2008的项目。我们将一些数据加载到大量表中。对于每个表,都会创建几个视图。 第一个视图,我们称之为标准视图,只列出表中的所有列。

第二个视图,我们称之为自定义视图,只列出表中特定的选定列。由于业务需求,需要此视图。所选列是手工挑选的,和RENAMED

现在我想通过自动提取两个视图和表中的所有列如何相互关联来记录这一点。 这就是问题出现的地方。

我使用以下SQL来制作列表:

/* Run this for the DATABASE you want info on.  */

/* The first table lists all Tables and columns. */
with ListOfTableColumns as (
select 
       TheTables.name as 'TableName'
      ,TheColumns.name as 'ColumnName'
      ,TheColumns.column_id as 'ColumnNumber'

from sys.tables as TheTables   /* Find tables */ 
join sys.columns as TheColumns  /* Find columns from tables */
on TheColumns.object_id = TheTables.object_id

),

/* The second table contains all Custom views and columns. */
ListOfCustomViewColumns as (
SELECT
    object_name(d.object_id) as ViewName,
    c.name AS ViewColumn,
    isnull(type_name(c.system_type_id), t.name) AS DateType,
    object_name(d.referenced_major_id) as TableName,
    tablecols.name AS TableColumn
FROM 
    sys.views v
    JOIN sys.columns c ON c.object_id = v.object_id
    LEFT JOIN sys.types t ON c.user_type_id = t.user_type_id
    JOIN sys.sql_dependencies d ON d.object_id = v.object_id 
        AND c.column_id = d.referenced_minor_id
    JOIN sys.columns tablecols ON d.referenced_major_id = tablecols.object_id 
        AND tablecols.column_id = d.referenced_minor_id 
        AND tablecols.column_id = c.column_id
where v.schema_id = (select schema_id from sys.schemas where name = 'LZSDS') /* We only want the Custom views. */
),

/* The third table contains all Standard views and columns. */
ListOfStandardViewColumns as (
SELECT
    object_name(d.object_id) as ViewName,
    c.name AS ViewColumn,
    isnull(type_name(c.system_type_id), t.name) AS DateType,
    object_name(d.referenced_major_id) as TableName,
    tablecols.name AS TableColumn
FROM 
    sys.views v
    JOIN sys.columns c ON c.object_id = v.object_id
    LEFT JOIN sys.types t ON c.user_type_id = t.user_type_id
    JOIN sys.sql_dependencies d ON d.object_id = v.object_id 
        AND c.column_id = d.referenced_minor_id
    JOIN sys.columns tablecols ON d.referenced_major_id = tablecols.object_id 
        AND tablecols.column_id = d.referenced_minor_id 
        AND tablecols.column_id = c.column_id
where v.schema_id = (select schema_id from sys.schemas where name = 'LZSVW') /* We only want the Custom views. */
)

/* Create the actual final list of Tables and Views. */
select
  ListOfTableColumns.TableName as 'Table_name'
 ,ListOfTableColumns.ColumnName as 'Table_column_name'
 ,ListOfTableColumns.ColumnNumber as 'Table_column_number'
 ,ListOfStandardViewColumns.ViewColumn as 'Standard_view_column_name'
 ,ListOfStandardViewColumns.ViewName as 'Standard_view_name'
 ,ListOfCustomViewColumns.ViewColumn as 'Custom_view_column_name'
 ,ListOfCustomViewColumns.ViewName as 'Custom_view_name'
from ListOfTableColumns
left join ListOfStandardViewColumns
on ListOfTableColumns.TableName = ListOfStandardViewColumns.TableName
and ListOfTableColumns.ColumnName = ListOfStandardViewColumns.TableColumn
left join ListOfCustomViewColumns
on ListOfTableColumns.TableName = ListOfCustomViewColumns.TableName
and ListOfTableColumns.ColumnName = ListOfCustomViewColumns.TableColumn
order by ListOfTableColumns.TableName, ListOfTableColumns.ColumnNumber

只要自定义视图包含所有列,上面的代码就可以很好地匹配列。一旦他们中的一些人被选中不参与观点,他们就会在摘录中出现错误。

问题图片可以在这里看到:http://pasteboard.co/2yqRNOj1.png

如何从sys.tables或INFORMATION_SCHEMA中提取可以正确匹配列的提取?

如果您想要一些示例代码来设置问题的表,我在下面提供了它。 (您可能需要更改某些模式名称等以适合您的安装。)

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[LZS].[TBDLZLT000_TESTTABLE1]') AND type in (N'U'))
DROP TABLE [LZS].[TBDLZLT000_TESTTABLE1]
GO

CREATE TABLE [LZS].[TBDLZLT000_TESTTABLE1](
    [DWH_DATE] [datetime] NOT NULL,
    [NUMERIC1] [decimal](3, 0) NOT NULL,
    [NUMERIC2] [decimal](3, 0) NULL,
    [NUMERIC3] [decimal](3, 0) NULL,
    [VARCHAR1] [varchar](3) NOT NULL,
    [VARCHAR2] [varchar](3) NULL,
    [VARCHAR3] [varchar](3) NULL,
    [UPDATE_TIMESTAMP] [datetime] NOT NULL,
 CONSTRAINT [PKDLZLT000] PRIMARY KEY CLUSTERED 
(
    [DWH_DATE] ASC,
    [NUMERIC1] ASC,
    [VARCHAR1] ASC,
    [UPDATE_TIMESTAMP] ASC
) ON [PRIMARY]
) ON [PRIMARY]
GO

-- Create Standard View 
IF  EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[LZSVW].[STANDARD_TEST_TABLE_VIEW]'))
DROP VIEW [LZSVW].[STANDARD_TEST_TABLE_VIEW]
GO

CREATE VIEW [LZSVW].[STANDARD_TEST_TABLE_VIEW] as select 
 * 
from LZS.TBDLZLT000_TESTTABLE1
;
GO


-- Create Custom View
IF  EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[LZSDS].[CUSTOM_TEST_TABLE_VIEW]'))
DROP VIEW [LZSDS].[CUSTOM_TEST_TABLE_VIEW]
GO

CREATE VIEW [LZSDS].[CUSTOM_TEST_TABLE_VIEW] as select 
 DWH_DATE 
,NUMERIC1 AS NUM1
,NUMERIC3 AS NUM3
,VARCHAR1 AS VC1
,VARCHAR3 AS VC3
,UPDATE_TIMESTAMP
from LZS.TBDLZLT000_TESTTABLE1
where DWH_DATE = (SELECT MAX(DWH_DATE) FROM LZS.TBDLZLT000_TESTTABLE1)
GO

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[LZS].[TBDLZLT002_TESTTABLE2]') AND type in (N'U'))
DROP TABLE [LZS].[TBDLZLT002_TESTTABLE2]
GO

CREATE TABLE [LZS].[TBDLZLT002_TESTTABLE2](
    [DWH_DATE] [datetime] NOT NULL,
    [NUMERIC1] [decimal](3, 0) NOT NULL,
    [NUMERIC2] [decimal](3, 0) NULL,
    [NUMERIC3] [decimal](3, 0) NULL,
    [VARCHAR1] [varchar](3) NOT NULL,
    [VARCHAR2] [varchar](3) NULL,
    [VARCHAR3] [varchar](3) NULL,
    [UPDATE_TIMESTAMP] [datetime] NOT NULL,
 CONSTRAINT [PKDLZLT002] PRIMARY KEY CLUSTERED 
(
    [DWH_DATE] ASC,
    [NUMERIC1] ASC,
    [VARCHAR1] ASC,
    [UPDATE_TIMESTAMP] ASC
) ON [PRIMARY]
) ON [PRIMARY]
GO

-- Create Standard View 
IF  EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[LZSVW].[STANDARD_TEST_TABLE2_VIEW]'))
DROP VIEW [LZSVW].[STANDARD_TEST_TABLE2_VIEW]
GO

CREATE VIEW [LZSVW].[STANDARD_TEST_TABLE2_VIEW] as select 
 * 
from LZS.TBDLZLT002_TESTTABLE2
;
GO


-- Create Custom View
IF  EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[LZSDS].[CUSTOM_TEST_TABLE2_VIEW]'))
DROP VIEW [LZSDS].[CUSTOM_TEST_TABLE2_VIEW]
GO

CREATE VIEW [LZSDS].[CUSTOM_TEST_TABLE2_VIEW] as select 
 DWH_DATE
,NUMERIC1 AS NUM1
,NUMERIC2 AS NUM2
,NUMERIC3 AS NUM3
,VARCHAR1 AS VC1
,VARCHAR2 AS VC2
,VARCHAR3 AS VC3
,UPDATE_TIMESTAMP
from LZS.TBDLZLT002_TESTTABLE2
where DWH_DATE = (SELECT MAX(DWH_DATE) FROM LZS.TBDLZLT002_TESTTABLE2)
GO

1 个答案:

答案 0 :(得分:0)

您可以使用INFORMATION_SCHEMA.VIEW_COLUMN_USAGE,如下所示(根据您的示例数据):

;WITH TableColumnsLZS as 
(
    SELECT 
        s.name as 'SchemaName'
        ,t.name as 'TableName'
        ,c.name as 'ColumnName'
        ,c.column_id as 'ColumnNumber'
    FROM sys.tables as t
        INNER JOIN sys.columns as c ON c.object_id = t.object_id
        INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
    WHERE s.name = 'LZS'
)
, StandardViewColumnsLZSVW AS
(
    SELECT * 
    FROM INFORMATION_SCHEMA.VIEW_COLUMN_USAGE AS UsedColumns 
    WHERE UsedColumns.VIEW_SCHEMA = 'LZSVW'
), 
CustomViewColumnsLZSDS AS
(
    SELECT * 
    FROM INFORMATION_SCHEMA.VIEW_COLUMN_USAGE AS UsedColumns 
    WHERE UsedColumns.VIEW_SCHEMA = 'LZSDS'
)
SELECT LZS.TableName Table_name, 
    LZS.ColumnName Table_column_name,
    LZS.ColumnNumber Table_column_number,
    LZSVW.COLUMN_NAME Standard_view_column_name,
    LZSVW.VIEW_NAME Standard_view_name,
    LZSDS.COLUMN_NAME Custom_view_column_name,
    LZSDS.VIEW_NAME Custom_view_name
FROM TableColumnsLZS LZS
    LEFT JOIN StandardViewColumnsLZSVW LZSVW ON LZS.SchemaName = LZSVW.TABLE_SCHEMA AND LZS.TableName = LZSVW.TABLE_NAME AND LZS.ColumnName = LZSVW.COLUMN_NAME
    LEFT JOIN CustomViewColumnsLZSDS LZSDS ON LZS.SchemaName = LZSDS.TABLE_SCHEMA AND LZS.TableName = LZSDS.TABLE_NAME AND LZS.ColumnName = LZSDS.COLUMN_NAME

返回: this

编辑:

INFORMATION_SCHEMA.VIEW_COLUMN_USAGE中的

COLUMN_NAME获取列的真实姓名,而不是别名。当视图中的列数不等于表中的列数时,尝试与INFORMATION_SCHEMA.COLUMNS一起加入也不起作用,因为ordinal_position是从表级保留的。

SELECT *
    FROM INFORMATION_SCHEMA.COLUMNS tc
        INNER JOIN INFORMATION_SCHEMA.VIEW_COLUMN_USAGE vu on vu.table_schema = tc.table_schema
                                                         and vu.table_name = tc.table_name
                                                         and vu.column_name = tc.column_name
        INNER JOIN INFORMATION_SCHEMA.COLUMNS vc on vc.table_schema = vu.view_schema
                                                         and vc.table_name = vu.view_name
                                                         and tc.ordinal_position = vc.ordinal_position
    WHERE vu.VIEW_SCHEMA = 'LZSDS'

但这有效:

 ;WITH TableColumnsLZS as 
    (
        SELECT 
            s.name as 'SchemaName'
            ,t.name as 'TableName'
            ,c.name as 'ColumnName'
            ,c.column_id as 'ColumnNumber'
        FROM sys.tables as t
            INNER JOIN sys.columns as c ON c.object_id = t.object_id
            INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
        WHERE s.name = 'LZS'
    )
    , StandardViewColumnsLZSVW AS
    (
        SELECT * 
        FROM INFORMATION_SCHEMA.VIEW_COLUMN_USAGE AS UsedColumns 
        WHERE UsedColumns.VIEW_SCHEMA = 'LZSVW'
    ), 
    OrdinalPositionCTE
    AS
    (
        SELECT vu.*, 
        ROW_NUMBER() OVER(PARTITION BY vu.table_name ORDER BY ordinal_position) ordinal_position
        FROM INFORMATION_SCHEMA.COLUMNS tc
            INNER JOIN INFORMATION_SCHEMA.VIEW_COLUMN_USAGE vu on vu.table_schema = tc.table_schema
                                                             and vu.table_name = tc.table_name
                                                             and vu.column_name = tc.column_name
        WHERE vu.VIEW_SCHEMA = 'LZSDS'
    ),
    CustomViewColumnsLZSDS
    AS
    (
        SELECT op.*, vc.COLUMN_NAME Alias
        FROM OrdinalPositionCTE op
        INNER JOIN INFORMATION_SCHEMA.COLUMNS vc on vc.table_schema = op.view_schema
                                                             and vc.table_name = op.view_name
                                                             and op.ordinal_position = vc.ordinal_position
    )
SELECT LZS.TableName Table_name, 
    LZS.ColumnName Table_column_name,
    LZS.ColumnNumber Table_column_number,
    LZSVW.COLUMN_NAME Standard_view_column_name,
    LZSVW.VIEW_NAME Standard_view_name,
    LZSDS.Alias Custom_view_column_name,
    LZSDS.VIEW_NAME Custom_view_name
FROM TableColumnsLZS LZS
    LEFT JOIN StandardViewColumnsLZSVW LZSVW ON LZS.SchemaName = LZSVW.TABLE_SCHEMA AND LZS.TableName = LZSVW.TABLE_NAME AND LZS.ColumnName = LZSVW.COLUMN_NAME
    LEFT JOIN CustomViewColumnsLZSDS LZSDS ON LZS.SchemaName = LZSDS.TABLE_SCHEMA AND LZS.TableName = LZSDS.TABLE_NAME AND LZS.ColumnName = LZSDS.COLUMN_NAME