🛠 Outils IT
🛠 98 outils 📚 37 docs
🤖 Assistant

Microsoft SQL Server - Import / Restauration d'une base

1. Introduction et formats acceptes

Trois grands chemins d'import existent vers MSSQL :

Format sourceCommandeNiveau
.bakRESTORE DATABASEBase entiere (la plus rapide)
.sqlsqlcmd -i ou execution dans SSMSDDL + DML, lent mais portable
.csv / .tsvbcp in ou BULK INSERTUne table (apres CREATE TABLE)
.bacpacSqlPackage /Action:ImportBase entiere avec schema + data compresse
.mdf + .ldfCREATE DATABASE ... FOR ATTACHFichiers physiques directs
Choix rapide :
  • J'ai un .bak ? → Section 3 (RESTORE DATABASE)
  • J'ai un .sql ? → Section 4
  • J'ai des CSV ? → Sections 5 / 6
  • J'ai des fichiers .mdf / .ldf seuls ? → Section 8

2. Prerequis et inspection du fichier

2.1 Droits requis

  • RESTORE DATABASE : role dbcreator ou sysadmin
  • BULK INSERT / bcp in : ADMINISTER BULK OPERATIONS + INSERT sur la table
  • Le compte service SQL Server doit pouvoir lire le fichier (.bak / CSV) sur le disque du serveur.

2.2 Inspecter un .bak avant restauration

# Verifier que le fichier est lisible et non corrompu
sqlcmd -S localhost -E -Q "RESTORE VERIFYONLY FROM DISK='D:\backup\MaBase.bak'"

# Voir les jeux de sauvegarde contenus (utile si plusieurs FULL/DIFF dans un meme fichier)
sqlcmd -S localhost -E -Q "RESTORE HEADERONLY FROM DISK='D:\backup\MaBase.bak'"

# Voir les fichiers logiques (noms MDF / LDF) - INDISPENSABLE pour MOVE
sqlcmd -S localhost -E -Q "RESTORE FILELISTONLY FROM DISK='D:\backup\MaBase.bak'"

Le resultat de FILELISTONLY donne par exemple :

LogicalName   PhysicalName                              Type
MaBase        D:\Data\MaBase.mdf                        D
MaBase_log    D:\Logs\MaBase_log.ldf                    L

Notez les LogicalName : ils seront reutilises dans la clause MOVE au moment du RESTORE.

3. Restaurer un .bak (RESTORE DATABASE)

3.1 Restauration simple (memes chemins que la source)

sqlcmd -S localhost -E -Q "RESTORE DATABASE [MaBase] FROM DISK='D:\backup\MaBase.bak' WITH REPLACE, STATS=10"

3.2 Restauration avec relocalisation des fichiers (MOVE)

Cas le plus frequent : restaurer un .bak sur un serveur dont les chemins de stockage sont differents.

sqlcmd -S localhost -E -Q "
RESTORE DATABASE [MaBase]
FROM DISK='D:\backup\MaBase.bak'
WITH
    MOVE 'MaBase'     TO 'D:\SQL\Data\MaBase.mdf',
    MOVE 'MaBase_log' TO 'D:\SQL\Logs\MaBase_log.ldf',
    REPLACE,
    STATS=10
"
Important : Les chemins MOVE TO sont evalues cote serveur. Les dossiers doivent exister et etre accessibles en ecriture par le compte de service SQL Server.

3.3 Restaurer sous un autre nom de base

RESTORE DATABASE [MaBase_Test]
FROM DISK='D:\backup\MaBase.bak'
WITH
    MOVE 'MaBase'     TO 'D:\SQL\Data\MaBase_Test.mdf',
    MOVE 'MaBase_log' TO 'D:\SQL\Logs\MaBase_Test_log.ldf',
    REPLACE

3.4 Options principales

OptionEffet
REPLACEEcrase la base existante (sinon erreur si elle existe deja)
RECOVERY (defaut)La base est utilisable apres restauration
NORECOVERYLa base reste en mode "restauration" : permet d'appliquer des DIFF ou des LOG ensuite
STANDBY = 'fichier_undo.bak'La base est lisible mais des logs peuvent encore etre appliques
STATS=10Affiche la progression tous les 10%
CHECKSUMVerifie l'integrite a la lecture
FILE=2Restaure le 2eme jeu de sauvegarde du fichier (cf. HEADERONLY)

