基于SchemaColumn&创建表。 SchemaTable组合表

时间:2016-07-26 14:00:54

标签: sql-server tsql stored-procedures

希望这不是一个基本的问题。

我想使用存储过程和构建表在db中创建一组新表。

构建表包括以下列和一些示例行:

tblNm   colNm       colTyp  colLen  colReq  colWarning  colUni  colComUni
account personID    Decimal NULL    0       0           0       0
account studentNum  String  15      0       0           0       0

我正在考虑使用Multiple Cursors作为嵌套循环的一种形式,但我无法弄清楚如何在嵌套过程中定义列参数,因为游标只返回一个值。

我知道我需要构建一个解析这些值的alter语句,但我是在一个心理障碍中。任何可能具有洞察力的教程都将非常感激

先谢谢。

1 个答案:

答案 0 :(得分:3)

您可以使用两个游标或一个游标来解决问题。两个游标将使代码更具可读性。一个光标效率更高。

两个游标

下面的代码演示了如何使用两个游标迭代表和列。

DECLARE @tblNm VARCHAR(MAX)
DECLARE cTables CURSOR FOR
    SELECT tblNm
    FROM CompositeSchema
    GROUP BY tblNm
    ORDER BY tblNm
OPEN cTables
FETCH cTables INTO @tblNm
WHILE @@FETCH_STATUS=0
    BEGIN
        PRINT 'Processing table '+@tblNm

        -- Start of code to execute for each table

        DECLARE @sqlCreateTable VARCHAR(MAX)
        SET @sqlCreateTable = 'CREATE TABLE ['+@tblNm+'] ('

        DECLARE @colNm VARCHAR(MAX),@colTyp VARCHAR(MAX),@colLen INT,@colReq BIT,@colWarning BIT,@colUni BIT,@colComUni BIT
        DECLARE @isFirst BIT
        SET @isFirst = 1
        DECLARE cCols CURSOR FOR
            SELECT colNm,colTyp,colLen,colReq,colWarning,colUni,colComUni
            FROM CompositeSchema
            WHERE tblNm=@tblNm
            ORDER BY colComUni DESC,colNm ASC
        OPEN cCols
        FETCH cCols INTO @colNm,@colTyp,@colLen,@colReq,@colWarning,@colUni,@colComUni
        WHILE @@FETCH_STATUS=0
            BEGIN
                PRINT 'Processing column ['+@tblNm+'].['+@colNm+']'

                -- Start of code to process each column (simplified!)

                IF @isFirst=0
                    SET @sqlCreateTable = @sqlCreateTable+','
                SET @isFirst = 0

                SET @sqlCreateTable = @sqlCreateTable+'['+@colNm+'] '+@colTyp
                IF NOT @colLen IS NULL
                    SET @sqlCreateTable = @sqlCreateTable+'('+CAST(@colLen AS VARCHAR)+')'

                -- End of code to process each column

                FETCH cCols INTO @colNm,@colTyp,@colLen,@colReq,@colWarning,@colUni,@colComUni
            END
        CLOSE cCols
        DEALLOCATE cCols

        SET @sqlCreateTable = @sqlCreateTable+')'
        PRINT @sqlCreateTable

        -- EXEC(@sqlCreateTable)

        -- End of code to execute for each table

        FETCH cTables INTO @tblNm
    END
CLOSE cTables
DEALLOCATE cTables

一个光标

在这种情况下,我们只使用一个游标。我们跟踪@currentTblNm变量中正在处理的当前表的内容。每当变量发生变化时,我们都会立即创建所有列。

DECLARE @currentTblNm VARCHAR(MAX),@sqlCreateTable VARCHAR(MAX)
SET @currentTblNm = ''

DECLARE @tblNm VARCHAR(MAX),@colNm VARCHAR(MAX),@colTyp VARCHAR(MAX),@colLen INT,@colReq BIT,@colWarning BIT,@colUni BIT,@colComUni BIT
DECLARE @isFirst BIT
SET @isFirst = 1
DECLARE cCols CURSOR FOR
    SELECT tblNm,colNm,colTyp,colLen,colReq,colWarning,colUni,colComUni
    FROM CompositeSchema
    ORDER BY tblNm ASC,colComUni DESC,colNm ASC
OPEN cCols
FETCH cCols INTO @tblNm,@colNm,@colTyp,@colLen,@colReq,@colWarning,@colUni,@colComUni
WHILE @@FETCH_STATUS=0
    BEGIN
        IF @currentTblNm<>@tblNm
            BEGIN
                IF @sqlCreateTable<>''
                    BEGIN
                        SET @sqlCreateTable = @sqlCreateTable+')'
                        PRINT @sqlCreateTable
                        --EXEC (@sqlCreateTable)
                    END

                SET @isFirst = 1
                SET @sqlCreateTable = 'CREATE TABLE ['+@tblNm+'] ('
                SET @currentTblNm = @tblNm

                PRINT 'Processing table ['+@tblNm+']'
            END

        -- Start of code to process each column (simplified!)

        IF @isFirst=0
            SET @sqlCreateTable = @sqlCreateTable+','
        SET @isFirst = 0

        SET @sqlCreateTable = @sqlCreateTable+'['+@colNm+'] '+@colTyp
        IF NOT @colLen IS NULL
            SET @sqlCreateTable = @sqlCreateTable+'('+CAST(@colLen AS VARCHAR)+')'

        -- End of code to process each column

        FETCH cCols INTO @tblNm,@colNm,@colTyp,@colLen,@colReq,@colWarning,@colUni,@colComUni
    END
CLOSE cCols
DEALLOCATE cCols

IF @sqlCreateTable<>''
    BEGIN
        SET @sqlCreateTable = @sqlCreateTable+')'
        PRINT @sqlCreateTable

        -- EXEC(@sqlCreateTable)
    END

简化了两段代码,两个游标和一个游标。正确创建所有约束的逻辑(如主键,唯一约束,外键等),正确映射列数据类型的逻辑,而不是忘记,在创建新表和修改新表之间进行区分现有表超出了本文的范围。

值得一提的是,您还可以使用FOR XML的声明性SQL代码来创建表结构。这是可能的,并且能够生成具有更好性能的CREATE TABLE语句。根据经验,我知道这段代码将难以维护,您可能会遇到声明性SQL的限制。