SQL Server: создание таблицы из сохраненной схемы?

Я хотел бы создать хранимую процедуру, которая принимает имя таблицы в качестве параметра, а затем создает эту таблицу, если она не существует, в соответствии со схемой, хранящейся где-то.

Возможно ли это - могу ли я сохранить схему и использовать ее в качестве шаблона для создания таблиц? Или я должен жестко запрограммировать 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

person core    schedule 31.03.2009    source источник
comment
зачем вам создавать таблицы по требованию? должно быть лучшее решение вашей проблемы   -  person KM.    schedule 31.03.2009
comment
Каждый стол — это чат. Я знаю, о чем вы думаете: я просто напрашиваюсь на неприятности. Возможно, но я полагаю, что у меня есть пуленепробиваемая процедура, которая проверяет, является ли @tableName подходящим идентификатором (от 1 до 128 символов Юникода, не начинается с '@' или '# ', так далее.).   -  person core    schedule 01.04.2009


Ответы (4)


Я начну с предупреждения: изменение схемы вашей базы данных программным путем, как правило, будет плохой идеей.

Тем не менее, все, что вам нужно сейчас, это создать строку и выполнить ее EXEC; например:

DECLARE @CreateString VARCHAR(200)
SELECT @CreateString = 'CREATE TABLE ' + @tableName + ''
EXEC (@CreateString)
person Chris Shaffer    schedule 31.03.2009

Если вы хотите хранить схему и создавать таблицы по запросу, я бы рекомендовал вам просмотреть схему для Information_Schema.Columns хранит достаточно информации, чтобы вы могли сгенерировать оператор создания для данной таблицы (структура, но не ограничения). Лично я думаю, что меньше накладных расходов для сценария/перескрипта хранимых процедур на основе схемы таблицы, с которой они будут взаимодействовать, аналогично тому, что описано в этот пост

person cmsjr    schedule 31.03.2009
comment
Другими словами, то, что я пытаюсь сделать, не является общепринятой практикой, а? Я думаю о схеме, больше похожей на переменную в коде. Звучит как неправильный подход. - person core; 31.03.2009
comment
Я бы сказал, что намного чаще генерируются процессы на основе схемы, чем генерируются схемы на основе процессов. Может быть, посмотрите на ORM в целом и на NHibernate как на конкретный инструмент. - person cmsjr; 31.03.2009

Да, ты можешь это сделать. На самом деле 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, в которой хранится сгенерированный вами код.

person eKek0    schedule 01.04.2009

Да, такое можно сделать; наша компания разработала для этого инструмент, который оказался для нас феноменально ценным. К сожалению, я не могу поделиться им с вами, но он очень хорошо работает в соответствии с тем, что вы описываете в своем вопросе.

person mwigdahl    schedule 31.03.2009