3.5 Chaine FULL + DIFF + LOG (point-in-time)

-- 1) Restaurer le FULL en NORECOVERY
RESTORE DATABASE [MaBase] FROM DISK='D:\backup\MaBase_FULL.bak'
WITH NORECOVERY, REPLACE;

-- 2) Restaurer le DIFF (toujours NORECOVERY si on enchaine avec un LOG)
RESTORE DATABASE [MaBase] FROM DISK='D:\backup\MaBase_DIFF.bak'
WITH NORECOVERY;

-- 3) Restaurer les LOG, idealement en STOPAT pour un point-in-time
RESTORE LOG [MaBase] FROM DISK='D:\backup\MaBase_LOG.trn'
WITH RECOVERY, STOPAT = '2026-05-21 10:00:00';

3.6 Restauration en script PowerShell

param(
    [string]$Server     = "localhost",
    [string]$BakFile    = "D:\backup\MaBase.bak",
    [string]$NewDbName  = "MaBase",
    [string]$DataPath   = "D:\SQL\Data",
    [string]$LogPath    = "D:\SQL\Logs"
)

# 1. Lire FILELISTONLY pour recuperer les LogicalName
$files = & sqlcmd -S $Server -E -h-1 -W -s "|" -Q "SET NOCOUNT ON; RESTORE FILELISTONLY FROM DISK='$BakFile'"

# 2. Construire les clauses MOVE
$moves = @()
foreach ($line in $files) {
    if ($line -match "^(\S+)\|(\S+)\|(D|L)\|") {
        $logicalName = $matches[1]
        $type        = $matches[3]
        if ($type -eq "D") {
            $newPath = Join-Path $DataPath "$NewDbName.mdf"
        } else {
            $newPath = Join-Path $LogPath  "${NewDbName}_log.ldf"
        }
        $moves += "MOVE '$logicalName' TO '$newPath'"
    }
}

# 3. Construire et executer le RESTORE
$moveClause = $moves -join ", "
$restore = "RESTORE DATABASE [$NewDbName] FROM DISK='$BakFile' WITH $moveClause, REPLACE, STATS=10"

Write-Host "Restauration en cours..." -ForegroundColor Cyan
& sqlcmd -S $Server -E -Q $restore

4. Importer un .sql (script T-SQL)

4.1 Pre-requis : creer la base cible

sqlcmd -S localhost -E -Q "CREATE DATABASE [MaBase]"

4.2 Executer le script

# Mode caracteres : utf-8 (UTF-8 BOM)
sqlcmd -S localhost -E -d MaBase -i "D:\backup\MaBase.sql" -f 65001

# Avec auth SQL
sqlcmd -S localhost -U sa -P MotDePasse -d MaBase -i "D:\backup\MaBase.sql"

# En mode silencieux (pas de message intermediaire), log les erreurs
sqlcmd -S localhost -E -d MaBase -i "D:\backup\MaBase.sql" -b -o "D:\backup\import.log"

4.3 Options sqlcmd utiles

OptionEffet
-i fichierFichier d'entree (script SQL)
-o fichierFichier de sortie (log)
-d baseBase par defaut
-bQuitte avec un code d'erreur si echec (utile en script)
-f 65001Code page UTF-8
-r 1Redirige les erreurs vers stderr
-V 16Severite minimum pour erreur (defaut 0)
-xDesactive l'interpretation des variables

4.4 Gros fichier .sql (> 1 Go)

Pour les exports volumineux, decouper le script ou utiliser osql (deprecie mais plus tolerant) :

# Lire en streaming avec PowerShell
Get-Content D:\backup\big.sql -ReadCount 0 | sqlcmd -S localhost -E -d MaBase

# Alternative : passer par -i (sqlcmd gere bien jusqu'a plusieurs Go)
sqlcmd -S localhost -E -d MaBase -i "D:\backup\big.sql" -b
Erreur frequente "Incorrect syntax near GO" : les exports de mssql-scripter contiennent des separateurs GO. Ils sont compris par sqlcmd mais pas par tous les executeurs SQL (.NET SqlCommand, par exemple). Utiliser sqlcmd -i ou SSMS.

