Хранимые процедуры/схема БД при управлении источником

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

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

Мы используем SQL Server на работе, и я начал использовать darcs для управления версиями, но мне было бы интересно узнать об общих стратегиях, а также о любых удобных инструментах.

Редактировать: Вау, спасибо за все замечательные предложения, ребята! Мне жаль, что я не мог выбрать более одного "Принятого ответа"!

Ответ 1

Мы выбираем script все и включаем все хранимые процедуры и изменения схемы. Нет инструментов wysiwyg, и никакие фантастические программы синхронизации не нужны.

Изменения схемы просты, все, что вам нужно сделать, это создать и поддерживать один файл для этой версии, включая все изменения схемы и данных. Это станет вашим преобразованием script из версии x в x + 1. Затем вы можете запустить его против производственной резервной копии и интегрировать ее в свою ежедневную сборку, чтобы убедиться, что она работает без ошибок. Обратите внимание, что важно не изменять и не удалять уже написанную схему/загрузку данных sql, так как вы можете закончить разбиение любого sql, написанного позже.

-- change #1234
ALTER TABLE asdf ADD COLUMN MyNewID INT
GO

-- change #5678
ALTER TABLE asdf DROP COLUMN SomeOtherID
GO

Для хранимых процедур мы выбираем один файл для sproc, и он использует форму drop/create. Все хранимые процедуры воссоздаются при развертывании. Недостатком является то, что если изменение было произведено вне контроля источника, изменение будет потеряно. В то же время, это верно для любого кода, но ваш DBA'a должен знать об этом. Это действительно заставляет людей за пределами команды удалять ваши хранимые процедуры, поскольку их изменения теряются при обновлении.

Используя Sql Server, синтаксис выглядит следующим образом:

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[usp_MyProc]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [usp_MyProc]
GO

CREATE PROCEDURE [usp_MyProc]
(
    @UserID INT
)
AS

SET NOCOUNT ON

-- stored procedure logic.

SET NOCOUNT OFF

GO  

Осталось только написать служебную программу, которая объединяет все отдельные файлы и создает новый файл со всем набором обновлений (как один script). Сделайте это, сначала добавив изменения схемы, а затем рекурсивную структуру каталогов и включив все файлы хранимых процедур.

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

добавление: Рик прав, что вы потеряете разрешения на хранимые процедуры с помощью DROP/CREATE, поэтому вам может понадобиться написать еще один script, чтобы снова включить определенные разрешения. Это разрешение script будет последним для запуска. Наш опыт нашел больше проблем с семантикой ALTER verses DROP/CREATE. YMMV

Ответ 2

создать "проект базы данных" в Visual Studio для написания и управления вашим кодом SQL и сохранить проект под контролем версий вместе с остальной частью вашего решения.

Ответ 3

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

01.CreateUserTable.sql
02.PopulateUserTable
03.AlterUserTable.sql
04.CreateOrderTable.sql

Идея заключалась в том, что мы всегда знали, какой заказ запускать скрипты, и мы могли бы избежать необходимости решать проблемы целостности данных, которые могут возникнуть, если вы попытаетесь изменить script # 1 (что, по-видимому, приведет к тому, что INSERT в # 2 сбой).

Ответ 4

Одна вещь, которую следует учитывать при создании сценариев drop/create в SQL Server, заключается в том, что разрешения на уровне объекта будут потеряны. Мы изменили наш стандарт, чтобы вместо этого использовать скрипты ALTER, который поддерживает эти разрешения.

Есть несколько других предостережений, например, тот факт, что удаление объекта приводит к потере записей зависимостей, используемых sp_depends, и создание объекта создает только зависимости для этого объекта. Поэтому, если вы отбрасываете/создаете представление, sp_depends больше не будет знать о каких-либо объектах, ссылающихся на это представление.

Мораль истории, используйте сценарии ALTER.

Ответ 5

Я согласен с практикой Роберта Полсона (и выше). Это предполагает, что вы контролируете команду разработчиков с ответственностью и дисциплиной, чтобы придерживаться такой практики.

Чтобы "принудительно" включить в мои команды, наши решения поддерживают как минимум один проект базы данных из Visual Studio Team Edition для профессионалов баз данных. Как и в других проектах в решении, проект базы данных получает управление версиями. Это делает естественным процесс разработки, чтобы разбить все в базе данных на поддерживаемые куски, "дисциплинировать" мою команду на этом пути.

Конечно, будучи проектом Visual Studio, здесь нет идеального места. Есть много причуд, с которыми вы столкнетесь, что может помешать вам или смутить вас. Потребовалось некоторое понимание того, как работает проект, прежде чем заставить его выполнить ваши задачи. Примеры включают

