【问题标题】:Create views with a column dropped for all tables in the database为数据库中的所有表创建删除列的视图
【发布时间】:2020-02-28 20:18:06
【问题描述】:

我的数据库有大量的表,我们称它们为 Table1、Table2、Table3 等,我需要为合并复制设置它们,这意味着 SQL Server 将在每个表中创建一个新的列 (rowguid)。

这对我的前端来说是个问题(我无法更改),所以我现在的想法是创建一个删除 rowguid 列的每个表的视图,并将它们放在自己的架构下。

由于有大量的表和每个表中的大量列,这不容易手动完成,所以现在我正在尝试为此编写一些 SQL 代码。 我必须说没有成功。

我需要的是一个递归代码,它为每个表创建一个新视图(命名为与表相同的名称,但在一个新架构下)但省略了每个表中的 rowguid 列。

我发现了如何删除 rowguid 列而无需明确知道列名(它们因表而异)。

SELECT * INTO #TemporaryTable FROM [dbo].[Table1]
ALTER TABLE #TemporaryTable DROP COLUMN rowguid
SELECT * FROM #TemporaryTable

DROP TABLE #TemporaryTable

但是如何将它与 CREATE VIEW 结合起来(据我所知只能有一个 SELECT),然后让它遍历我数据库中的所有表,这远远超出了我的能力范围。

【问题讨论】:

    标签: sql-server view


    【解决方案1】:

    一种方法是使用动态 SQL。但是,CREATE VIEW 必须是批处理中的唯一语句,这意味着如果您想为每个表创建一个,那么您要么需要使用动态动态 SQL(是的,我说过),要么使用 CURSOR .对于大量表来说,先验的性能会更高,但后者更容易阅读(和写入)。如果这是一个一次性的过程,那么我不太关心性能,所以我会走CURSOR 路线。

    CREATE SCHEMA vw; --Create a schema for the views
    GO
    
    DECLARE Tables CURSOR FORWARD_ONLY
    FOR
    SELECT s.[name] AS SchemaName,
           t.[name] AS TableName
    FROM sys.schemas s
         JOIN sys.tables t ON s.schema_id = t.schema_id
    WHERE EXISTS (SELECT 1
                  FROM sys.columns c
                  WHERE c.object_id = t.object_id
                    AND c.[name] = N'rowguid'); --Incase you have tables without this, as I assume you don't need views of those
    
    DECLARE @SchemaName sysname,
            @TableName sysname,
            @SQL nvarchar(MAX),
            @CRLF nchar(2) = NCHAR(13) + NCHAR(10);
    
    OPEN Tables;
    
    FETCH NEXT FROM Tables
    INTO @SchemaName, @TableName;
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
    
        PRINT N'Creating View for object ' + QUOTENAME(@SchemaName) + N'.' + QUOTENAME(@TableName) + N'.';
    
        --Create the dynamic statement
        SET @SQL = N'CREATE VIEW vw.' + QUOTENAME(@TableName) + N' AS' + @CRLF + @CRLF +
                   N'    SELECT ' + STUFF((SELECT N',' + @CRLF +
                                                  N'           ' + QUOTENAME(C.[name])
                                           FROM sys.columns c
                                                JOIN sys.tables t ON c.object_id = t.object_id
                                                JOIN sys.schemas s ON t.schema_id = s.schema_id
                                           WHERE t.[name] = @TableName
                                             AND s.name = @SchemaName
                                             AND c.[name] != N'rowguid'
                                           ORDER BY c.column_id ASC
                                           FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,14,N'') + @CRLF +
                  N'    FROM ' + QUOTENAME(@SchemaName) + N'.' + QUOTENAME(@TableName) + N';'
    
        PRINT @SQL; --Incase you need to the code run for debugging
    
        --Create the View
        EXEC sp_executesql @SQL;
    
        --Get next object
        FETCH NEXT FROM Tables
        INTO @SchemaName, @TableName;
    
    END;
    
    CLOSE Tables;
    DEALLOCATE Tables;
    

    注意,如果您有 2 个不同模式的同名表,这将失败。

    【讨论】:

    • 唯一的是它还包括所有系统表,我不明白如何省略它。 :)
    • 这很简单,@Quist,只需在 WHERE 中添加 AND t.[type] = 'U' 即可获得 CURSOR 声明。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多