2009-09-05 3 views
39

Я создал несколько определенных пользователем типов в БД, как показано нижеAlter пользователя типа в Sql Server

CREATE TYPE [dbo].[StringID] FROM [nvarchar](20) NOT NULL 

и назначены различные таблицы. Мои таблицы в БД в различных схемах (не только ПСЭ)

Но я понял, что мне нужно больше поле, и мне нужно изменить, например, увеличение по сравнению с NVARCHAR к NVARCHAR, но нет тип отчета Alter

I нужен сценарий, который temp table/cursor вообще и сохранит там все таблицы и поля, где используется мой тип. Затем измените существующие поля на базовый тип - например. от CustID [StringID] до CustID [nvarchar (20)]. Оставьте тип пользователя и заново создайте его новым типом. NVARCHAR (50) и, наконец, установить обратно поля к типу пользователя

У меня нет правила определяют по типам, так что не надо падать правила и повторно добавить их

Я не очень хорошо знаком с T-Sql, поэтому любая помощь приветствуется.

ответ

26

Это то, что я обычно использую, хотя и немного руководства:

/* Add a 'temporary' UDDT with the new definition */ 
exec sp_addtype t_myudt_tmp, 'numeric(18,5)', NULL 


/* Build a command to alter all the existing columns - cut and 
** paste the output, then run it */ 
select 'alter table dbo.' + TABLE_NAME + 
     ' alter column ' + COLUMN_NAME + ' t_myudt_tmp' 
from INFORMATION_SCHEMA.COLUMNS 
where DOMAIN_NAME = 't_myudt' 

/* Remove the old UDDT */ 
exec sp_droptype t_mydut 


/* Rename the 'temporary' UDDT to the correct name */ 
exec sp_rename 't_myudt_tmp', 't_myudt', 'USERDATATYPE' 
+0

Это хорошее начало. Я добавил TABLE_SCHEMA в select, так как мои таблицы не все в схеме dbo, но в разных других схемах. Теперь мне нужно понять, как выбрать в таблицу курсора или temp, а затем выполнить оператор, созданный строкой. Спасибо за помощь – bzamfir

+2

Это, вероятно, единственный жизнеспособный способ, так как, к сожалению, у SQL Server нет команды «ALTER TYPE» (почему бы и нет?) –

+9

Вы можете проголосовать за команду «ALTER TYPE» на https: // connect .microsoft.com/SQLServer/feedback/details/319134/msft-mso-support-alter-type –

5

there's a good example of a more comprehensive script here

Стоит отметить, что этот сценарий будет включать в себя взгляды, если у вас есть. Я запускал его, а вместо exec'ing inline генерировал скрипт в качестве вывода, который я затем настраивал и запускал.

Кроме того, если у вас есть функции/sprocs с использованием пользовательских типов, вам необходимо отбросить их перед запуском скрипта.

Уроки: в будущем, не беспокойтесь о UDT, они более сложны, чем они того стоят.

SET NOCOUNT ON 

DECLARE @udt VARCHAR(150) 
DECLARE @udtschema VARCHAR(150) 
DECLARE @newudtschema VARCHAR(150) 
DECLARE @newudtDataType VARCHAR(150) 
DECLARE @newudtDataSize smallint 
DECLARE @OtherParameter VARCHAR(50) 

SET @udt = 'Name' -- Existing UDDT 
SET @udtschema = 'dbo' -- Schema of the UDDT 
SET @newudtDataType = 'varchar' -- Data type for te new UDDT 
SET @newudtDataSize = 500 -- Lenght of the new UDDT 
SET @newudtschema = 'dbo' -- Schema of the new UDDT 
SET @OtherParameter = ' NULL' -- Other parameters like NULL , NOT NULL 
DECLARE @Datatype VARCHAR(50), 
    @Datasize SMALLINT 

DECLARE @varcharDataType VARCHAR(50) 

DECLARE @Schemaname VARCHAR(50), 
    @TableName VARCHAR(50), 
    @FiledName VARCHAR(50) 

CREATE TABLE #udtflds 
    (
     Schemaname VARCHAR(50), 
     TableName VARCHAR(50), 
     FiledName VARCHAR(50) 
    ) 

SELECT TOP 1 
     @Datatype = Data_type, 
     @Datasize = character_maximum_length 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE Domain_name = @udt 
     AND Domain_schema = @udtschema 

SET @varcharDataType = @Datatype 
IF @DataType Like '%char%' 
    AND @Datasize IS NOT NULL 
    AND (@newudtDataType <> 'varchar(max)' 
      OR @newudtDataType <> 'nvarchar(max)' 
     ) 
    BEGIN 
     SET @varcharDataType = @varcharDataType + '(' 
      + CAST(@Datasize AS VARCHAR(50)) + ')' 
    END 

INSERT INTO #udtflds 
     SELECT TABLE_SCHEMA, 
       TABLE_NAME, 
       Column_Name 
     FROM INFORMATION_SCHEMA.COLUMNS 
     WHERE Domain_name = @udt 
       AND Domain_schema = @udtschema 