Но для команд, которые не имеют практики управления версиями своих объектов базы данных, это хорошее начало. Другой известной альтернативой, конечно, является Red Gate набор продуктов SQL Server, который большинство людей, которые их используют, считают выше предлагаемого Microsoft.

Ответ 6

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

Ответ 7

Разнообразные перспективы из моего опыта. В мире Oracle все управлялось "созданием" DDL-скриптов. Как упоминал Аххолли, один script для каждого объекта. Если объект необходимо изменить, его DDL script будет изменен. Там одна оболочка script, которая вызывает все объектные скрипты, чтобы вы могли развернуть текущую сборку БД в любую нужную среду. Это для основного создания ядра.

Очевидно, что в живом приложении всякий раз, когда вы нажимаете новую сборку, которая требует, скажем, нового столбца, вы не собираетесь отказываться от таблицы и создавать ее новую. Вы собираетесь сделать ALTER script и добавить столбец. Поэтому каждый раз, когда такое изменение должно произойти, всегда есть две вещи: 1) написать альтернативный DDL и 2) обновить ядро, создать DDL, чтобы отразить изменение. Оба идут в исходное управление, но единственный alter script является скорее кратковременным изменением времени, так как он будет использоваться только для применения дельта.

Вы также можете использовать такой инструмент, как ERWin, для обновления модели и пересылки генерации DDL, но большинство администраторов баз данных, которые, как я знаю, не доверяют инструменту моделирования для генерации script точно так, как они хотят. Вы также можете использовать ERWin для реверсирования вашего основного DDL script в модель периодически, но для того, чтобы заставить его выглядеть правильно (каждый раз, когда вы это делаете),

В мире Microsoft мы использовали подобную тактику, но мы использовали продукт Red Gate для управления сценариями и дельтами. Все еще помещайте скрипты в исходное управление. Еще один script за объект (таблица, sproc, что угодно). В начале некоторые администраторы баз данных действительно предпочитали использовать графический интерфейс SQL Server для управления объектами, а не для использования сценариев. Но это затрудняло управление предприятием по мере его роста.

Если DDL находится в исходном управлении, тривиально использовать любой инструмент построения (обычно ant) для записи развертывания script.

Ответ 8

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

Ответ 9

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

Мы сохранили бы скрипты в исходном элементе управления следующим образом (структура папок ниже):

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

[корень]
    [Приложение]
        [версия]
                   

\ скрипты
    MyApplication\
        1.2.1\
            001.MyTable.Create.sql
            002.MyOtherTable.Create.sql
            100.dbo.usp.MyTable.GetAllNewStuff.sql

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

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

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

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

Ответ 10

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

Для любого нового проекта существует установленная процедура. У нас есть создание схемы script в версии 1, хранимое создание proc script и, возможно, создание начальной загрузки данных script. Все procs хранятся в одном, по общему признанию, массивном файле. Если мы используем Enterprise Library, мы включаем копию создания script для ведения журнала; если это проект ASP.NET с использованием инфраструктуры приложений ASP.NET(аутентификация, персонализация и т.д.), мы также включаем этот script. (Мы сгенерировали его из инструментов Microsoft, а затем изменили его до тех пор, пока он не работал реплицируемым образом на разных сайтах. Не забава, а ценная инвестиция времени.)

Мы используем магический CTRL + F, чтобы найти понравившийся нам процесс.:) (Нам бы это понравилось, если SQL Management Studio имела навигацию по коду, например, VS. Sigh!)

Для последующих версий у нас обычно есть скрипты upgradeSchema, upgradeProc и/или updateDate. Для обновлений схемы мы максимально используем таблицы ALTER, при необходимости создавая новые. Для обновлений proc мы DROP и CREATE.

Одна морщина появляется с таким подходом. Легко создать базу данных, и легко получить новую скорость до текущей версии БД. Однако следует заботиться о генерации DAL (которую мы в настоящее время обычно делаем с SubSonic), чтобы гарантировать, что изменения DB/schema/proc синхронизируются с использованием кода, используемого для доступа к ним. Тем не менее, в наших путях сборки есть командный файл, который генерирует SubSonic DAL, поэтому наша SOP проверяет код DAL, повторно запускает этот командный файл, а затем проверяет все это в любое время при изменении схемы и/или procs. (Это, конечно, запускает сборку источника, обновляет общие зависимости к соответствующим DLL...)

Ответ 11

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

Схема начинается с 1 script, и мы будем делать изменения в версии.

