SQL, как изменить столбец в таблице SQL, не нарушая другие зависимости?

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

Вот мой вопрос:

У меня есть таблица с именем Контакты со столбцом varchar Название. Теперь, в середине разработки, я хочу заменить поле Title на TitleID, которое является внешним ключом для таблицы ContactTitles. На данный момент таблица Contacts имеет более 60 зависимостей (другие таблицы, функции представлений).

Как я могу сделать это самым безопасным и простым способом?

Мы используем: MSSQL 2005, данные уже перенесены, просто хочу изменить схему.

Изменить:

Спасибо Всем за быстрый повтор.

Как уже упоминалось, таблица Contacts имеет более 60 зависимостей, но при выполнении следующего запроса только 5 из них используют столбец Title. Сценарий миграции был запущен, поэтому никаких изменений данных не требуется.

/*gets all objects which use specified column */

SELECT Name FROM syscomments sc JOIN sysobjects so ON sc.id = so.id WHERE TEXT LIKE '%Title%' AND TEXT LIKE '%TitleID%'

Затем я просмотрел эти 5 представлений и обновил их вручную.


person cinek    schedule 21.06.2010    source источник
comment
Вы должны быть немного осторожны в SQL2005 с этим. Если какие-либо определения имеют длину > 4000 символов, их можно разделить на 2 строки, запрос в моем посте безопаснее (или на самом деле было бы предпочтительнее использовать sys.sql_modules). Я предполагаю, что вы никогда не используете *, который также может все испортить?   -  person Martin Smith    schedule 21.06.2010
comment
@Мартин Смит, вы правы, но я больше интересовался местами, где использовались эти столбцы.   -  person cinek    schedule 21.06.2010
comment
я имею в виду, что существует крошечная вероятность того, что определение разбито таким образом, что одна строка заканчивается ...Tit, а следующая соответствующая строка начинается le..., поэтому запрос LIKE пропустит ее.   -  person Martin Smith    schedule 21.06.2010
comment
@Martin Smith, когда столбец был удален и запущен генератор сущностей, от него не было жалоб (он выполняет проверку схемы). Хорошо, могу сказать, что в этот раз мне повезло.   -  person cinek    schedule 21.06.2010


Ответы (4)


Для Microsoft SQL Server у Redgate есть (не бесплатный) продукт, который может помочь с этим рефакторингом http://www.red-gate.com/products/sql_refactor/index.htm

В прошлом мне удавалось делать это довольно легко (хотя и примитивно), просто получая список вещей для обзора.

SELECT * FROM sys.objects
WHERE OBJECT_DEFINITION(OBJECT_ID) LIKE '%Contacts%' 

(и, возможно, учет информации о зависимостях и фильтрация по типу объекта)

Сценарии всех интересующих вас в Management Studio, а затем просто перейдите по списку, просмотрите их все и измените CREATE на ALTER. Это должно быть довольно простое и повторяющееся изменение даже для 60 возможных зависимостей. Кроме того, если вы ссылаетесь на несуществующий столбец, вы должны получить сообщение об ошибке при запуске сценария для ALTER.

Если вы используете * в своих запросах или специальный SQL в своих приложениях, очевидно, все может быть немного сложнее.

person Martin Smith    schedule 21.06.2010
comment
этот ответ был самым точным для меня. - person cinek; 25.06.2010

Используйте методы рефакторинга. Начните с создания нового поля с именем TitleID, затем скопируйте все заголовки в таблицу ContactTitles. Затем одну за другой обновите каждую из зависимостей, чтобы использовать поле TitleID. Просто убедитесь, что у вас все еще есть работающая система после каждого шага.

Если данные будут меняться, вам нужно быть осторожным и убедиться, что любые изменения в столбце Title также влияют на таблицу ContactTitles. Вам нужно будет только синхронизировать их, пока вы выполняете рефакторинг.

Редактировать: об этом даже есть книга! Рефакторинг баз данных.

person Skilldrick    schedule 21.06.2010

Как указывали другие, это зависит от вашей СУБД.

Есть два подхода:

  • внести изменения в таблицу и исправить все зависимости
  • создайте представление, которое вы можете использовать вместо прямого доступа к таблице (это может защитить вас от будущих изменений в базовых таблицах ядра, но вы можете потерять некоторые функции обновления, в зависимости от вашей СУБД)
person Unreason    schedule 21.06.2010

Используйте SP_Depend «Имя таблицы», чтобы проверить зависимости таблицы, а затем используйте SP_Rename, чтобы переименовать имя столбца, что очень полезно. sp_rename автоматически переименовывает связанный индекс всякий раз, когда переименовывается ограничение PRIMARY KEY или UNIQUE. Если переименованный индекс связан с ограничением PRIMARY KEY, ограничение PRIMARY KEY также автоматически переименовывается процедурой sp_rename.

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

person KuldipMCA    schedule 21.06.2010
comment
Я бы не стал доверять информации о зависимостях, если вы не запустили sp_refreshsqlmodule для всех объектов. Это может быть неправильно, если зависимости создаются не по порядку. - person Martin Smith; 21.06.2010
comment
Когда вы запускаете Sql, все автоматически обновляется. я прав или не прав? поэтому нет проблем с проверкой зависимостей. - person KuldipMCA; 21.06.2010
comment
Почти уверен, что это неправильно, но не стесняйтесь доказывать, что я ошибаюсь! - person Martin Smith; 21.06.2010
comment
Хорошо, ваш способ хорош, но мой способ Быстрый, чтобы получить список зависимостей, которые помогут в разработке. - person KuldipMCA; 21.06.2010