SQL Server - copia procedimentos armazenados de um banco de dados para outro

86

Eu sou novo em SQL, e o que eu precisava fazer era combinar 2 bancos de dados .mdf em um. Fiz isso usando o SQL Server 2008 Manager - Tarefas> Importar / Exportar tabelas. As tabelas e visualizações foram copiadas com êxito, mas não há procedimentos armazenados no novo banco de dados. Existe alguma maneira de fazer isso?

Carvalho
fonte
1
Se você deseja copiá-los programaticamente, comece aqui: stackoverflow.com/a/6124487/138938
Jon Crowell

Respostas:

137
  • Clique com o botão direito no banco de dados
  • Tarefas
  • Gerar Scripts
  • Selecione os objetos que deseja fazer o script
  • Script para arquivo
  • Execute scripts gerados no banco de dados de destino
Jaimal Chohan
fonte
Oi, obrigado pela resposta rápida. Você pode explicar como usar o script no banco de dados de destino. Eu sou novo nisso.
Oak
1
@BarryKaye E se ele tiver 30-40 procedimentos armazenados? Clicar com o botão direito não seria um pouco lento?
rvphx de
@Oak Abra o arquivo de script gerado no SQL Management Studio. Altere a conexão para seu novo banco de dados. Altere a linha no topo do arquivo onde diz 'Use DatabaseName' para seu banco de dados e execute.
Jaimal Chohan de
Uau. Agora eu pensei que era o único que gostava da abordagem baseada em GUI !!
rvphx de
10
@RajivVarma - você faz esta tarefa uma vez para o banco de dados - não para cada SP! Se você marcar a caixa de seleção de nível superior ao lado de "Procedimentos armazenados", ela os seleciona todos juntos - 1 clique.
Barry Kaye
19

Este código copia todos os procedimentos armazenados no banco de dados Master para o banco de dados de destino. Você pode copiar apenas os procedimentos que desejar, filtrando a consulta no nome do procedimento.

@sql é definido como nvarchar (max), @Name é o banco de dados de destino

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
fonte
Obrigado! ... Nos comentários, mas não declarados no código estão @sql& @Name:DECLARE @sql NVARCHAR(MAX); DECLARE @Name NVARCHAR(32);
datalifenyc
Existe alguma maneira de fazer isso em servidores diferentes? Do servidor A para o servidor B?
Rajaram1991
5

Mais tarde, mas dá mais detalhes que podem ser úteis ...

Aqui está uma lista de coisas que você pode fazer com vantagens e desvantagens

Gerar scripts usando SSMS

  • Prós: extremamente fácil de usar e com suporte por padrão
  • Contras: os scripts podem não estar na ordem de execução correta e você pode obter erros se o procedimento armazenado já existir no banco de dados secundário. Certifique-se de revisar o script antes de executá-lo.

Ferramentas de terceiros

  • Prós: ferramentas como ApexSQL Diff (é o que eu uso, mas existem muitas outras como ferramentas da Red Gate ou Dev Art) irão comparar dois bancos de dados em um clique e gerar um script que você pode executar imediatamente
  • Contras: eles não são gratuitos (a maioria dos fornecedores tem uma versão de avaliação totalmente funcional)

Visualizações do sistema

  • Prós: você pode ver facilmente quais procedimentos armazenados existem no servidor secundário e apenas gerar aqueles que você não tem.
  • Contras: requer um pouco mais de conhecimento de SQL

Aqui está como obter uma lista de todos os procedimentos em algum banco de dados que não existem em outro banco de dados

select *
from DB1.sys.procedures P
where P.name not in 
 (select name from DB2.sys.procedures P2)
LarryB
fonte
5

