Методология контроля версий SQL - PullRequest
14 голосов
/ 05 мая 2010

На SO есть несколько вопросов о контроле версий для SQL и большом количестве ресурсов в Интернете, но я не могу найти что-то, что бы полностью охватывало то, что я пытаюсь сделать.

Прежде всего, я говорю о методологии здесь. Я знаком с различными приложениями по управлению исходным кодом и знаком с такими инструментами, как SQL Gate в Red Gate и т. Д., И знаю, как написать приложение для автоматической проверки входов и выходов из моей системы контроля версий. Если есть инструмент, который был бы особенно полезен для предоставления совершенно новой методологии или который имел бы полезную и необычную функциональность, то отлично, но для задач, упомянутых выше, я уже настроен.

Требования, которым я пытаюсь соответствовать:

  • Версии схемы базы данных и справочной таблицы
  • Версии сценариев DML для исправлений данных в больших таблицах
  • Сервер может быть повышен с версии N до версии N + X, где X не всегда может быть 1
  • Код не дублируется в системе управления версиями - например, если я добавляю столбец в таблицу, мне не нужно проверять, чтобы изменения были как в сценарии создания, так и в сценарии изменения
  • Система должна поддерживать несколько клиентов, которые находятся в разных версиях для приложения (пытаясь получить их все в пределах 1 или 2 выпусков, но пока нет)

Некоторые организации хранят сценарии инкрементного изменения в своем контроле версий, и для перехода с версии N на N + 3 вам придется запускать сценарии для N-> N + 1, затем N + 1-> N + 2, затем N + 2- > N + 3. Некоторые из этих сценариев могут быть повторяющимися (например, добавляется столбец, но затем он изменяется для изменения типа данных). Мы пытаемся избежать этой повторяемости, поскольку некоторые клиентские БД могут быть очень большими, поэтому эти изменения могут занять больше времени, чем необходимо.

Некоторые организации просто сохраняют полный сценарий построения базы данных на каждом уровне версии, а затем используют такой инструмент, как SQL Compare, чтобы вывести базу данных до одной из этих версий. Проблема здесь в том, что смешивание сценариев DML может быть проблемой. Представьте себе сценарий, в котором я добавляю столбец, использую скрипт DML для заполнения указанного столбца, затем в более поздней версии это имя столбца изменяется.

Возможно, есть какое-то гибридное решение? Может я просто прошу слишком много? Любые идеи или предложения будут с благодарностью.

Если модераторы считают, что это более уместно для вики сообщества, пожалуйста, сообщите мне.

Спасибо!

Ответы [ 6 ]

6 голосов
/ 06 мая 2010

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

  • База данных не требует независимой версии из приложения
  • Все сценарии обновления базы данных должны быть идемпотентными

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

Конечно, этот метод предъявляет несколько требований к дизайну базы данных:

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

Примеры из недавнего проекта:

001.sql:

if object_id(N'dbo.Registrations') is null 
begin
    create table dbo.Registrations
    (
        [Id]                    uniqueidentifier not null,
        [SourceA]               nvarchar(50)     null,
        [SourceB]               nvarchar(50)     null,
        [Title]                 nvarchar(50)     not null,
        [Occupation]            nvarchar(50)     not null,
        [EmailAddress]          nvarchar(100)    not null,
        [FirstName]             nvarchar(50)     not null,
        [LastName]              nvarchar(50)     not null,
        [ClinicName]            nvarchar(200)    not null,
        [ClinicAddress]         nvarchar(50)     not null,
        [ClinicCity]            nvarchar(50)     not null,
        [ClinicState]           nchar(2)         not null,
        [ClinicPostal]          nvarchar(10)     not null,
        [ClinicPhoneNumber]     nvarchar(10)     not null,
        [ClinicPhoneExtension]  nvarchar(10)     not null,
        [ClinicFaxNumber]       nvarchar(10)     not null,
        [NumberOfVets]          int              not null,  
        [IpAddress]             nvarchar(20)     not null,
        [MailOptIn]             bit              not null,
        [EmailOptIn]            bit              not null,
        [Created]               datetime         not null,
        [Modified]              datetime         not null,
        [Deleted]               datetime         null
    );
end

if not exists(select 1 from information_schema.table_constraints where constraint_name = 'pk_registrations')
    alter table dbo.Registrations add
        constraint pk_registrations primary key nonclustered (Id);

if not exists (select 1 from sysindexes where [name] = 'ix_registrations_created')
    create clustered index ix_registrations_created
        on dbo.Registrations(Created);

