Cet article propose une procédure afin d’exporter les données de vos tables sous forme d’ordre INSERT INTO.
Nous poursuivrons cette série d’article consacré à la rétro ingénierie avec un article consacré à l’écriture d’une procédure de création des tables, puis une dernière consacrée aux objets de code (fonctions, procédures, triggers).
CREATE PROCEDURE P_RETRO_INSERT @TABLE NVARCHAR(128),
@SCHEMA NVARCHAR(128) = 'dbo',
@IDENT_FORCE BIT = 1
AS
/******************************************************************************
* Frédéric Brouard - SQLpro - http://www.sqlspot.com - 2008-09-02 *
*******************************************************************************
* Exporter les données des tables sous forme d'ordre INSERT INTO *
*******************************************************************************
* paramètres : @SCHEMA nom du schéma de la table (si NULL ou vide dbo) *
* @TABLE nom de la table *
* @IDENT_FORCE force l'insertion des autoincréments *
*******************************************************************************
* NOTA : - Les types image, sql_variant, xml, rowversion, timestamp, binary, *
* varbinary et xml ne sont pas supportés dans cette version *
* - valable pour SQL server 2005 et suivants *
*******************************************************************************
* copyright F. Brouard / SQLpro / SQLspot *
*******************************************************************************
* MODIFICATIONS : *
* - rajout de "AS SQL_COMMAND" dans la ligne : *
* SET @SQL = 'SELECT ''' + @SQLFIX + ''' + SQL_COMMAND +'') '' ... *
* - suppression des tirets dans les dates *
* - ajout des types date, time et datetime2 *
* - supression des blancs inutile des valeurs chaînes de caractères *
* - rajout de la gestion des NULL dans les valeurs retournées *
******************************************************************************/
-- met le schéma à dbo à défaut
SET @SCHEMA = COALESCE(NULLIF(@SCHEMA , ''), 'dbo');
-- regarde si la table existe bien
IF NOT EXISTS(SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = @SCHEMA
AND TABLE_NAME = @TABLE
AND TABLE_TYPE = 'BASE TABLE')
BEGIN
SELECT @SCHEMA = COALESCE(@SCHEMA, ''), @TABLE = COALESCE(@TABLE, '')
RAISERROR('Aucune table de nom %s.%s n''a été trouvée dans la base courante.', 16, 1, @SCHEMA, @TABLE);
RETURN;
END
-- préparation des variables
DECLARE @OBJ NVARCHAR(261);
SET @OBJ = '[' +@SCHEMA+'].[' + @TABLE+']'
DECLARE @SQLFIX NVARCHAR(max), @SQLVAL NVARCHAR(max), @SQLCOL NVARCHAR(max), @SQL NVARCHAR(max);
SELECT @SQLFIX = 'INSERT INTO ' + @OBJ + ' (';
-- construit la partie fixe de la chaîne de requête dynamique
SELECT @SQLFIX = @SQLFIX + '['+ COLUMN_NAME +'], '
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = @SCHEMA
AND TABLE_NAME = @TABLE
ORDER BY ORDINAL_POSITION;
SELECT @SQLFIX = SUBSTRING(@SQLFIX, 1, LEN(@SQLFIX) -1) +') VALUES (', @SQLVAL = 'SELECT ', @SQLCOL = '';
-- construit la partie variable de la chaîne de requête
SELECT @SQLVAL = @SQLVAL +
CASE
WHEN DATA_TYPE IN ('nchar', 'nvarchar', 'char', 'varchar', 'text', 'ntext')
THEN 'COALESCE('''''''' + REPLACE(RTRIM('+COLUMN_NAME+'), '''''''', '''''''''''') +'''''''', ''NULL'') +'', ''+ '
WHEN DATA_TYPE IN ('float', 'real', 'decimal', 'smallint', 'int', 'bigint', 'tinyint', 'bit',
'money', 'smallmoney')
THEN 'COALESCE(CAST('+COLUMN_NAME+' AS VARCHAR(128)), ''NULL'') +'', ''+ '
WHEN DATA_TYPE IN ('datetime', 'smalldatetime', 'date', 'time', 'datetime2')
THEN 'COALESCE('''''''' + REPLACE(CONVERT(VARCHAR(32), '+COLUMN_NAME+', 121), ''-'', '''')+ '''''''', ''NULL'') +'', ''+ '
WHEN DATA_TYPE IN ('uniqueidentifier')
THEN 'COALESCE('''''''' + CAST('+COLUMN_NAME+'AS VARCHAR(64))+'''''''', ''NULL'') +'', ''+ '
ELSE ''
END,
@SQLCOL = @SQLCOL +
CASE
WHEN DATA_TYPE IN ('nchar', 'nvarchar', 'char', 'varchar', 'text', 'ntext',
'float', 'real', 'decimal', 'smallint', 'int', 'bigint', 'tinyint', 'bit',
'money', 'smallmoney', 'datetime', 'smalldatetime',
'date', 'time', 'datetime2', 'uniqueidentifier')
THEN COLUMN_NAME +', '
ELSE ''
END
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = @SCHEMA
AND TABLE_NAME = @TABLE
ORDER BY ORDINAL_POSITION;
SET @SQLCOL = SUBSTRING(@SQLCOL, 1, LEN(@SQLCOL) - 2);
-- réencapsule la requête afin d'avoir les données dans l'ordre de la première colonne
SELECT @SQLVAL = SUBSTRING(@SQLVAL, 1, LEN(@SQLVAL) -6) +' AS SQL_COMMAND, ROW_NUMBER() OVER(ORDER BY '
+ MIN(COLUMN_NAME)+') AS N FROM ' + @OBJ
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = @SCHEMA
AND TABLE_NAME = @TABLE
AND ORDINAL_POSITION = 1;
-- réencapsule la requête afin de générer les données de la table
SET @SQLVAL = 'SELECT SQL_COMMAND, N FROM (' + @SQLVAL +') AS T ';
SET @SQL = 'SELECT ''' + @SQLFIX + ''' + SQL_COMMAND +'') '' as SQL_COMMAND, N FROM (' + @SQLVAL +') AS TT';
-- en cas de présence d'identity et de demande de forçage...
IF @IDENT_FORCE = 1 AND NOT EXISTS(SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMNPROPERTY(OBJECT_ID(@OBJ), COLUMN_NAME, 'IsIdentity') = 1
AND TABLE_SCHEMA = @SCHEMA
AND TABLE_NAME = @TABLE)
SET @IDENT_FORCE = 0
-- ...ajoute les commande de débranchement et de rebranchement
IF @IDENT_FORCE = 1
SET @SQL = 'SELECT CAST(''SET IDENTITY INSERT ' + @OBJ + ' ON'' AS VARCHAR(max)) AS SQL_COMMAND, CAST(0 AS BIGINT) AS N UNION ALL ' + @SQL +
' UNION ALL SELECT CAST(''SET IDENTITY INSERT ' + @OBJ + ' OFF'' AS VARCHAR(max)) AS SQL_COMMAND, CAST(9223372036854775807 AS BIGINT) AS N'
-- réencapsule le tout en requête
SET @SQL = 'SELECT SQL_COMMAND + '';'' FROM (' + @SQL + ') AS TTT ORDER BY N;'
-- exécute la requête finale
EXEC (@SQL)
GO
Exemple d’utilisation :
EXEC P_RETRO_INSERT 'T_CLIENT', 'dbo', 0
***
Frédéric BROUARD – SQLpro – MVP SQL Server
Spécialiste SQL/BD modélisation de données
SQL & SGBDR http://sqlpro.developpez.com/
Expert SQL Server : http://www.sqlspot.com
audits – optimisation – tuning – formation
Améliorations apportées :
– suppression des tirets dans les dates
– ajout des types date, time et datetime2
– suppression des blancs inutile des valeurs chaînes de caractères
– rajout de la gestion des NULL dans les valeurs retournées
Merci pour m’avoir indiqué ces petites erreurs. La première n’est pas encore corrigé, mais la seconde l’est déjà .
Merci Frédéric pour cet excellent script. J’ai longtemps cherché dans SQL 2005 une fonction automatique, un « générer script » ou « exporter données » pour le faire. En vain. Étonnant de la part de SQL Server !
Petites remarques :
1) S’il y a des attributs à NULL cela ne marche pas.
2) Il manque un « AS SQL_COMMAND » dans la requête TT :
SET @SQL = ‘SELECT »’ + @SQLFIX + »’ + SQL_COMMAND + ») » as SQL_COMMAND, N FROM (‘ + @SQLVAL +’) AS TT';
Après ça marche.
Merci.
Eric DD