SQL Server - копирование хранимых процедур из одной базы данных в другую

86

Я новичок в SQL, и мне нужно было объединить 2 базы данных .mdf в одну. Я сделал это с помощью диспетчера SQL Server 2008 - Задачи> Импорт / экспорт таблиц. Таблицы и представления были успешно скопированы, но в новой базе данных нет хранимых процедур. Есть ли способ это сделать?

Дуб
источник
1
Если вы хотите скопировать их программно, начните здесь: stackoverflow.com/a/6124487/138938
Джон Кроуэлл,

Ответы:

137
  • Щелкните правой кнопкой мыши базу данных
  • Задачи
  • Сгенерировать скрипты
  • Выберите объекты, которые хотите добавить в сценарий
  • Скрипт в файл
  • Запускать сгенерированные скрипты для целевой базы данных
Джаймал Чохан
источник
Привет, спасибо за быстрый ответ. Не могли бы вы объяснить, как использовать скрипт для целевой базы данных. Я новичок в этом.
Дуб
1
@BarryKaye Что делать, если у него 30-40 хранимых процедур? Разве щелчок правой кнопкой мыши не будет медленным?
rvphx
@Oak Откройте файл сгенерированного сценария в SQL Management Studio. Измените соединение с вашей новой базой данных. Измените строку в самом верху файла, где написано «Use DatabaseName», на вашу базу данных и выполните.
Джаймал Чохан,
Вау. Теперь я подумал, что я единственный, кому нравится подход, основанный на графическом интерфейсе !!
rvphx
10
@RajivVarma - вы делаете это задание один раз для базы данных, а не для каждого SP! Если вы установите флажок верхнего уровня рядом с «Хранимые процедуры», он выберет их все вместе - 1 щелчок.
Барри Кэй
19

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

@sql определяется как nvarchar (max), @Name - целевая база данных

DECLARE c CURSOR FOR 
   SELECT Definition
   FROM [ResiDazeMaster].[sys].[procedures] p
   INNER JOIN [ResiDazeMaster].sys.sql_modules m ON p.object_id = m.object_id

OPEN c

FETCH NEXT FROM c INTO @sql

