Existe-t-il un moyen de générer un script de création à partir d'une table existante uniquement en T-SQL (c'est-à-dire sans utiliser SMO, car T-SQL n'a pas accès à SMO). Disons qu'une procédure stockée qui reçoit un nom de table et renvoie une chaîne qui contient le script de création pour la table donnée?
Permettez-moi maintenant de décrire la situation à laquelle je suis confronté, car il peut y avoir une manière différente d'aborder cela. J'ai une instance avec plusieurs dizaines de bases de données. Ces bases de données ont toutes le même schéma, toutes les mêmes tables, index et ainsi de suite. Ils ont été créés dans le cadre d'une installation de logiciel tiers. J'ai besoin d'avoir un moyen de travailler avec eux afin de pouvoir agréger leurs données de manière ad hoc. Les gens sympas de dba.se m'ont déjà aidé ici Comment créer un déclencheur dans une autre base de données?
Actuellement, je dois trouver un moyen de faire un choix à partir d'une table dans toutes les bases de données. J'ai enregistré tous les noms de base de données dans une table appelée Databasees
et j'ai écrit le script suivant pour exécuter une instruction select sur chacun d'eux:
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
DROP TABLE #tmp
select * into #tmp from Database1.dbo.Table1 where 1=0
DECLARE @statement nvarchar(max) =
N'insert into #tmp select * from Table1 where Column1=0 and Cloumn2 =1'
DECLARE @LastDatabaseID INT
SET @LastDatabaseID = 0
DECLARE @DatabaseNameToHandle varchar(60)
DECLARE @DatabaseIDToHandle int
SELECT TOP 1 @DatabaseNameToHandle = Name,
@DatabaseIDToHandle = Database_Ref_No
FROM Databasees
WHERE Database_Ref_No > @LastDatabaseID
ORDER BY Database_Ref_No
WHILE @DatabaseIDToHandle IS NOT NULL
BEGIN
DECLARE @sql NVARCHAR(MAX) = QUOTENAME(@DatabaseNameToHandle) + '.dbo.sp_executesql'
EXEC @sql @statement
SET @LastDatabaseID = @DatabaseIDToHandle
SET @DatabaseIDToHandle = NULL
SELECT TOP 1 @DatabaseNameToHandle = Name,
@DatabaseIDToHandle = Database_Ref_No
FROM Databasees
WHERE Database_Ref_No > @LastDatabaseID
ORDER BY Database_Ref_No
END
select * from #tmp
DROP TABLE #tmp
Cependant, le script ci-dessus échoue avec le message suivant:
Une valeur explicite pour la colonne d'identité dans la table '#tmp' ne peut être spécifiée que lorsqu'une liste de colonnes est utilisée et IDENTITY_INSERT est ON.
Ajout de ceci:
SET IDENTITY_INSERT #tmp ON
n'aide pas, car je ne peux pas spécifier la liste des colonnes et la garder générique.
En SQL, il n'y a aucun moyen de désactiver l'identité sur une table donnée. Vous pouvez uniquement déposer une colonne et ajouter une colonne, ce qui, évidemment, change l'ordre des colonnes. Et si l'ordre des colonnes change, vous devez à nouveau spécifier la liste des colonnes, ce serait différent selon la table que vous interrogez.
Je pensais donc que si je pouvais obtenir le script de création de table dans mon code T-SQL, je pouvais le manipuler avec des expressions de manipulation de chaîne pour supprimer la colonne d'identité et également ajouter une colonne pour le nom de la base de données au jeu de résultats.
Quelqu'un peut-il penser à un moyen relativement facile de réaliser ce que je veux?
la source
Il n'est pas possible dans T-SQL de générer un script de création complet d'une table. Au moins, il n'y a pas de construction. vous pouvez toujours écrire votre propre "générateur" en parcourant les informations
sys.columns
.Mais dans votre cas, vous n'avez pas besoin d'obtenir le script de création complet. Tout ce dont vous avez besoin est d'empêcher la
SELECT INTO
copie de la propriété d'identité. La façon la plus simple de le faire est d'ajouter un calcul à cette colonne. Donc au lieu detu dois écrire
Pour générer cette instruction, vous pouvez à nouveau utiliser sys.columns comme dans ce SQL Fiddle
Configuration du schéma MS SQL Server 2008 :
Les deux colonnes dont nous avons besoin sont
name
etis_identity
: Requête 1 :Résultats :
Avec cela, nous pouvons utiliser une
CASE
instruction pour générer chaque colonne pour la liste des colonnes:Requête 2 :
Résultats :
Avec une petite astuce XML, nous pouvons concaténer tout cela ensemble pour obtenir la liste complète des colonnes:
Requête 3 :
Résultats :
Gardez à l'esprit que vous ne pouvez pas créer une table #temp à l'aide de SQL dynamique et l'utiliser en dehors de cette instruction car la table #temp devient hors de portée une fois votre instruction sql dynamique terminée. Vous devez donc soit compresser tout votre code dans la même chaîne SQL dynamique, soit utiliser une vraie table. Si vous devez être en mesure d'exécuter plusieurs de ces scripts / procédures en même temps, vous devez nous fournir un nom de table aléatoire, sinon ils se marcheront les uns sur les autres. Quelque chose comme ça
QUOTENAME(N'temp_'+CAST(NEWID() AS NVARCHAR(40))
devrait faire un assez bon nom.Au lieu de copier toutes les données, vous pouvez également utiliser une technique similaire pour générer automatiquement une vue pour chaque table qui regroupe toutes les incarnations de cette table dans toutes les bases de données. En fonction de la taille de la table, cela peut toutefois être plus rapide ou plus lent, vous devez donc le tester. Si vous suivez cette voie, je placerais ces vues dans une base de données distincte.
la source
Il existe un bon script pour y parvenir dans l'article SQLServerCentral:
La dernière version actuelle du script est également disponible sous forme de texte ici (stormrage.com).
Je souhaite qu'il y ait un moyen d'inclure tout le script ici, car cela fonctionne pour moi. Le script est tout simplement trop long pour être collé ici.
Copyright:
la source
Vous pouvez générer un brut à l'
CREATE TABLE
aide de SQL dynamique à partir des données deINFORMATION_SCHEMA.COLUMNS
.Si vous devez ajouter des contraintes, etc., vous devrez ajouter des informations à partir de certaines des autres
INFORMATION_SCHEMA
vues.Documentation Microsoft
la source