DECLARE @exec VARCHAR(500) 

DECLARE alter_cursor CURSOR 
    FOR SELECT Schemaname, 
       TableName, 
       FiledName 
     FROM #udtflds 

OPEN alter_cursor 
FETCH NEXT FROM alter_cursor INTO @Schemaname, @TableName, @FiledName 

WHILE @@FETCH_STATUS = 0 
    BEGIN 
     SET @exec = 'Alter Table ' + @Schemaname + '.' + @TableName 
      + ' ALTER COLUMN ' + @FiledName + ' ' + @varcharDataType 
     EXECUTE (@exec 
       ) 
     FETCH NEXT FROM alter_cursor INTO @Schemaname, @TableName, @FiledName 

    END 

CLOSE alter_cursor 

SET @exec = 'DROP TYPE [' + @udtschema + '].[' + @udt + ']' 
EXEC (@exec 
    ) 

SET @varcharDataType = @newudtDataType 

IF @newudtDataType Like '%char%' 
    AND @newudtDataSize IS NOT NULL 
    AND (@newudtDataType <> 'varchar(max)' 
      OR @newudtDataType <> 'nvarchar(max)' 
     ) 
    BEGIN 
     SET @varcharDataType = @varcharDataType + '(' 
      + CAST(@newudtDataSize AS VARCHAR(50)) + ')' 
    END 

SET @exec = 'CREATE TYPE [' + @newudtschema + '].[' + @udt + '] FROM ' 
    + @varcharDataType + ' ' + @OtherParameter 
EXEC (@exec 
    ) 

OPEN alter_cursor 
FETCH NEXT FROM alter_cursor INTO @Schemaname, @TableName, @FiledName 

WHILE @@FETCH_STATUS = 0 
    BEGIN 
     SET @exec = 'Alter Table ' + @Schemaname + '.' + @TableName 
      + ' ALTER COLUMN ' + @FiledName + ' ' + '[' + @newudtschema 
      + '].[' + @udt + ']' 
     EXECUTE (@exec 
       ) 
     FETCH NEXT FROM alter_cursor INTO @Schemaname, @TableName, @FiledName 
    END 

CLOSE alter_cursor 
DEALLOCATE alter_cursor 
SELECT * 
FROM #udtflds 

DROP TABLE #udtflds 

1: http://www.sql-server-performance.com/2008/how-to-alter-a-uddt/ заменил http://www.sql-server-performance.com/faq/How_to_alter_a%20_UDDT_p1.aspx

+0

Отличный сценарий! Я просто использовал его для изменения базового типа данных моего dbo.percentage UDT, от десятичной (9, 2) до десятичной (9, 4). – bloparod

+0

ссылка сейчас отключена – Rory

+1

Я обновил неработающую ссылку в ответ @ Robin на текущий адрес для этого ответа. –

3

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