Все это хранится в проекте базы данных визуальной студии, подключенном к TFS (работа @или VisualSVN Server @home для личных вещей) со структурой папок следующим образом:
- проект
- функции
- схема
- хранимые процедуры
- views

Ответ 12

В моей компании мы стараемся хранить все элементы базы данных в исходном контроле как отдельные сценарии так же, как и для отдельных файлов кода. Любые обновления сначала создаются в базе данных, а затем переносятся в репозиторий исходного кода, поэтому сохраняется история изменений.
В качестве второго шага все изменения базы данных переносятся в базу данных интеграции. Эта база данных интеграции представляет собой то, что должна быть в производственной базе данных, например, после развертывания. У нас также есть база данных QA, которая представляет текущее состояние производства (или последнее развертывание). После того, как все изменения внесены в базу данных Integration, мы используем инструмент сравнения схем (Red Gate SQL Diff для SQL Server) для создания script, который будет переносить все изменения из одной базы данных в другую.
Мы обнаружили, что это довольно эффективно, поскольку он генерирует один script, который мы можем легко интегрировать с нашими установщиками. Самая большая проблема, с которой мы часто сталкиваемся, заключается в том, что разработчики забывают перенести свои изменения в интеграцию.

Ответ 13

Мы сохраняем хранимые процедуры в контроле источника.

Ответ 14

Script все (создание объекта и т.д.) и сохраните эти сценарии в исходном элементе управления. Как изменения происходят? Это часть стандартной практики того, как дела обстоят. Нужно добавить таблицу? Напишите CREATE TABLE script. Обновить sproc? Отредактируйте хранимую процедуру script.

Я предпочитаю один script для каждого объекта.

Ответ 15

Для procs напишите procs с обертками script в простые файлы и примените изменения из этих файлов. Если он применяется правильно, вы можете проверить этот файл, и вы также сможете воспроизвести его из этого файла.

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

Ответ 16

Мы сохраняем хранимые процедуры в контроле источника. То, как мы (или, по крайней мере, я) это делаем, это добавить папку в мой проект, добавить файл для каждого SP и вручную скопировать, вставить в него код. Поэтому, когда я меняю SP, мне нужно вручную изменить исходный элемент.

Мне было бы интересно услышать, смогут ли люди сделать это автоматически.

Ответ 17

Я настоятельно рекомендую поддерживать схему и хранимые процедуры в управлении версиями.

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

Схема - это менее очевидный ответ в зависимости от того, что вы имеете в виду. Очень полезно поддерживать SQL, который определяет ваши таблицы в исходном управлении, для дублирования сред (prod/dev/user и т.д.).

Ответ 18

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

Ответ 19

Мы храним все, что связано с приложением в нашем SCM. Сценарии БД обычно хранятся в собственном проекте, но обрабатываются так же, как и любой другой код... дизайн, реализация, проверка, фиксация.

Ответ 20

Я запускаю задание script в формальную структуру каталогов.

Ниже приведен код VS2005, проект командной строки, вызываемый из командного файла, который выполняет эту работу. ключи app.config в конце кода.

Он основан на другом коде, который я нашел в Интернете. Чуть боль, чтобы настроить, но хорошо работает, как только вы его заработаете.

Imports Microsoft.VisualStudio.SourceSafe.Interop
Imports System
Imports System.Configuration

