web-dev-qa-db-fra.com

SQL Server - copier les procédures stockées d'une base de données à une autre

Je suis novice en SQL et je devais combiner 2 bases de données .mdf en une. Je l'ai fait à l'aide de SQL Server 2008 Manager - Tâches> Importer/Exporter des tables. Les tables et les vues ont été copiées avec succès, mais la nouvelle base de données ne contient aucune procédure stockée. Y'a-t'il un quelconque moyen d'y arriver?

78
Oak
  • Clic droit sur la base de données
  • Les tâches
  • Générer des scripts
  • Sélectionnez les objets que vous souhaitez scripter
  • Script à fichier
  • Exécuter les scripts générés sur la base de données cible
127
Jaimal Chohan

Ce code copie toutes les procédures stockées dans la base de données principale dans la base de données cible. Vous pouvez copier uniquement les procédures souhaitées en filtrant la requête en fonction du nom de la procédure.

@sql est défini comme nvarchar (max), @Name est la base de données cible

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
15
ShaQue

Plus tard, mais donne plus de détails qui pourraient être utiles…

Voici une liste de choses que vous pouvez faire avec des avantages et des inconvénients

Générez des scripts à l'aide de SSMS

  • Avantages: extrêmement facile à utiliser et supporté par défaut
  • Inconvénients: les scripts peuvent ne pas être dans le bon ordre d'exécution et des erreurs peuvent survenir si une procédure stockée existe déjà dans la base de données secondaire. Assurez-vous de revoir le script avant de l'exécuter.

Outils tiers

  • Avantages: outils tels que ApexSQL Diff (c'est ce que j'utilise, mais il y en a beaucoup d'autres, comme des outils de Red Gate ou Dev. Art) comparera deux bases de données en un clic et générera un script que vous pourrez exécuter immédiatement
  • Inconvénients: ceux-ci ne sont pas gratuits (la plupart des fournisseurs ont cependant un essai entièrement fonctionnel)

Vues système

  • Avantages: Vous pouvez facilement voir quelles procédures stockées existent sur le serveur secondaire et ne générer que celles que vous n’avez pas.
  • Inconvénients: Nécessite un peu plus de connaissances en SQL.

Voici comment obtenir une liste de toutes les procédures d’une base de données qui n’existent pas dans une autre base de données

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

J'ai initialement trouvé cet article à la recherche d'une solution permettant de copier des procédures stockées de ma base de données de production distante vers ma base de données de développement locale. Après avoir utilisé avec succès l'approche suggérée dans ce fil, j'ai compris que je devenais de plus en plus paresseux (ou plein de ressources, selon votre préférence) et que je souhaitais que cela soit automatisé. Je suis tombé sur ce lien , ce qui s’est avéré très utile (merci vincpa), et j’ai prolongé, aboutissant au fichier suivant (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()

J'ai un fichier .bat qui appelle cela et s'appelle à partir du Planificateur de tâches. Après l'appel du fichier Powershell, j'ai:

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

Cette ligne passera par le répertoire et supprimera les procédures à recréer. S'il ne s'agissait pas d'un environnement de développement, je n'aimerais pas abandonner les procédures de cette manière. J'ai alors renommé tous les fichiers de procédure stockée pour avoir .sql:

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

Et puis courez:

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

Et cela parcourt tous les fichiers .sql et recrée les procédures stockées. J'espère que n'importe quelle partie de ceci s'avérera utile à quelqu'un.

4
vandsh

Vous pouvez générer un script de la procédure stockée comme décrit dans d'autres réponses. Une fois le script généré, vous pouvez utiliser sqlcmd pour les exécuter sur le DB cible, comme

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

Vous pouvez utiliser la fonction "Générer des scripts ..." de SSMS pour créer un script de ce que vous devez transférer. Cliquez avec le bouton droit sur la base de données source dans SSMS, choisissez "Générer des scripts ...", puis suivez les instructions de l'assistant. Ensuite, exécutez votre script résultant, qui contiendra désormais les instructions create de la procédure stockée.

3
bluevector

utilisation

select * from sys.procedures

montrer toutes vos procédures;

sp_helptext @objname = 'Procedure_name'

pour obtenir le code

et votre créativité pour construire quelque chose pour les parcourir et générer le code d'exportation :)

3
Diego

Dans Mgmt Studio, cliquez avec le bouton droit de la souris sur votre base de données d'origine, puis sur Tâches, puis sur Générer des scripts ... - suivez l'assistant.

0
Barry Kaye

SELECT définition + caractère (13) + 'GO' FROM MyDatabase.sys.sql_modules s INNER JOIN s MyDatabase.sys.procedures p ON [s]. [Id_objet] = [p]. [Id_objet] WHERE nom p. LIKE 'Quelque chose% '"queryout" c:\SP_scripts.sql -S MonInstance -T -t -w

obtenir le sp et l'exécuter

0
ShaQue