Ajout d'une identité à une colonne existante
je dois changer la clé primaire d'une table à une colonne d'identité, et il y a déjà un certain nombre de lignes dans la table.
j'ai un script pour nettoyer les IDs pour s'assurer qu'ils sont séquentiels à partir de 1, fonctionne très bien sur ma base de données de test.
Qu'est-ce que la commande SQL pour modifier la colonne pour avoir une propriété d'identité?
19 réponses
vous ne pouvez pas modifier les colonnes existantes pour l'identité.
vous avez 2 options,
-
"créer une nouvelle table avec Identité et supprimer la table existante
-
créer une nouvelle colonne avec Identité et supprimer la colonne existante
approche 1. ( nouveau tableau ) ici vous pouvez conserver les valeurs de données existantes sur le colonne d'identité nouvellement créée.
CREATE TABLE dbo.Tmp_Names
(
Id int NOT NULL
IDENTITY(1, 1),
Name varchar(50) NULL
)
ON [PRIMARY]
go
SET IDENTITY_INSERT dbo.Tmp_Names ON
go
IF EXISTS ( SELECT *
FROM dbo.Names )
INSERT INTO dbo.Tmp_Names ( Id, Name )
SELECT Id,
Name
FROM dbo.Names TABLOCKX
go
SET IDENTITY_INSERT dbo.Tmp_Names OFF
go
DROP TABLE dbo.Names
go
Exec sp_rename 'Tmp_Names', 'Names'
approche 2 ( nouvelle colonne ) vous ne pouvez pas conserver les valeurs de données existantes sur la nouvelle colonne identité, la colonne identité contiendra la séquence du numéro.
Alter Table Names
Add Id_new Int Identity(1, 1)
Go
Alter Table Names Drop Column ID
Go
Exec sp_rename 'Names.Id_new', 'ID', 'Column'
voir le Microsoft SQL Server Forum post pour plus de détails:
en SQL 2005 et au-dessus, il y a un truc pour résoudre ce problème sans changer les pages de données de la table. Ceci est important pour les grandes tables où toucher chaque page de données peut prendre des minutes ou des heures. L'astuce fonctionne aussi même si la colonne identité est une clé primaire, fait partie d'un index groupé ou non groupé, ou d'autres gotchas qui peuvent déclencher la solution la plus simple "Ajouter/Supprimer/Renommer la colonne".
voici le truc: vous pouvez utiliser SQL Server's ALTER TABLE...Basculer déclaration pour changer le schéma d'une table sans changer les données, ce qui signifie que vous pouvez remplacer une table avec une identité avec un schéma de table identique, mais sans colonne D'identité. Le même truc fonctionne pour ajouter de l'identité à une colonne existante.
normalement, modifier la TABLE...Le commutateur est utilisé pour remplacer efficacement une partition complète dans une table partitionnée par une nouvelle partition vide. Mais il peut également être utilisé dans les tables non-divisées aussi.
j'ai utilisé cette astuce pour convertir, en moins de 5 secondes, une colonne de A d'une table de ligne de 2,5 milliards de L'identité à une non-identité (afin d'exécuter une requête de plusieurs heures dont le plan de requête a fonctionné mieux pour les colonnes de non-identité), puis restauré le réglage de L'identité, encore une fois en moins de 5 secondes.
voici un exemple de code de comment ça marche.
CREATE TABLE Test
(
id int identity(1,1),
somecolumn varchar(10)
);
INSERT INTO Test VALUES ('Hello');
INSERT INTO Test VALUES ('World');
-- copy the table. use same schema, but no identity
CREATE TABLE Test2
(
id int NOT NULL,
somecolumn varchar(10)
);
ALTER TABLE Test SWITCH TO Test2;
-- drop the original (now empty) table
DROP TABLE Test;
-- rename new table to old table's name
EXEC sp_rename 'Test2','Test';
-- update the identity seed
DBCC CHECKIDENT('Test');
-- see same records
SELECT * FROM Test;
c'est évidemment plus impliqué que le solutions dans d'autres réponses, mais si votre table est grande, cela peut être un vrai gain de vie. Il y a quelques mises en garde:
- autant que je sache, l'identité est la seule chose que vous pouvez changer sur les colonnes de votre table avec cette méthode. Ajout / Suppression de colonnes, modification de la nullité, etc. n'est pas autorisé.
- vous aurez besoin de déposer les clés foriegn avant de faire le commutateur et de les restaurer après.
- même pour avec SCHEMABINDING fonctions, vues, etc.
- nouvelle table de l'index doivent correspondre exactement (mêmes colonnes, même ordre, etc.)
- tables anciennes et nouvelles doivent être sur le même groupe de fichiers.
- ne fonctionne que sur SQL Server 2005 ou après
- j'ai déjà cru que cette astuce ne fonctionne que sur les versions Enterprise ou Developer de SQL Server( parce que les partitions ne sont supportées que dans les versions Enterprise et Developer), mais Mason G. Zhwiti dans son commentaire ci-dessous dit qu'il fonctionne également dans L'Édition Standard SQL aussi. Je suppose que cela signifie que la restriction à L'entreprise ou le développeur ne s'applique pas à modifier la TABLE...COMMUTATEUR.
Il y a un bon article sur TechNet détaillant les exigences ci-dessus.
UPDATE - Eric Wu avait un commentaire ci-dessous qui ajoute des informations importantes sur cette solution. Le copier ici pour s'assurer qu'il obtient plus d'attention:
il y a une autre mise en garde qui vaut la peine d'être mentionnée. Bien que les nouvelle table recevra volontiers des données de l'ancienne table, et tous les de nouvelles lignes seront insérées suivant un modèle d'identité, elles seront commencer à 1 et potentiellement briser si la colonne est une clé primaire. Envisagez de lancer
DBCC CHECKIDENT('<newTableName>')
immédiatement après commutation. Voir msdn.microsoft.com/en-us/library/ms176057.aspx pour plus info.
si la table est activement prolongée avec de nouvelles lignes (ce qui signifie que vous n'avez pas beaucoup de temps d'arrêt entre l'ajout de L'identité et l'ajout de nouvelles lignes, puis à la place de DBCC CHECKIDENT
vous voudrez définir manuellement la valeur de graine d'identité dans le nouveau schéma de table pour être plus grand que le plus grand ID existant dans la table, par exemple IDENTITY (2435457, 1)
. Vous pourriez être en mesure d'inclure à la fois le ALTER TABLE...SWITCH
et le DBCC CHECKIDENT
dans une transaction (ou non-n'avez pas testé ce) mais il semble que le réglage manuel de la valeur de graine sera plus facile et plus sûr.
évidemment, si aucune nouvelle ligne n'est ajoutée à la table (ou si elles ne sont ajoutées qu'occasionnellement, comme un processus quotidien ETL) alors cette condition de course ne se produira pas donc DBCC CHECKIDENT
est très bien.
vous ne pouvez pas modifier une colonne pour en faire une colonne D'identité. Ce que vous devez faire est de créer une nouvelle colonne qui est définie comme une IDENTITÉ à partir de l'obtenir-aller, puis supprimer l'ancienne colonne, et renommer le nouveau à l'ancien nom.
ALTER TABLE (yourTable) ADD NewColumn INT IDENTITY(1,1)
ALTER TABLE (yourTable) DROP COLUMN OldColumnName
EXEC sp_rename 'yourTable.NewColumn', 'OldColumnName', 'COLUMN'
Marc
il y a une solution fraîche décrite ici: SQL SERVER – pour Ajouter ou Supprimer l'Identité de Propriété sur la Colonne
en bref éditez manuellement votre table dans SQL Manager, changez l'identité, ne sauvegardez pas les modifications, montrez simplement le script qui sera créé pour les modifications, Copiez-le et utilisez-le plus tard.
c'est un gain de temps énorme, car il (le script) contient toutes les clés étrangères, les indices, etc. liées à la table que vous changez. La rédaction de cette manuellement... À dieu ne plaise.
explication Simple
renommer la colonne existante en utilisant sp_RENAME
EXEC sp_RENAME ' Table_Name.Existing_ColumnName',' New_ColumnName',' COLUMN '
exemple pour renommer:
la colonne UserID existante est renommée OldUserID
EXEC sp_RENAME 'AdminUsers.UserID' , 'OldUserID', 'COLUMN'
puis Ajouter une nouvelle colonne en utilisant alter query pour définir la clé primaire et valeur d'identité
ALTER TABLE TableName ADD Old_ColumnName INT NOT NULL PRIMARY KEY IDENTITY(1,1)
exemple de clé primaire 151980920"
le nom de la nouvelle colonne créée est UserID
ALTER TABLE Users ADD UserID INT NOT NULL PRIMARY KEY IDENTITY(1,1)
puis supprimer la colonne renommée
ALTER TABLE Table_Name DROP COLUMN Renamed_ColumnName
exemple de Drop renommé colonne
ALTER TABLE Users DROP COLUMN OldUserID
maintenant nous avons ajouté une clé primaire et l'identité à la colonne existante sur la table.
dans sql server 2014 (Je ne sais pas pour les versions inférieures) vous pouvez le faire simplement, en utilisant sequence.
CREATE SEQUENCE sequence_name START WITH here_higher_number_than_max_existed_value_in_column INCREMENT BY 1;
ALTER TABLE table_name ADD CONSTRAINT constraint_name DEFAULT NEXT VALUE FOR sequence_name FOR column_name
je suis un développeur java qui s'est avéré pour obtenir sur une équipe sans DBA et un où en tant que développeur, Je ne peux pas obtenir des droits DBA. J'ai été chargé de déplacer un schéma entier entre deux bases de données, donc sans avoir de DBA, j'ai dû le faire et le faire en exécutant des scripts, ne pouvant pas utiliser L'interface graphique dans SQL Server 2008 parce que je n'avais pas de privilèges d'administration.
Tout a été déplacé sans problème, cependant, lors de l'exécution d'une procédure stockée sur le nouveau schéma.tableau, j'ai découvert que j' perdu l'identité champ dans une table. J'ai vérifié le script qui a créé la table et il était là, cependant, SQL Server ne l'a pas reçu quand j'ai lancé le script. J'ai été informé plus tard par un DBA qu'il avait vu ce même problème avant.
dans tous les cas, pour SQL Server 2008, ce sont les étapes que j'ai prises pour obtenir cette résolution et ils ont fonctionné, donc je poste ceci ici dans l'espoir qu'il sera une aide à quelqu'un. C'est ce que j'ai fait car j'avais des dépendances FK sur une autre table qui
j'ai utilisé cette requête pour vérifier l'identité était effectivement manquante et pour voir les dépendances sur la table.
1.) Trouver des statistiques sur une table:
exec sp_help 'dbo.table_name_old';
2.) Créer un duplicata, une nouvelle table identique, sauf ajouter un champ d'identité sur le champ PK où il était auparavant.
3.) Désactiver l'identité pour déplacer les données.
SET IDENTITY_INSERT dbo.table_name ON
4.) Le transfert de la données.
INSERT INTO dbo.table_name_new
(
field1, field2, etc...
)
SELECT
field1, field2, etc...
FROM
dbo.table_name_old;
5.) Vérifier que les données sont là.
SELECT * FROM dbo.table_name_new
6. De ré-activer l'identité.
SET IDENTITY_INSERT ToyRecP.ToyAwards.lkpFile_New OFF
7.) C'est le meilleur script que j'ai trouvé pour obtenir tous les FK relations de vérifier à quelle table(s) de la table d'origine des références comme des dépendances et je suis tombé sur beaucoup, donc c'est un gardien!
SELECT f.name AS ForeignKey,
OBJECT_NAME(f.parent_object_id) AS TableName,
COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName,
OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id
ORDER BY ReferenceTableName;
8.) Assurez-vous que vous avez tous les scripts PK et FK pour toutes les tables concernées, avant la prochaine étape.
9.) Vous pouvez faire un clic droit sur chaque touche et le script en utilisant SQL Server 2008
10.) Supprimer le (s) FK(s) de la (Des) table (s) de dépendances en utilisant cette syntaxe:
ALTER TABLE [dbo].[table_name] DROP CONSTRAINT [Name_of_FK]
11.) Supprimer la table originale:
DROP TABLE dbo.table_name_old;
13. Ces prochaines étapes s'appuient sur les scripts que vous avez créés dans SQL Server 2008 à l'étape 9.
-- ajouter le PK à la nouvelle table.
-- ajouter le FK à la nouvelle table.
--ajouter les FK de retour à la table des dépendances.
14.) Vérifier que tout est exact et complet. J'ai utilisé l'interface graphique pour regarder les tableaux.
15.) Renommez la nouvelle table pour les tables d'origine nom.
exec sp_RENAME '[Schema_Name.OldTableName]' , '[NewTableName]';
enfin, tout a fonctionné!
de par sa conception, il n'y a pas de façon simple d'allumer ou d'éteindre la caractéristique d'identité d'une colonne existante. Le seul moyen propre de faire cela est de créer une nouvelle colonne et d'en faire une colonne d'identité ou de créer une nouvelle table et la migration de vos données.
si nous utilisons SQL Server Management Studio pour nous débarrasser de la valeur d'identité sur la colonne" id", une nouvelle table temporaire est créée, les données sont déplacées vers la table temporaire, l'ancienne table est abandonnée et la nouvelle table est renommée.
utilisez Studio de gestion pour faire le changement et puis clic droit dans le concepteur et sélectionnez "Générer Script de changement".
vous verrez que C'est ce que fait SQL server en arrière-plan.
vous ne pouvez pas le faire comme cela, vous devez ajouter une autre colonne, la chute de la colonne d'origine et de renommer la nouvelle colonne ou ou créer un nouveau tableau, copier les données et la chute de l'ancien tableau suivi de renommer la nouvelle table à l'ancienne table
si vous utilisez SSMS et définissez la propriété identity à ON dans le designer, voici ce que SQL Server fait en coulisse. Donc, si vous avez une table nommée [user] c'est ce qui se passe si vous faites UserID et identity
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
SET ARITHABORT ON
SET NUMERIC_ROUNDABORT OFF
SET CONCAT_NULL_YIELDS_NULL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION
GO
GO
CREATE TABLE dbo.Tmp_User
(
UserID int NOT NULL IDENTITY (1, 1),
LastName varchar(50) NOT NULL,
FirstName varchar(50) NOT NULL,
MiddleInitial char(1) NULL
) ON [PRIMARY]
GO
SET IDENTITY_INSERT dbo.Tmp_User ON
GO
IF EXISTS(SELECT * FROM dbo.[User])
EXEC('INSERT INTO dbo.Tmp_User (UserID, LastName, FirstName, MiddleInitial)
SELECT UserID, LastName, FirstName, MiddleInitialFROM dbo.[User] TABLOCKX')
GO
SET IDENTITY_INSERT dbo.Tmp_User OFF
GO
GO
DROP TABLE dbo.[User]
GO
EXECUTE sp_rename N'dbo.Tmp_User', N'User', 'OBJECT'
GO
ALTER TABLE dbo.[User] ADD CONSTRAINT
PK_User PRIMARY KEY CLUSTERED
(
UserID
) ON [PRIMARY]
GO
COMMIT
ayant dit qu'il y a un moyen de hacker la table système pour l'accomplir en mettant la valeur bitwise mais qui n'est pas supporté et je ne le ferais pas
la réponse acceptée est fausse: vous pouvez modifier une colonne existante pour qu'elle soit une identité aussi longtemps que elle ne contient aucune valeur nulle. Après la modification, la graine d'identité commencera à la valeur max(colonne) + 1.
donc ce que vous devez vraiment faire en premier, est de fournir des valeurs pour tous les nulls.
comme j'ai compris dans les cas normaux nous créons un tableau avec clé primaire qui a propriété D'identité
Ainsi renommer ou Supprimer une colonne qui est associée à clé primaire contrainte ne sera pas possible parce que les règles de contrainte valident la structure de colonne.
Pour atteindre cela, nous devons traiter certaines étapes de la manière suivante:
Supposons TableName = "Employé" et ColumnName = 'Employé'
1. Ajouter une nouvelle colonne "EmployeeId_new" dans le tableau "Employee"
ALTER TABLE Employee ADD EmployeeId_new INT IDENTITY (1,1)
-
maintenant supprimer colonne "ID D'employé" du tableau "employé"
ALTER TABLE Employee DROP COLUMN EmployeeId -
Cela permettra de jeter de l'erreur à cause de la Contrainte de Clé Primaire sont soumis à des règles et de la validation de structure de colonne.
*### ' Msg 5074, Niveau 16, État 1, Ligne 1 L'objet [PK_dbo.L'employé] dépend de colmn [EmployeeId]." ### -
nous devons donc supprimer la contrainte principale de la table "employé", puis nous pouvons supprimer la colonne
ALTER TABLE Employee DROP constraint [PK_dbo.Employé] -
maintenant, nous pouvons supprimer la colonne "EmployeeId" de la table "employé" comme dans l'étape précédente où nous avons eu erreur
ALTER TABLE Colonne Employee DROP Employee ID -
Now colonne" EmployeeId " supprimé du tableau Nous allons donc renommer la nouvelle colonne 'EmployeeId_new' avec 'EmployeeId'
sp_rename 'Employee.Employé', 'EmployeeId_new', 'COLONNE' -
pour réorganiser le tableau dans la même forme qu'il était, nous devons ajouter la contrainte principale clé pour la colonne "Employee aid"
ALTER table Employee add constraint [PK_dbo.Clé primaire (EmployeeId)
8. maintenant le tableau "Employee" avec "EmployeeId" est modifié pour les règles D'identité avec la contrainte principale existante
il n'y en a pas, malheureusement; la propriété D'identité appartient à la table plutôt que la colonne.
la manière la plus facile est de le faire dans L'interface graphique, mais si ce n'est pas une option, vous pouvez faire le tour complet en copiant les données, en laissant tomber la colonne, en l'ajoutant de nouveau avec l'identité, et en remettant les données.
Voir ici pour un coup-par-coup compte.
clic droit sur le nom de la table dans L'Explorateur D'objets. Vous aurez quelques options. Cliquez sur "Design". Un nouvel onglet est ouvert pour cette table. Vous pouvez ajouter une contrainte D'identité ici dans'Propriétés de la colonne'.
pour modifier les propriétés d'identité d'une colonne:
- dans L'Explorateur de serveur, faites un clic droit sur la table avec les propriétés d'identité que vous voulez modifier et cliquez sur Ouvrir La définition de la Table. La table s'ouvre sur Table Designer.
- effacer la case à cocher Autoriser nulls pour la colonne que vous voulez changer.
- dans L'onglet Propriétés de la colonne, étendre la propriété Spécification D'identité.
- cliquez sur la case de la grille l'identité est la propriété de l'enfant et choisissez Oui dans la liste déroulante.
- Type A valeur dans la cellule D'identité. Cette valeur sera attribuée à la première ligne du tableau. La valeur 1 sera attribuée par défaut.
c'est cela, et cela a fonctionné pour moi
si l'affiche originale voulait en fait mettre une colonne existante pour être une PRIMARY KEY
pour la table et n'avait pas besoin que la colonne soit une IDENTITY
colonne (deux choses différentes) alors cela peut être fait via t-SQL avec:
ALTER TABLE [YourTableName]
ADD CONSTRAINT [ColumnToSetAsPrimaryKey] PRIMARY KEY ([ColumnToSetAsPrimaryKey])
notez la parenthèse autour du nom de la colonne après l'option PRIMARY KEY
.
bien que ce poste est vieux et je fais une hypothèse sur les besoins des demandeurs, je me suis senti ce supplémentaire l'information pourrait être utile pour les utilisateurs rencontrant ce fil que je crois que la conversation pourrait conduire à croire qu'une colonne existante ne peut pas être configuré pour être une clé primaire sans l'ajout d'une nouvelle colonne qui serait incorrect.
selon mon état actuel, je suis cette approche. Je veux donner l'identité à une table primaire après les données insérées par script.
comme je veux ajouter l'identité, donc il commence toujours de 1 à fin de Compte d'enregistrement que je veux.
--first drop column and add with identity
ALTER TABLE dbo.tblProductPriceList drop column ID
ALTER TABLE dbo.tblProductPriceList add ID INT IDENTITY(1,1)
--then add primary key to that column (exist option you can ignore)
IF NOT EXISTS (SELECT * FROM sys.key_constraints WHERE object_id = OBJECT_ID(N'[dbo].[PK_tblProductPriceList]') AND parent_object_id = OBJECT_ID(N'[dbo].[tblProductPriceList]'))
ALTER TABLE [tblProductPriceList] ADD PRIMARY KEY (id)
GO
cela créera la même colonne clé primaire avec identité
j'ai utilisé ces liens: https://blog.sqlauthority.com/2014/10/11/sql-server-add-auto-incremental-identity-column-to-table-after-creating-table /
Je ne crois pas qu'on puisse modifier une colonne existante pour qu'elle soit une colonne d'identité à l'aide de tsql. Cependant, vous pouvez le faire par l'Entreprise Gestionnaire de la vue de conception.
vous pouvez aussi créer une nouvelle ligne comme colonne identité, laisser tomber l'ancienne colonne, puis renommer votre nouvelle colonne.
ALTER TABLE FooTable
ADD BarColumn INT IDENTITY(1, 1)
NOT NULL
PRIMARY KEY CLUSTERED
fondamentalement, il y a quatre étapes logiques.
-
créer une nouvelle colonne identité. Allumez Insérer Identité de cette nouvelle colonne.
-
inscrire les données de la colonne source (la colonne que vous vouliez convertir en identité) dans cette nouvelle colonne.
-
désactiver L'indication de la nouvelle colonne.
-
Drop votre colonne source et renommez la nouvelle colonne par le nom de la colonne source.
il peut y avoir d'autres complexités comme travailler sur plusieurs serveurs, etc.
, Veuillez consulter l'article suivant pour les étapes (à l'aide de ssms et T-sql). Ces étapes sont destinées aux débutants avec moins de prise sur T-SQL.
génère un script pour toutes les tables avec la clé primaire = bigint qui n'ont pas de jeu d'identité; ceci retournera une liste des scripts générés avec chaque table;
SET NOCOUNT ON;
declare @sql table(s varchar(max), id int identity)
DECLARE @table_name nvarchar(max),
@table_schema nvarchar(max);
DECLARE vendor_cursor CURSOR FOR
SELECT
t.name, s.name
FROM sys.schemas AS s
INNER JOIN sys.tables AS t
ON s.[schema_id] = t.[schema_id]
WHERE EXISTS (
SELECT
[c].[name]
from sys.columns [c]
join sys.types [y] on [y].system_type_id = [c].system_type_id
where [c].[object_id] = [t].[object_id] and [y].name = 'bigint' and [c].[column_id] = 1
) and NOT EXISTS
(
SELECT 1 FROM sys.identity_columns
WHERE [object_id] = t.[object_id]
) and exists (
select 1 from sys.indexes as [i]
inner join sys.index_columns as [ic] ON i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
where object_name([ic].[object_id]) = [t].[name]
)
OPEN vendor_cursor
FETCH NEXT FROM vendor_cursor
INTO @table_name, @table_schema
WHILE @@FETCH_STATUS = 0
BEGIN
DELETE FROM @sql
declare @pkname varchar(100),
@pkcol nvarchar(100)
SELECT top 1
@pkname = i.name,
@pkcol = COL_NAME(ic.OBJECT_ID,ic.column_id)
FROM sys.indexes AS [i]
INNER JOIN sys.index_columns AS [ic] ON i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
WHERE i.is_primary_key = 1 and OBJECT_NAME(ic.OBJECT_ID) = @table_name
declare @q nvarchar(max) = 'SELECT '+@pkcol+' FROM ['+@table_schema+'].['+@table_name+'] ORDER BY '+@pkcol+' DESC'
DECLARE @ident_seed nvarchar(max) -- Change this to the datatype that you are after
SET @q = REPLACE(@q, 'SELECT', 'SELECT TOP 1 @output = ')
EXEC sp_executeSql @q, N'@output bigint OUTPUT', @ident_seed OUTPUT
insert into @sql(s) values ('BEGIN TRANSACTION')
insert into @sql(s) values ('BEGIN TRY')
-- create statement
insert into @sql(s) values ('create table ['+@table_schema+'].[' + @table_name + '_Temp] (')
-- column list
insert into @sql(s)
select
' ['+[c].[name]+'] ' +
y.name +
(case when [y].[name] like '%varchar' then
coalesce('('+(case when ([c].[max_length] < 0 or [c].[max_length] >= 1024) then 'max' else cast([c].max_length as varchar) end)+')','')
else '' end)
+ ' ' +
case when [c].name = @pkcol then 'IDENTITY(' +COALESCE(@ident_seed, '1')+',1)' else '' end + ' ' +
( case when c.is_nullable = 0 then 'NOT ' else '' end ) + 'NULL ' +
coalesce('DEFAULT ('+(
REPLACE(
REPLACE(
LTrim(
RTrim(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
LTrim(
RTrim(
REPLACE(
REPLACE(
object_definition([c].default_object_id)
,' ','~')
,')',' ')
)
)
,' ','*')
,'~',' ')
,' ','~')
,'(',' ')
)
)
,' ','*')
,'~',' ')
) +
case when object_definition([c].default_object_id) like '%get%date%' then '()' else '' end
+
')','') + ','
from sys.columns c
JOIN sys.types y ON y.system_type_id = c.system_type_id
where OBJECT_NAME(c.[object_id]) = @table_name and [y].name != 'sysname'
order by [c].column_id
update @sql set s=left(s,len(s)-1) where id=@@identity
-- closing bracket
insert into @sql(s) values( ')' )
insert into @sql(s) values( 'SET IDENTITY_INSERT ['+@table_schema+'].['+@table_name+'_Temp] ON')
declare @cols nvarchar(max)
SELECT @cols = STUFF(
(
select ',['+c.name+']'
from sys.columns c
JOIN sys.types y ON y.system_type_id = c.system_type_id
where c.[object_id] = OBJECT_ID(@table_name)
and [y].name != 'sysname'
and [y].name != 'timestamp'
order by [c].column_id
FOR XML PATH ('')
)
, 1, 1, '')
insert into @sql(s) values( 'IF EXISTS(SELECT * FROM ['+@table_schema+'].['+@table_name+'])')
insert into @sql(s) values( 'EXEC(''INSERT INTO ['+@table_schema+'].['+@table_name+'_Temp] ('+@cols+')')
insert into @sql(s) values( 'SELECT '+@cols+' FROM ['+@table_schema+'].['+@table_name+']'')')
insert into @sql(s) values( 'SET IDENTITY_INSERT ['+@table_schema+'].['+@table_name+'_Temp] OFF')
insert into @sql(s) values( 'DROP TABLE ['+@table_schema+'].['+@table_name+']')
insert into @sql(s) values( 'EXECUTE sp_rename N''['+@table_schema+'].['+@table_name+'_Temp]'', N'''+@table_name+''', ''OBJECT''')
if ( @pkname is not null ) begin
insert into @sql(s) values('ALTER TABLE ['+@table_schema+'].['+@table_name+'] ADD CONSTRAINT ['+@pkname+'] PRIMARY KEY CLUSTERED (')
insert into @sql(s)
select ' ['+COLUMN_NAME+'] ASC,' from information_schema.key_column_usage
where constraint_name = @pkname
GROUP BY COLUMN_NAME, ordinal_position
order by ordinal_position
-- remove trailing comma
update @sql set s=left(s,len(s)-1) where id=@@identity
insert into @sql(s) values (' )')
end
insert into @sql(s) values ('--Run your Statements')
insert into @sql(s) values ('COMMIT TRANSACTION')
insert into @sql(s) values ('END TRY')
insert into @sql(s) values ('BEGIN CATCH')
insert into @sql(s) values (' ROLLBACK TRANSACTION')
insert into @sql(s) values (' DECLARE @Msg NVARCHAR(MAX) ')
insert into @sql(s) values (' SELECT @Msg=ERROR_MESSAGE() ')
insert into @sql(s) values (' RAISERROR(''Error Occured: %s'', 20, 101,@msg) WITH LOG')
insert into @sql(s) values ('END CATCH')
declare @fqry nvarchar(max)
-- result!
SELECT @fqry = (select char(10) + s from @sql order by id FOR XML PATH (''))
SELECT @table_name as [Table_Name], @fqry as [Generated_Query]
PRINT 'Table: '+@table_name
EXEC sp_executeSql @fqry
FETCH NEXT FROM vendor_cursor
INTO @table_name, @table_schema
END
CLOSE vendor_cursor;
DEALLOCATE vendor_cursor;