SQL Сервер, изменяющий тип данных столбца для нескольких таблиц - PullRequest
0 голосов
/ 21 января 2020

Мы просматриваем нашу базу данных (SQL Server 2014) и проводим некоторую нормализацию. База данных была перенесена из MS Access постепенно в течение многих лет многими разными людьми, и, к сожалению, столбцы не являются стандартными для всех таблиц. Я создал скрипт ниже, пытаясь сделать это автоматически, потому что есть много таблиц. Я продолжаю бить стену за стеной. Последняя стена, которую я пробиваю и с трудом преодолеваю, это: enter image description here Несколько замечаний по поводу этого скрипта:

  1. В нем содержится таблица ColumnModel, которая содержит имя столбца и тип данных, в который мы хотим преобразовать столбец.

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

    DECLARE @Tables TABLE (TableName VARCHAR(200))
    DECLARE @Columns TABLE (ColumnName VARCHAR(200))
    DECLARE @TableName AS VARCHAR(200)
    DECLARE @ColumnName AS VARCHAR(200)
    DECLARE @NewDataType AS VARCHAR(200)
    DECLARE @SQL AS VARCHAR(500)
    DECLARE @Nullable AS BIT
    
    INSERT INTO @Tables
    SELECT DISTINCT o.name AS TableName FROM sys.columns c
    INNER JOIN sys.objects  o on c.object_id=o.object_id
    INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
    INNER JOIN ColumnModel cm ON '['+ c.name+ ']' = cm.[Column]
    ORDER BY o.name
    
    SELECT @TableName= MIN(TableName) FROM @Tables
    WHILE @TableName IS NOT NULL
    BEGIN
    
    INSERT INTO @Columns
    SELECT c.name AS ColumnName FROM sys.columns c
    INNER JOIN sys.objects  o on c.object_id=o.object_id
    INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
    INNER JOIN ColumnModel cm ON '['+ c.name+ ']' = cm.[Column]
    WHERE o.name =  @TableName 
    ORDER BY c.name
    
        -- LOOP THROUGH EACH COLUMN IN TABLE AND MODIFY DATATYPE
    SELECT @ColumnName= MIN(ColumnName) FROM @Columns
    WHILE @ColumnName IS NOT NULL
    BEGIN
        -- DETERMINE IF Column Is Nullable or not
        SET @Nullable = (SELECT c.is_nullable FROM sys.columns c
                        INNER JOIN sys.objects  o on c.object_id=o.object_id
                        INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
                        INNER JOIN ColumnModel cm ON '['+ c.name+ ']' = cm.[Column]
                        WHERE o.name =  @TableName AND c.name =  @ColumnName)
    
        -- GET New Data Type
        SET @NewDataType = (SELECT DataType FROM ColumnModel WHERE [Column] =  '['+ @ColumnName+ ']')
        IF @Nullable = 1
        BEGIN
            SET @SQL = 'ALTER TABLE dbo.[' + @TableName + '] ALTER COLUMN [' + @ColumnName + '] ' + @NewDataType + ' NULL'
            EXEC(@SQL)
            PRINT @SQL
        END
    
        IF @Nullable = 0
        BEGIN
            -- ALTER COLUMN
            SET @SQL = 'ALTER TABLE dbo.[' + @TableName + ']  ALTER COLUMN [' + @ColumnName + '] ' + @NewDataType + ' NOT NULL'
            EXEC(@SQL)
            PRINT @SQL
        END
       DELETE FROM @Columns
        -- MOVE NEXT COLUMN
        SELECT @ColumnName = MIN(ColumnName) FROM @Columns  WHERE  ColumnName > @ColumnName
    END
    
    -- MOVE NEXT TABLE
    SELECT @TableName = MIN(TableName) FROM @Tables  WHERE  TableName > @TableName
    

    END

УДАЛИТЬ ВСЕ индексы БД Скрипт:

SELECT 'ALTER INDEX ' + QUOTENAME(I.name) + ' ON ' +  QUOTENAME(SCHEMA_NAME(T.schema_id))+'.'+ QUOTENAME(T.name) + ' DISABLE' 
FROM sys.indexes I
INNER JOIN sys.tables T ON I.object_id = T.object_id
WHERE I.type_desc = 'NONCLUSTERED'
AND I.name IS NOT NULL
AND I.is_disabled = 0

Сценарий удаления и создания всех ограничений, которые я здесь записал: https://www.mssqltips.com/sqlservertip/3347/drop-and-recreate-all-foreign-key-constraints-in-sql-server/

Единственное изменение, которое я создал локальный таблица вместо табличной переменной. Однако этот сценарий сгенерировал весь код удаления в одном столбце и весь код создания в другом столбце ... вместо добавления его в строки. Как вы думаете, возможно, что столбцы не могут содержать полный сценарий? Столбец, похоже, не был усечен, поэтому я подумал, что это не проблема.

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

...