Originalmente, encontrei esta postagem procurando uma solução para copiar procedimentos armazenados de meu banco de dados de produção remoto para meu banco de dados de desenvolvimento local. Após o sucesso usando a abordagem sugerida neste tópico, percebi que estava ficando cada vez mais preguiçoso (ou engenhoso, o que você preferir) e queria que isso fosse automatizado. Encontrei este link , que se mostrou muito útil (obrigado vincpa), e o estendi, resultando no seguinte arquivo (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()

Eu tenho um arquivo .bat que chama isso e é chamado do Agendador de tarefas. Após a chamada para o arquivo Powershell, eu tenho:

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

Essa linha passará pelo diretório e descartará os procedimentos que vai recriar. Se este não fosse um ambiente de desenvolvimento, eu não gostaria de descartar os procedimentos programaticamente dessa maneira. Em seguida, renomeio todos os arquivos de procedimento armazenado para ter .sql:

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

E então execute:

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

E isso itera por meio de todos os arquivos .sql e recria os procedimentos armazenados. Espero que qualquer parte disso seja útil para alguém.

Vandsh
fonte
Estou gostando disso. Tenho que escrever um processo para arquivar pedaços de um banco de dados de produções um ano de cada vez. Eu não quero ter que ter arquivos SQL pendurados, que provavelmente não serão atualizados conforme o esquema se desenvolve, então estou adaptando isso para criar um banco de dados vazio baseado em um destino sem a etapa intermediária de gravar arquivos no disco (mais limpar). Acho que esta é provavelmente a melhor e mais reutilizável resposta para essa pergunta, parabéns, senhor!
Steve Pettifer
3

Você pode usar a função "Gerar Scripts ..." do SSMS para criar um script de tudo o que você precisa transferir. Clique com o botão direito no banco de dados de origem no SSMS, escolha "Gerar scripts ..." e siga o assistente. Em seguida, execute o script resultante que agora conterá as instruções de criação do procedimento armazenado.

bluevector
fonte
3

usar

select * from sys.procedures

para mostrar todos os seus procedimentos;

sp_helptext @objname = 'Procedure_name'

para obter o código

e sua criatividade para construir algo para percorrer todos eles e gerar o código de exportação :)

Diego
fonte
3

Você pode gerar script dos procs armazenados conforme descrito em outras respostas. Uma vez que o script foi gerado, você pode usar sqlcmdpara executá-los no banco de dados de destino, como

sqlcmd -S <server name> -U <user name> -d <DB name> -i <script file> -o <output log file> 
Rahul
fonte
0

No Mgmt Studio, clique com o botão direito do mouse em seu banco de dados original, em Tarefas e em Gerar scripts ... - siga o assistente.

Barry Kaye
fonte
0

SELECT definição + char (13) + 'GO' FROM MyDatabase.sys.sql_modules s INNER JOIN MyDatabase.sys.procedures p ON [s]. [Object_id] = [p]. [Object_id] ONDE p.name LIKE 'Something% '"queryout" c: \ SP_scripts.sql -S MyInstance -T -t -w

pegue o sp e execute-o

ShaQue
fonte
Esta é uma solução muito boa, mas 1) você deve apontar que a saída de texto ou arquivo é necessária (não exiba os resultados na grade, ou você perderá caracteres EOL) e 2) parece haver um limite de 8k para saída de texto no SQL Server Management Studio.
DAB de
0

Outra opção é transferir procedimentos armazenados usando o SQL Server Integration Services (SSIS) . Há uma tarefa chamada Transferir Objetos do SQL Server Task . Você pode usar a tarefa para transferir os seguintes itens:

  • Mesas
  • Visualizações
  • Procedimentos armazenados
  • Funções definidas pelo usuário
  • Padrões
  • Tipos de dados definidos pelo usuário
  • Funções de Partição
  • Esquemas de Partição
  • Esquemas
  • Assembléias
  • Agregados definidos pelo usuário
  • Tipos definidos pelo usuário
  • Coleção de Esquema XML

É um tutorial gráfico para Transferir Tarefa de Objetos do SQL Server.

Abdollah
fonte