Module Module1

    Dim sourcesafeDataBase As String, sourcesafeUserName As String, sourcesafePassword As String, sourcesafeProjectName As String, fileFolderName As String


    Sub Main()
        If My.Application.CommandLineArgs.Count > 0 Then
            GetSetup()
            For Each thisOption As String In My.Application.CommandLineArgs
                Select Case thisOption.ToUpper
                    Case "CHECKIN"
                        DoCheckIn()
                    Case "CHECKOUT"
                        DoCheckOut()
                    Case Else
                        DisplayUsage()
                End Select
            Next
        Else
            DisplayUsage()
        End If
    End Sub

    Sub DisplayUsage()
        Console.Write(System.Environment.NewLine + "Usage: SourceSafeUpdater option" + System.Environment.NewLine + _
            "CheckIn - Check in ( and adds any new ) files in the directory specified in .config" + System.Environment.NewLine + _
            "CheckOut - Check out all files in the directory specified in .config" + System.Environment.NewLine + System.Environment.NewLine)
    End Sub

    Sub AddNewItems()
        Dim db As New VSSDatabase
        db.Open(sourcesafeDataBase, sourcesafeUserName, sourcesafePassword)
        Dim Proj As VSSItem
        Dim Flags As Integer = VSSFlags.VSSFLAG_DELTAYES + VSSFlags.VSSFLAG_RECURSYES + VSSFlags.VSSFLAG_DELNO
        Try
            Proj = db.VSSItem(sourcesafeProjectName, False)
            Proj.Add(fileFolderName, "", Flags)
        Catch ex As Exception
            If Not ex.Message.ToString.ToLower.IndexOf("already exists") > 0 Then
                Console.Write(ex.Message)
            End If
        End Try
        Proj = Nothing
        db = Nothing
    End Sub

    Sub DoCheckIn()
        AddNewItems()
        Dim db As New VSSDatabase
        db.Open(sourcesafeDataBase, sourcesafeUserName, sourcesafePassword)
        Dim Proj As VSSItem
        Dim Flags As Integer = VSSFlags.VSSFLAG_DELTAYES + VSSFlags.VSSFLAG_UPDUPDATE + VSSFlags.VSSFLAG_FORCEDIRYES + VSSFlags.VSSFLAG_RECURSYES
        Proj = db.VSSItem(sourcesafeProjectName, False)
        Proj.Checkin("", fileFolderName, Flags)
        Dim File As String
        For Each File In My.Computer.FileSystem.GetFiles(fileFolderName)
            Try
                Proj.Add(fileFolderName + File)
            Catch ex As Exception
                If Not ex.Message.ToString.ToLower.IndexOf("access code") > 0 Then
                    Console.Write(ex.Message)
                End If
            End Try
        Next
        Proj = Nothing
        db = Nothing
    End Sub

    Sub DoCheckOut()
        Dim db As New VSSDatabase
        db.Open(sourcesafeDataBase, sourcesafeUserName, sourcesafePassword)
        Dim Proj As VSSItem
        Dim Flags As Integer = VSSFlags.VSSFLAG_REPREPLACE + VSSFlags.VSSFLAG_RECURSYES
        Proj = db.VSSItem(sourcesafeProjectName, False)
        Proj.Checkout("", fileFolderName, Flags)
        Proj = Nothing
        db = Nothing
    End Sub

    Sub GetSetup()
        sourcesafeDataBase = ConfigurationManager.AppSettings("sourcesafeDataBase")
        sourcesafeUserName = ConfigurationManager.AppSettings("sourcesafeUserName")
        sourcesafePassword = ConfigurationManager.AppSettings("sourcesafePassword")
        sourcesafeProjectName = ConfigurationManager.AppSettings("sourcesafeProjectName")
        fileFolderName = ConfigurationManager.AppSettings("fileFolderName")

    End Sub

End Module



<add key="sourcesafeDataBase" value="C:\wherever\srcsafe.ini"/>
<add key="sourcesafeUserName" value="vssautomateuserid"/>
<add key="sourcesafePassword" value="pw"/>
<add key="sourcesafeProjectName" value="$/where/you/want/it"/>
<add key="fileFolderName" value="d:\yourdirstructure"/>

Ответ 21

Если вы ищете легкое готовое решение, наша система Sql Historian использует фоновый процесс для автоматической синхронизации изменений DDL с TFS или SVN, прозрачный для всех, кто вносит изменения в базу данных. По моему опыту, большая проблема заключается в поддержании кода в исходном элементе управления с тем, что было изменено на вашем сервере, - и это потому, что обычно вам приходится полагаться на людей (разработчиков, даже!), Чтобы изменить их рабочий процесс и не забудьте проверить их изменения после того как они уже сделали это на сервере. Наложение этой нагрузки на машину облегчает жизнь.

Ответ 22

Резервное копирование сценариев выпуска в репозитории управления версиями

Это обычная практика. Сценарии выпуска обычно хранятся в папке с именем после релиза.

Это хорошая или плохая практика? Я не знаю. Но

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

Контроль источника хранимых процедур

Нет никакой разницы между хранимыми процедурами и другим кодом, например С++ файлами, касающимися управления версиями.

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

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

Скрипты создания таблицы

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

Если вы хотите развернуть удаление столбца в таблицу, например. то вам нужно создать script с инструкцией ALTER TABLE DROP COLUMN (или сделать некоторые причудливые вещи SWITCH). Но как вы отступаете DROP COLUMN после выполнения? Это практически невозможно.

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

Другие скрипты

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

Сценарии, которые изменяют данные, ведут себя как скрипты создания таблиц (кроме статических сценариев данных)

Если таблица всегда развертывается в пустом состоянии, вы можете развернуть этот script всегда и обрабатывать его точно так же, как любая другая хранимая процедура. Вам не нужны обходные пути ALTER TABLE DROP/ADD COLUMN.

Нижняя линия

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

Но большинство сценариев базы данных можно эффективно обрабатывать.

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