5. Importer un CSV / TSV (bcp)

5.1 Creer la table cible

CREATE TABLE dbo.Clients (
    Id      INT PRIMARY KEY,
    Nom     NVARCHAR(100),
    Email   NVARCHAR(200),
    Actif   BIT
);

5.2 Import avec bcp

# CSV avec virgule, ignore la 1ere ligne (header) avec -F 2
bcp MaBase.dbo.Clients in "D:\import\clients.csv" -c -t"," -r"\n" -F 2 -S localhost -T

# Avec UTF-8 (eviter les pb d'accents)
bcp MaBase.dbo.Clients in "D:\import\clients.csv" -c -t"," -F 2 -C 65001 -S localhost -T

# Avec auth SQL
bcp MaBase.dbo.Clients in "D:\import\clients.csv" -c -t"," -F 2 -S localhost -U sa -P MotDePasse

5.3 Options bcp in

OptionEffet
-F nCommencer a la ligne n (mettre 2 si CSV a une ligne d'entete)
-L nDerniere ligne a importer
-b 10000Taille de batch (commit toutes les n lignes)
-e fichier.errFichier de log des lignes en erreur
-m 100Stoppe apres 100 erreurs
-kConserve les valeurs NULL (n'utilise pas les DEFAULT)
-EGarde les valeurs IDENTITY de la source (IDENTITY_INSERT)
-h "TABLOCK"Verrouille la table : import beaucoup plus rapide

5.4 Fichier format (.fmt) pour structures complexes

# Generer un fichier format
bcp MaBase.dbo.Clients format nul -c -t"," -f D:\import\clients.fmt -S localhost -T

# L'utiliser pour l'import
bcp MaBase.dbo.Clients in D:\import\clients.csv -f D:\import\clients.fmt -S localhost -T
Performance : pour importer des fichiers volumineux (> 1M lignes), combiner : -b 50000 -h "TABLOCK,ORDER(Id ASC)". Gain typique : x5 a x10.

6. BULK INSERT en T-SQL

Alternative interne a bcp : execution depuis n'importe quel client (SSMS, sqlcmd, application).

BULK INSERT dbo.Clients
FROM 'D:\import\clients.csv'
WITH (
    FIELDTERMINATOR = ',',
    ROWTERMINATOR   = '\n',
    FIRSTROW        = 2,         -- ignore la 1ere ligne (header)
    CODEPAGE        = '65001',   -- UTF-8
    DATAFILETYPE    = 'char',
    KEEPNULLS,                   -- preserve les NULL
    TABLOCK,                     -- accelere
    ERRORFILE       = 'D:\import\clients.err',
    MAXERRORS       = 100
);
Chemin : le fichier est lu cote serveur SQL Server. Si vous lancez la commande depuis un poste distant, le chemin D:\import\clients.csv doit exister sur le serveur, pas sur le poste client. Pour utiliser un partage : FROM '\\serveur\partage\file.csv' + droits SMB du compte de service.

6.1 OPENROWSET BULK (alternative)

-- Permet de filtrer / transformer avant insertion
INSERT INTO dbo.Clients (Id, Nom, Email)
SELECT Id, Nom, Email
FROM OPENROWSET(
    BULK 'D:\import\clients.csv',
    FORMATFILE = 'D:\import\clients.fmt',
    FIRSTROW   = 2
) AS src
WHERE Actif = 1;

7. Importer un .bacpac (SqlPackage)

SqlPackage /Action:Import `
    /SourceFile:"D:\import\MaBase.bacpac" `
    /TargetServerName:"localhost" `
    /TargetDatabaseName:"MaBase_New" `
    /TargetTrustServerCertificate:True

Options utiles :

  • /p:DatabaseEdition=Basic (Azure SQL : edition cible)
  • /p:DatabaseServiceObjective=S1 (niveau de service)
  • /p:Storage=File (defaut : fichier ; pour Azure : BlobStorage)

7.1 Importer un .dacpac (schema seulement)

SqlPackage /Action:Publish `
    /SourceFile:"D:\import\MaBase.dacpac" `
    /TargetServerName:"localhost" `
    /TargetDatabaseName:"MaBase_Empty"

8. Attacher des fichiers MDF / LDF

Si vous recevez les fichiers physiques d'une base (.mdf et .ldf) au lieu d'un .bak :

-- Copier d'abord les fichiers dans un dossier accessible par le service SQL
-- Exemple : D:\SQL\Data\MaBase.mdf et D:\SQL\Logs\MaBase_log.ldf

CREATE DATABASE [MaBase]
ON   (FILENAME = N'D:\SQL\Data\MaBase.mdf'),
     (FILENAME = N'D:\SQL\Logs\MaBase_log.ldf')
FOR ATTACH;

8.1 Attacher sans le LDF (regenere automatiquement)

CREATE DATABASE [MaBase]
ON (FILENAME = N'D:\SQL\Data\MaBase.mdf')
FOR ATTACH_REBUILD_LOG;
Risque : ATTACH_REBUILD_LOG ignore les transactions non commitees du LDF original. A utiliser uniquement si le LDF est perdu ou corrompu.

8.2 Detacher (avant deplacement)

USE master;
EXEC sp_detach_db 'MaBase';
-- Puis copier MDF/LDF vers le nouveau serveur

9. Verifications post-import

9.1 Integrite physique de la base

USE MaBase;
DBCC CHECKDB WITH NO_INFOMSGS, ALL_ERRORMSGS;

9.2 Mise a jour des statistiques

USE MaBase;
EXEC sp_updatestats;

9.3 Verifier les utilisateurs orphelins (SID different sur le nouveau serveur)

USE MaBase;
EXEC sp_change_users_login 'Report';   -- Liste les orphelins

-- Reassigner un login existant
EXEC sp_change_users_login 'Update_One', 'mon_user', 'mon_login_sql';

9.4 Verifier la taille et l'espace

USE MaBase;
EXEC sp_spaceused;

-- Par table
SELECT
    t.name AS TableName,
    SUM(p.rows) AS RowCount,
    SUM(a.total_pages) * 8 / 1024.0 AS TotalSizeMB
FROM sys.tables t
JOIN sys.partitions p ON t.object_id = p.object_id
JOIN sys.allocation_units a ON p.partition_id = a.container_id
WHERE p.index_id IN (0, 1)
GROUP BY t.name
ORDER BY TotalSizeMB DESC;

9.5 Reorganiser / Reconstruire les index

-- Reconstruire tous les index de toutes les tables
USE MaBase;
EXEC sp_MSforeachtable 'ALTER INDEX ALL ON ? REBUILD';

10. Depannage courant

ErreurCauseSolution
The media set has 2 family members but only 1 are provided Le .bak a ete fait sur plusieurs fichiers (cf. section 3.6 export) Specifier tous les fichiers : FROM DISK='f1.bak', DISK='f2.bak'
The backup set holds a backup of a database other than the existing Le .bak contient une autre base que celle visee Ajouter WITH REPLACE
Restore failed for Server. Exclusive access could not be obtained La base cible est en cours d'utilisation ALTER DATABASE [base] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; puis RESTORE
The version of the database is greater than the current server .bak issu d'une version MSSQL plus recente Restaurer sur la meme version (ou superieure). Impossible de downgrader.
RESTORE detected an error on page .bak corrompu RESTORE VERIFYONLY ; sinon refaire le .bak source
BULK INSERT : Cannot bulk load. The file does not exist Chemin evalue cote serveur, pas cote client Deplacer le fichier sur le serveur ou utiliser un partage UNC accessible par le compte service
bcp : Conversion failed Type CSV incompatible avec le schema (ex: date au format inattendu) Generer un fichier format .fmt avec bcp ... format nul et le retoucher
Login failed for user apres restore Utilisateur DB orphelin (SID different) EXEC sp_change_users_login 'Update_One', 'user', 'login'
Mode SINGLE_USER bloque ? Si une autre session a deja pris la base en single_user :
-- Lister les sessions
SELECT spid FROM sys.sysprocesses WHERE dbid = DB_ID('MaBase');

-- Tuer une session
KILL 53;

-- Repasser en multi-user
ALTER DATABASE [MaBase] SET MULTI_USER;
Voir aussi : MSSQL - Export / Dump d'une base pour generer les fichiers, et MSSQL - Conversion vers MySQL / PostgreSQL pour la migration vers un autre SGBD.