SQL Server - copie des procédures stockées d'une base de données vers une autre


86

Je suis nouveau dans SQL et ce que j'avais à faire était de combiner 2 bases de données .mdf en une seule. Je l'ai fait en utilisant SQL Server 2008 Manager - Tâches> Tables d'importation / exportation. Les tables et les vues ont été copiées avec succès, mais il n'y a pas de procédures stockées dans la nouvelle base de données. Y'a-t'il un quelconque moyen d'y arriver?


1
Si vous souhaitez les copier par programme, commencez ici: stackoverflow.com/a/6124487/138938
Jon Crowell

Réponses:


137
  • Faites un clic droit sur la base de données
  • Tâches
  • Générer des scripts
  • Sélectionnez les objets que vous souhaitez script
  • Script vers fichier
  • Exécuter des scripts générés sur la base de données cible

Salut, merci pour une réponse rapide. Pouvez-vous s'il vous plaît expliquer comment utiliser le script contre la base de données cible. Je suis nouveau dans ce domaine.
Oak

1
@BarryKaye Et s'il a 30 à 40 procédures stockées? Un clic droit ne serait-il pas un peu lent?
rvphx

@Oak Ouvrez le fichier de script de génération dans SQL Management Studio. Modifiez la connexion à votre nouvelle base de données. Changez la ligne tout en haut du fichier où il est dit «Utiliser DatabaseName» dans votre base de données et exécutez.
Jaimal Chohan

Sensationnel. Maintenant, je pensais que j'étais le seul à aimer l'approche basée sur l'interface graphique !!
rvphx

10
@RajivVarma - vous effectuez cette tâche une fois pour la base de données - pas pour chaque SP! Si vous cochez la case de niveau supérieur à côté de "Procédures stockées", il les sélectionne toutes ensemble - 1 clic.
Barry Kaye

19

Ce code copie toutes les procédures stockées dans la base de données Master dans la base de données cible, vous pouvez copier uniquement les procédures que vous aimez en filtrant la requête sur le 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

Merci! ... Dans les commentaires, mais non déclarés dans le code sont @sql& @Name:DECLARE @sql NVARCHAR(MAX); DECLARE @Name NVARCHAR(32);
datalifenyc

Existe-t-il un moyen de faire de même sur différents serveurs? Du serveur A au serveur B?
Rajaram1991

5

Tardive 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érer des scripts à l'aide de SSMS

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

Outils tiers

  • Avantages: des outils comme ApexSQL Diff (c'est ce que j'utilise mais il y en a beaucoup d'autres comme les outils de Red Gate ou Dev Art) compareront deux bases de données en un clic et généreront 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 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

J'ai initialement trouvé cet article à la recherche d'une solution pour 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 réussi à utiliser l'approche suggérée dans ce fil, j'ai réalisé que je devenais de plus en plus paresseux (ou ingénieux, selon ce que vous préférez) et que je voulais que cela soit automatisé. Je suis tombé sur ce lien , qui s'est avéré très utile (merci vincpa), et je l'ai étendu, ce qui a donné le 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 est appelé à partir du planificateur de tâches. Après l'appel au 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 qu'elle va recréer. Si ce n'était pas un environnement de développement, je n'aimerais pas abandonner les procédures par programme de cette façon. Je renomme ensuite 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 exécutez:

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 toute partie de ceci s'avérera utile à quelqu'un.


J'aime ça. Je dois écrire un processus d'archivage des morceaux d'une BD de production une année à la fois. Je ne veux pas avoir à suspendre des fichiers SQL qui ne seront probablement pas mis à jour au fur et à mesure du développement du schéma.J'adapte donc cela pour créer une base de données vide basée sur une cible sans l'étape intermédiaire d'écriture de fichiers sur le disque (plus nettoyer). Je pense que c'est probablement la meilleure et la plus réutilisable réponse à cette question, bravo monsieur!
Steve Pettifer

3

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


3

utilisation

select * from sys.procedures

pour montrer toutes vos procédures;

sp_helptext @objname = 'Procedure_name'

pour obtenir le code

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


3

Vous pouvez générer le script des procs stockés comme décrit dans d'autres réponses. Une fois le script généré, vous pouvez l'utiliser sqlcmdpour les exécuter sur la base de données cible comme

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

0

Dans Mgmt Studio, faites un clic droit sur votre base de données d'origine puis Tâches puis Générer des scripts ... - suivez l'assistant.


0

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

obtenir le sp et l'exécuter


C'est une très bonne solution, mais 1) vous devez souligner que la sortie de texte ou de fichier est nécessaire (n'affichez pas les résultats dans la grille, ou vous perdrez des caractères EOL) et 2) il semble y avoir une limite de 8k pour la sortie de texte dans SQL Server Management Studio.
DAB

0

Une autre option consiste à transférer des procédures stockées à l'aide de SQL Server Integration Services (SSIS) . Il existe une tâche appelée Tâche de transfert d'objets SQL Server . Vous pouvez utiliser la tâche pour transférer les éléments suivants:

  • les tables
  • Vues
  • Procédures stockées
  • Fonctions définies par l'utilisateur
  • Par défaut
  • Types de données définis par l'utilisateur
  • Fonctions de partition
  • Schémas de partition
  • Schémas
  • Assemblées
  • Agrégats définis par l'utilisateur
  • Types définis par l'utilisateur
  • Collection de schémas XML

Il s'agit d'un didacticiel graphique pour la tâche de transfert d'objets SQL Server.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.