【问题标题】:SQL Server: Creating table from stored schema?SQL Server:从存储模式创建表?
【发布时间】:2010-10-16 15:54:25
【问题描述】:

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

这可能吗——我可以存储一个模式并使用它作为模板来创建表吗?还是我必须在存储过程本身中对 CREATE TABLE 及其方案进行硬编码?

这里的想法是能够在不更改存储过程(关注点分离)的情况下更改架构,因为我可能会扩展该过程以做更多事情。

据我所知,我不知道是否只是硬编码存储过程中表的架构,或者我是否可以以某种方式存储和提取该架构。

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

【问题讨论】:

  • 为什么需要按需建表?必须有更好的解决方案来解决您的问题
  • 每张桌子都是一个聊天室。我知道你在想什么:我只是自找麻烦。也许吧,但我相信我有一个防弹例程,可以检查以确保@tableName 是一个适当的标识符(1 - 128 个 unicode 字符,不以'@'或'# '等)。

标签: sql sql-server schema


【解决方案1】:

是的,您可以这样做。事实上,微软在其系统存储过程中做到了这一点。您可以查找它们并查看该代码。另外,我过去做过类似的事情,但要创建一个存储过程,而不是一个表。思路基本一样,可以参考我的代码。

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 变量,用于存储您生成的代码。

【讨论】:

    【解决方案2】:

    是的,这种事情是可以做到的;我们公司开发了一种工具来做到这一点,这对我们来说非常有价值。不幸的是,我无法与您分享它,但它非常符合您在问题中描述的方式。

    【讨论】:

      【解决方案3】:

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

      也就是说,您现在只需要创建一个字符串并执行它;例如:

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • 换句话说,我正在尝试做的并不是真正的常见做法,嗯?我正在考虑一个更像代码中的变量的模式。听起来方法不对。
        • 我会说基于模式生成 procs 比基于 procs 生成模式要普遍得多。也许一般看一下 ORM,而 NHibernate 是一个特定的工具。
        猜你喜欢
        • 1970-01-01
        • 2012-02-28
        • 2022-11-11
        • 2016-09-24
        • 2013-05-02
        • 2012-05-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多