if not exists (select 1 from sysindexes where [name] = 'ix_registrations_email')
    create index ix_registrations_email
        on dbo.Registrations(EmailAddress);

if not exists (select 1 from sysindexes where [name] = 'ix_registrations_email')
    create index ix_registrations_name_and_clinic
        on dbo.Registrations (FirstName,
                              LastName,
                              ClinicName);

002.sql

/**********************************************************************
  The original schema allowed null for these columns, but we don't want
  that, so update existing nulls and change the columns to disallow 
  null values
 *********************************************************************/

update dbo.Registrations set SourceA = '' where SourceA is null;
update dbo.Registrations set SourceB = '' where SourceB is null;
alter table dbo.Registrations alter column SourceA nvarchar(50) not null;
alter table dbo.Registrations alter column SourceB nvarchar(50) not null;

/**********************************************************************
  The client wanted to modify the signup form to include a fax opt-in
 *********************************************************************/

if not exists 
(
    select 1 
      from information_schema.columns
     where table_schema = 'dbo'
       and table_name   = 'Registrations'
       and column_name  = 'FaxOptIn'
)
alter table dbo.Registrations 
    add FaxOptIn bit null 
        constraint df_registrations_faxoptin default 0;

003.sql, 004.sql и т. Д. *

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

3 голосов
/ 05 мая 2010

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

Самый многообещающий инструмент, который я читал о таких припадках, это Liquibase .
Вот несколько дополнительных ссылок:

2 голосов
/ 06 мая 2010

Да, вы просите много, но все они действительно уместны! Здесь, в Red Gate, мы движемся к полному решению для разработки баз данных с нашим расширением SSMS SQL Source Control и сталкиваемся с аналогичными проблемами.

http://www.red -gate.com / продукция / SQL_Source_Control / index.htm

В следующем выпуске мы полностью поддерживаем изменения схемы и косвенно поддерживаем статические данные с помощью нашего инструмента сравнения данных SQL. Все изменения сохраняются как сценарии создания, хотя при обновлении или развертывании в базе данных инструмент гарантирует, что изменения будут применены соответствующим образом как ALTER или CREATE.

Самым сложным требованием, для которого пока нет простого решения, является управление версиями и развертывание, которые вы очень четко описываете. Если вы вносите сложные изменения в схему и данные, это может быть неизбежным, если сценарий миграции, созданный вручную, создается для перехода между двумя смежными версиями, поскольку не все «намерения» всегда сохраняются вместе с более новой версией. Переименования столбцов являются ярким примером. Решением может быть разработка системы, которая сохраняет намерение, или, если это слишком сложно, позволяет пользователю предоставить собственный сценарий для выполнения сложных изменений. Некоторая структура управления версиями могла бы управлять ими и «волшебным образом» создавать сценарии развертывания из двух произвольных версий.

1 голос
/ 12 мая 2010

Мы используем SQL Examiner для хранения схемы базы данных под контролем версий.Я также попробовал VS2010, но, на мой взгляд, подход VS слишком сложен для небольших и средних проектов.С SQL Examiner я в основном работаю с SSMS и использую SQL Examiner для регистрации обновлений SVN (TFS и SourceSafe также поддерживаются, но я никогда не пробовал).

Вот описание подхода SQL Examiner: Как получить базу данных под контролем версий

1 голос
/ 05 мая 2010

для такого рода проблем используйте Visual Studio Team System 2008 для контроля версий вашей базы данных sql.

в цф нет. функции avialbe как

  • Datacompare
  • Schemacompare
  • управление версиями

об управлении версиями базы данных: http://www.codinghorror.com/blog/2006/12/is-your-database-under-version-control.html для более подробной проверки: http://msdn.microsoft.com/en-us/library/ms364062(VS.80).aspx

0 голосов
/ 14 июля 2010

Попробуйте DBSourceTools. (http://dbsourcetools.codeplex.com)
Это открытый исходный код, специально разработанный для создания сценариев для всей базы данных - таблиц, представлений, процедур на диске, а затем для повторного создания этой базы данных через цель развертывания.
Вы можете записать все данные в сценарий или просто указать, для каких таблиц нужно записывать данные.
Кроме того, вы можете заархивировать результаты для распространения.
Мы используем его для контроля версий баз данных и тестирования обновлений для новых выпусков.
В серверной части он построен на основе SMO и поэтому поддерживает SQL 2000, 2005 и 2008.
DBDiff интегрирован, чтобы позволить сравнения схем.
Повеселись, - Натан.

...