Некоторые разработчики также имеют функции SP и функции, использующие параметры UDT, которые также не охватываются. (См комментарии на Robin's link и в Connect entry) запись

Соединим

с 2007 года, наконец, был закрыт после 3-х лет:

Благодарим Вас за отправку этого предложение, но, учитывая его приоритет по отношению ко многим другие предметы в нашей очереди, маловероятно, что мы наденем . Таким образом, мы имеем , закрывая это предложение как «не будет fix».

Я пытался решить похожую проблему ALTERing XML SCHEMA COLLECTIONS, и шаги, как представляется, в основном относятся к АЬТЕЕ TYPE, тоже:

Чтобы отбросить, следующие шаги:

  • Если столбец таблицы ссылается на UDT, он должен быть преобразован в базовый тип
  • Если столбец таблицы имеет ограничение по умолчанию, снимите ограничение по умолчанию
  • Если процедура ure или функция имеет параметры UDT, процедура или функция должна быть удалена
  • Если индекс в столбце UDT, индекс должен быть удален
  • Если индекс является первичным ключом, все внешние ключи должны быть отброшен
  • Если вычисляются столбцы на основе столбца UDT, вычисленные столбцы должны быть отброшены
  • Если есть индексы на этих вычисляемых столбцов, индексы должны быть отброшены
  • Если есть схема, оценка представления, функции или процедуры, основанные на таблицах, содержащих столбцы UDT, эти объекты необходимо отбросить
-3

Простой DROP TYPE сначала CREATE TYPE с исправлениями/изменениями?

Существует простой тест, чтобы узнать, определено ли это, прежде чем вы его отпустите ... как таблица, proc или function - если бы я не был на работе, я бы посмотрел, что это такое?

(я обезжиренное только выше тоже ... если я читаю это неправильно, я извиняюсь заранее;)

+16

Вы не можете отказаться от типа, если он используется. –

4

Как devio говорит, что нет никакого способа, чтобы просто изменить тип, если он используется.

Рабочий стол с помощью SMS, который работал для меня, заключался в создании сценария создания и внесении соответствующих изменений; переименовать существующий UDT; запустите скрипт create; перекомпилируйте связанные sprocs и отпустите переименованную версию.

+0

Как вы переименовываете существующий UDT? – Muflix

5

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

Пример использования:

exec RECREATE_TYPE @schema='dbo', @typ_nme='typ_foo', @sql='AS TABLE([bar] varchar(10) NOT NULL)' 

Код:

CREATE PROCEDURE [dbo].[RECREATE_TYPE] 
    @schema  VARCHAR(100),  -- the schema name for the existing type 
    @typ_nme VARCHAR(128),  -- the type-name (without schema name) 
    @sql  VARCHAR(MAX)  -- the SQL to create a type WITHOUT the "CREATE TYPE schema.typename" part 
AS DECLARE 
    @scid  BIGINT, 
    @typ_id  BIGINT, 
    @temp_nme VARCHAR(1000), 
    @msg  VARCHAR(200) 
BEGIN 
    -- find the existing type by schema and name 
    SELECT @scid = [SCHEMA_ID] FROM sys.schemas WHERE UPPER(name) = UPPER(@schema); 
    IF (@scid IS NULL) BEGIN 
     SET @msg = 'Schema ''' + @schema + ''' not found.'; 
     RAISERROR (@msg, 1, 0); 
    END; 
    SELECT @typ_id = system_type_id FROM sys.types WHERE UPPER(name) = UPPER(@typ_nme); 
    SET @temp_nme = @typ_nme + '_rcrt'; -- temporary name for the existing type 

    -- if the type-to-be-recreated actually exists, then rename it (give it a temporary name) 
    -- if it doesn't exist, then that's OK, too. 
    IF (@typ_id IS NOT NULL) BEGIN 
     exec sp_rename @[email protected]_nme, @newname= @temp_nme, @objtype='USERDATATYPE' 
    END;  

    -- now create the new type 
    SET @sql = 'CREATE TYPE ' + @schema + '.' + @typ_nme + ' ' + @sql; 
    exec sp_sqlexec @sql; 

    -- if we are RE-creating a type (as opposed to just creating a brand-spanking-new type)... 
    IF (@typ_id IS NOT NULL) BEGIN 
     exec recompile_prog; -- then recompile all stored procs (that may have used the type) 
     exec sp_droptype @[email protected]_nme; -- and drop the temporary type which is now no longer referenced 
    END;  
END 

GO 


CREATE PROCEDURE [dbo].[recompile_prog] 
AS 
BEGIN 
    SET NOCOUNT ON; 
    DECLARE @v TABLE (RecID INT IDENTITY(1,1), spname sysname) 
    -- retrieve the list of stored procedures 
    INSERT INTO 
     @v(spname) 
    SELECT 
     '[' + s.[name] + '].[' + items.name + ']'  
    FROM 
     (SELECT sp.name, sp.schema_id, sp.is_ms_shipped FROM sys.procedures sp UNION SELECT so.name, so.SCHEMA_ID, so.is_ms_shipped FROM sys.objects so WHERE so.type_desc LIKE '%FUNCTION%') items 
     INNER JOIN sys.schemas s ON s.schema_id = items.schema_id  
     WHERE is_ms_shipped = 0; 

    -- counter variables 
    DECLARE @cnt INT, @Tot INT; 
    SELECT @cnt = 1; 
    SELECT @Tot = COUNT(*) FROM @v; 
    DECLARE @spname sysname 
    -- start the loop 
    WHILE @Cnt <= @Tot BEGIN  
     SELECT @spname = spname   
     FROM @v   
     WHERE RecID = @Cnt; 
     --PRINT 'refreshing...' + @spname  
     BEGIN TRY  -- refresh the stored procedure   
      EXEC sp_refreshsqlmodule @spname  
     END TRY  
     BEGIN CATCH   
      PRINT 'Validation failed for : ' + @spname + ', Error:' + ERROR_MESSAGE(); 
     END CATCH  
     SET @Cnt = @cnt + 1; 
    END; 

END 
+0

Спасибо, что sprocs спас меня в кучу времени – pateketu

0

Самый простой способ сделать это через объект исследователь Visual Studio, который также поддерживается в издании Сообщества.

Как только у вас есть made a connection на SQL-сервер, перейдите к типу, щелкните правой кнопкой мыши и выберите «Просмотреть код», внесите изменения в схему определенного пользователем типа и нажмите «Обновить». Visual Studio должна показать вам все зависимости для этого объекта и сгенерировать скрипты для обновления типа и перекомпиляции зависимостей.

0

1.Возвратите старый UDT,
2.Выполнить запрос, 3. Поверните старый UDT.

0

Новый ответ на старый вопрос:

Визуальные базы данных проектов Студии обработать отпускание и воссоздать процесс при развертывании изменений. Он отбросит сохраненные procs, которые используют UDDT, а затем воссоздают их после удаления и воссоздания типа данных.

+0

Я не уверен, почему downvote. Если это не законный ответ, пожалуйста, дайте мне знать, почему. – mcfea

Смежные вопросы