WHILE @@FETCH_STATUS = 0 
BEGIN
   SET @sql = REPLACE(@sql,'''','''''')
   SET @sql = 'USE [' + @Name + ']; EXEC(''' + @sql + ''')'

   EXEC(@sql)

   FETCH NEXT FROM c INTO @sql
END             

CLOSE c
DEALLOCATE c
ShaQue
источник
Спасибо! ... В комментариях, но не заявленных в коде есть @sql& @Name:DECLARE @sql NVARCHAR(MAX); DECLARE @Name NVARCHAR(32);
datalifenyc
Есть ли способ сделать то же самое на разных серверах? С сервера A на сервер B?
Rajaram1991,
5

Поздно, но дает более подробную информацию, которая может быть полезна ...

Вот список того, что можно сделать с преимуществами и недостатками.

Создавать скрипты с помощью SSMS

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

Сторонние инструменты

  • Плюсы: такие инструменты, как ApexSQL Diff (это то, что я использую, но есть много других, таких как инструменты от Red Gate или Dev Art), будут сравнивать две базы данных одним щелчком мыши и генерировать скрипт, который вы можете выполнить немедленно.
  • Минусы: они не бесплатны (хотя у большинства поставщиков есть полнофункциональная пробная версия)

Системные представления

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

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

select *
from DB1.sys.procedures P
where P.name not in 
 (select name from DB2.sys.procedures P2)
ЛарриБ
источник
5

Первоначально я нашел этот пост в поисках решения для копирования хранимых процедур из моей удаленной производственной базы данных в мою локальную базу данных разработки. После успешного использования предлагаемого в этой ветке подхода я понял, что становлюсь все более ленивым (или находчивым, как вам больше нравится) и хотел, чтобы это было автоматизировано. Я наткнулся на эту ссылку , которая оказалась очень полезной (спасибо, vincpa), и я расширил ее, получив следующий файл (schema_backup.ps1):

$server             = "servername"
$database           = "databaseName"
$output_path        = "D:\prod_schema_backup"
$login = "username"
$password = "password"

$schema             = "dbo"
$table_path         = "$output_path\table\"
$storedProcs_path   = "$output_path\stp\"
$views_path         = "$output_path\view\"
$udfs_path          = "$output_path\udf\"
$textCatalog_path   = "$output_path\fulltextcat\"
$udtts_path         = "$output_path\udtt\"

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo")  | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended")  | out-null
$srvConn = new-object Microsoft.SqlServer.Management.Common.ServerConnection
$srvConn.ServerInstance = $server
$srvConn.LoginSecure = $false
$srvConn.Login = $login
$srvConn.Password = $password
$srv        = New-Object Microsoft.SqlServer.Management.SMO.Server($srvConn)
$db         = New-Object ("Microsoft.SqlServer.Management.SMO.Database")
$tbl        = New-Object ("Microsoft.SqlServer.Management.SMO.Table")
$scripter   = New-Object Microsoft.SqlServer.Management.SMO.Scripter($srvConn)

# Get the database and table objects
$db = $srv.Databases[$database]

$tbl            = $db.tables | Where-object { $_.schema -eq $schema  -and -not $_.IsSystemObject } 
$storedProcs    = $db.StoredProcedures | Where-object { $_.schema -eq $schema -and -not $_.IsSystemObject } 
$views          = $db.Views | Where-object { $_.schema -eq $schema } 
$udfs           = $db.UserDefinedFunctions | Where-object { $_.schema -eq $schema -and -not $_.IsSystemObject } 
$catlog         = $db.FullTextCatalogs
$udtts          = $db.UserDefinedTableTypes | Where-object { $_.schema -eq $schema } 

# Set scripter options to ensure only data is scripted
$scripter.Options.ScriptSchema  = $true;
$scripter.Options.ScriptData    = $false;

#Exclude GOs after every line
$scripter.Options.NoCommandTerminator   = $false;
$scripter.Options.ToFileOnly            = $true
$scripter.Options.AllowSystemObjects    = $false
$scripter.Options.Permissions           = $true
$scripter.Options.DriAllConstraints     = $true
$scripter.Options.SchemaQualify         = $true
$scripter.Options.AnsiFile              = $true

$scripter.Options.SchemaQualifyForeignKeysReferences = $true

$scripter.Options.Indexes               = $true
$scripter.Options.DriIndexes            = $true
$scripter.Options.DriClustered          = $true
$scripter.Options.DriNonClustered       = $true
$scripter.Options.NonClusteredIndexes   = $true
$scripter.Options.ClusteredIndexes      = $true
$scripter.Options.FullTextIndexes       = $true

$scripter.Options.EnforceScriptingOptions   = $true

function CopyObjectsToFiles($objects, $outDir) {
    #clear out before 
    Remove-Item $outDir* -Force -Recurse
    if (-not (Test-Path $outDir)) {
        [System.IO.Directory]::CreateDirectory($outDir)
    }   

    foreach ($o in $objects) { 

        if ($o -ne $null) {

            $schemaPrefix = ""

            if ($o.Schema -ne $null -and $o.Schema -ne "") {
                $schemaPrefix = $o.Schema + "."
            }

            #removed the next line so I can use the filename to drop the stored proc 
            #on the destination and recreate it
            #$scripter.Options.FileName = $outDir + $schemaPrefix + $o.Name + ".sql"
            $scripter.Options.FileName = $outDir + $schemaPrefix + $o.Name
            Write-Host "Writing " $scripter.Options.FileName
            $scripter.EnumScript($o)
        }
    }
}

# Output the scripts
CopyObjectsToFiles $tbl $table_path
CopyObjectsToFiles $storedProcs $storedProcs_path
CopyObjectsToFiles $views $views_path
CopyObjectsToFiles $catlog $textCatalog_path
CopyObjectsToFiles $udtts $udtts_path
CopyObjectsToFiles $udfs $udfs_path

Write-Host "Finished at" (Get-Date)
$srv.ConnectionContext.Disconnect()

У меня есть файл .bat, который вызывает это и вызывается из планировщика заданий. После обращения к файлу Powershell у меня есть:

for /f %f in ('dir /b d:\prod_schema_backup\stp\') do sqlcmd /S localhost /d dest_db /Q "DROP PROCEDURE %f"

Эта строка пройдет через каталог и отбросит процедуры, которые она собирается воссоздать. Если бы это не была среда разработки, мне бы не хотелось программно отбрасывать процедуры таким образом. Затем я переименовываю все файлы хранимых процедур в .sql:

powershell Dir d:\prod_schema_backup\stp\ | Rename-Item -NewName { $_.name + ".sql" }

А затем запустите:

for /f %f in ('dir /b d:\prod_schema_backup\stp\') do sqlcmd /S localhost /d dest_db /E /i "%f".sql

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

вандш
источник
Мне это нравится. Я должен написать процесс для архивирования фрагментов из производственной БД по одному году за раз. Я не хочу, чтобы висят файлы SQL, которые, вероятно, не будут обновляться по мере развития схемы, поэтому я адаптирую это для создания пустой БД на основе цели без промежуточного шага записи файлов на диск (подробнее очистить). Я считаю, что это, вероятно, лучший и наиболее пригодный для повторного использования ответ на этот вопрос, сэр!
Стив Петтифер
3

Вы можете использовать функцию SSMS «Generate Scripts ...» для написания скриптов, которые вам нужно передать. Щелкните правой кнопкой мыши исходную базу данных в SSMS, выберите «Создать сценарии ...» и следуйте инструкциям мастера. Затем запустите полученный сценарий, который теперь будет содержать операторы создания хранимой процедуры.

синий вектор
источник
3

использовать

select * from sys.procedures

показать все свои процедуры;

sp_helptext @objname = 'Procedure_name'

получить код

и ваше творчество, чтобы создать что-то, чтобы перебрать их все и сгенерировать код экспорта :)

Диего
источник
3

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

sqlcmd -S <server name> -U <user name> -d <DB name> -i <script file> -o <output log file> 
Рахул
источник
0

В Mgmt Studio щелкните правой кнопкой мыши исходную базу данных, затем «Задачи», затем «Создать сценарии» ... - следуйте указаниям мастера.

Барри Кэй
источник
0

ВЫБЕРИТЕ определение + char (13) + 'GO' FROM MyDatabase.sys.sql_modules s ВНУТРЕННЕЕ СОЕДИНЕНИЕ MyDatabase.sys.procedures p ON [s]. [Object_id] = [p]. [Object_id] WHERE p.name LIKE 'Something% '"запрос" c: \ SP_scripts.sql -S MyInstance -T -t -w

получить sp и выполнить его

ShaQue
источник
Это очень хорошее решение, но 1) вы должны указать, что требуется вывод текста или файла (не отображайте результаты в сетке, иначе вы потеряете символы EOL) и 2) кажется, что существует ограничение в 8k для вывода текста в SQL Server Management Studio.
DAB
0

Другой вариант - передать хранимые процедуры с помощью служб SQL Server Integration Services (SSIS) . Есть задача под названием «Задача передачи объектов SQL Server» . Вы можете использовать задание для передачи следующих предметов:

  • Столы
  • Просмотры
  • Хранимые процедуры
  • Пользовательские функции
  • По умолчанию
  • Типы данных, определяемые пользователем
  • Функции разделения
  • Схемы перегородок
  • Схемы
  • Сборки
  • Пользовательские агрегаты
  • Типы, определяемые пользователем
  • Коллекция схем XML

Это графическое руководство для задачи передачи объектов SQL Server.

Абдолла
источник