SQL Server: создание таблицы из хранимой схемы? - PullRequest
0 голосов
/ 31 марта 2009

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

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

2 голосов
/ 31 марта 2009

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

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

DECLARE @CreateString VARCHAR(200)
SELECT @CreateString = 'CREATE TABLE ' + @tableName + ''
EXEC (@CreateString)
1 голос
/ 01 апреля 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, в которой хранится ваш сгенерированный код.

1 голос
/ 31 марта 2009

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

0 голосов
/ 31 марта 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...