希望这不是一个基本的问题。
我想使用存储过程和构建表在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语句,但我是在一个心理障碍中。任何可能具有洞察力的教程都将非常感激
先谢谢。
答案 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的限制。