SQL Server:从存储的架构创建表?

时间:2009-03-31 16:48:51

标签: sql sql-server schema

我想创建一个以表名作为参数的存储过程,然后根据存储在某处的模式创建该表(如果它不存在)。

这是可能的 - 我可以存储架构并使用is作为模板来创建表吗?或者我必须在存储过程本身中对CREATE TABLE及其方案进行硬编码吗?

这里的想法是能够在不改变存储过程(关注点分离)的情况下更改模式,因为我可能会扩展该过程以执行更多操作。

据我所知,是否只是在sproc中对表的模式进行硬编码,或者是否可以以某种方式存储和拉出该模式。

CREATE PROCEDURE GenerateTable 
    @tableName as nvarchar(128)
AS
BEGIN
    IF OBJECT_ID(@tableName,'U') IS NULL
        CREATE TABLE @tableName ????????
    ENDIF
END 
GO

4 个答案:

答案 0 :(得分:2)

我会先发出警告 - 以编程方式更改数据库架构通常是一个坏主意。

那就是说,你现在需要的只是创建一个字符串并执行EXEC;例如:

DECLARE @CreateString VARCHAR(200)
SELECT @CreateString = 'CREATE TABLE ' + @tableName + ''
EXEC (@CreateString)

答案 1 :(得分:1)

如果您想要存储架构并按需生成表,我建议您查看Information_Schema.Columns的架构,它会存储足够的信息,您可以为给定的表生成create语句(结构但不是约束)。就个人而言,我认为基于他们将要与之交互的表的模式来编写/重写存储过程的开销较小,类似于this post

中描述的内容。

答案 2 :(得分:1)

是的,你可以这样做。实际上,Microsoft在其系统存储过程中执行此操作。您可以查找它们并查看该代码。此外,我过去做过类似的事情,但要创建存储过程,而不是表。这个想法基本相同,你可以从我的代码中引导。

CREATE procedure [dbo].[ScriptAbm]
@tabla varchar(50)
AS

set nocount on

if object_id(@tabla) is null begin
    select 'no existe la tabla'
    return
end

select identity(int, 1,1) as idcolumna, c.name AS Columna, t.name AS Tipo, 
    case when t.name in ('varchar', 'char') then cast(c.length as varchar)
    else null end as Longitud, ',' as coma
into #t
from syscolumns c
inner join systypes t on c.xtype = t.xtype
where c.id = object_id(@tabla)

declare @max int
select @max = max(idcolumna) from #t

update #t set coma = '' where idcolumna = @max

select  texto from (

    select 0 as orden, 1 idcolumna, 'CREATE PROCEDURE Actualizar' + @tabla texto

    union

    select 1, idcolumna, '@' + columna + ' ' + tipo
        + case when longitud is not null then ' (' + longitud + ')' else '' end 
        + coma
    from #t

    union

    select 2, 1, 'AS'

    union 

    select 3, 1, 
        CHAR(13) + CHAR(10) + 
        '-- =================================================================' + 
        CHAR(13) + CHAR(10) + 
        '-- Fecha: ' + convert(varchar, getdate(), 103) + 
        CHAR(13) + CHAR(10) + 
        '-- Autor: Leonardo Arias Paz ' +
        CHAR(13) + CHAR(10) + 
        '-- Descripción: Alta y modificación de la tabla ' + @tabla +
        CHAR(13) + CHAR(10) + 
        '-- =================================================================' +
        CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10)

    union

    select 3 as orden, 1, 'SET NOCOUNT ON' + CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10)

    union 

    select 3, 2, 'IF @' + (SELECT columna from #t where idcolumna = 1) + ' = 0 BEGIN'

    union

    select 4, 1, char(9) + char(9) + 'INSERT INTO ' + @tabla + ' ('

    union 

    select 5, idcolumna, char(9) + char(9) + char(9) + columna + coma
    from #t

    union 

    select 6, 1, char(9) + char(9) + ')'

    union

    select 7, 1, char(9) + char(9) + 'VALUES ('

    union

    select 8, idcolumna, char(9) + char(9) + char(9) + '@' + columna + coma
    from #t

    union

    select 9, 1, char(9) + char(9) + ')'

    union

    select 9, 2, 'END ELSE BEGIN'

    union

    select 9, 3, char(9) + char(9) + 'UPDATE ' + @tabla + ' SET '

    union

    select 10, idcolumna, char(9) + char(9) + char(9) + columna + char(9) + ' = @' + columna + coma
    from #t
    where idcolumna > 1

    union

    select 11, idcolumna, char(9) + char(9) + 'WHERE ' + columna + ' = ' + '@' + columna
    from #t
    where idcolumna = 1

    union

    select 12, 1, 'END' 

    union

    select 13, 1, CHAR(13) + CHAR(10) + 'SET NOCOUNT OFF' 

    union

    select 13, 2, CHAR(13) + CHAR(10) + 'GO'

) q
order by orden, idcolumna

set nocount off

注意:

当我拥有我需要的所有代码时,我将其打印出来,你应该使用

EXEC sp_executesql @code

其中@code是一个存储生成代码的nvarchar变量。

答案 3 :(得分:0)

是的,这种事情可以做到;我们公司开发了一种工具,这对我们来说非常有价值。不幸的是,我不能与你分享它,但它在你提出的问题中非常有用。