J'ai une colonne smalldatetime que j'ai besoin de modifier pour être une colonne datetime. C'est quelque chose qui fera partie d'un processus d'installation, il ne peut donc pas être une procédure manuelle. Malheureusement, la colonne a quelques index et une contrainte non nulle dessus. Les index sont liés aux performances et doivent être conservés uniquement à l'aide du nouveau type de données. Est-il possible d'écrire une déclaration qui me permettra de conserver les informations pertinentes tout en modifiant le type de données de la colonne? Si cela est le cas, comment cela peut-il être fait?Préserver les index SQL lors de la modification du type de données de colonne
Répondre
Vous ne pouvez pas modifier le type de données smalldatetime datetime avec les index, les contraintes uniques, les clés étrangères ou les contraintes de vérification en place. Vous devrez les laisser tomber avant de changer le type. Puis:
alter table T alter column TestDate datetime not null
Recréez ensuite les contraintes et les index qui s'appliquent toujours.
Quelques approches différentes pour générer la chute et crée:
1) Si vous avez donné des noms explicites à tous les index et les contraintes, votre installateur peut exécuter un script statique dans chaque environnement (dev, test, Pour générer ce script explicite, vous pouvez: a) Utiliser SSMS (ou avec SQL Server 2000, gestionnaire d'entreprise) pour créer un script pour les instructions create et drop. b) Travaillez à partir de votre référentiel de code source pour découvrir les noms et définitions des objets dépendants et assembler le script statique approprié. c) Essayez d'exécuter l'instruction alter. Voir ce qu'il échoue. Rechercher les définitions et écrire à la main la goutte et créer. (Personnellement, ce serait génial pour écrire la goutte, pas si bon à la création.2) Si vous n'avez pas donné de noms explicites à tous les index et contraintes, votre installateur devra interroger le dictionnaire de données pour les noms appropriés et utiliser le SQL dynamique pour exécuter les gouttes, dans le bon ordre, avant l'instruction alter column, puis crée, dans le bon ordre, après la colonne alter.
Cela sera plus simple si vous savez qu'il n'y a pas de contraintes, et seulement des index.
Il existe peut-être des outils ou des bibliothèques qui savent déjà comment procéder.
En outre, s'il s'agit d'une application empaquetée, vous ne pouvez pas être assuré que les DBA locaux n'ont pas ajouté d'index. REMARQUE: S'il existe une contrainte unique, il aura généré un index que vous ne pourrez pas supprimer avec DROP INDEX.
EDIT: Cela dépend de l'original et du type de données modifié. Si vous essayez de modifier une colonne de varchar en nvarchar, elle échouera. Considérant que, si vous modifiez la colonne de varchar (16) à varchar (32), il réussira.
--Disable Index
ALTER INDEX MyIndex ON MyTable DISABLE
GO
-- Change column datatype
--Enable Index
ALTER INDEX MyIndex ON MyTable REBUILD
GO
Si vous modifiez le type d'une colonne, tous les index utilisant cette colonne devront être reconstruits. Mais à moins que vous n'ayez d'énormes volumes de données (ou que vous les exécutiez 24 heures sur 24, 7 jours sur 7), la reconstruction des index n'est pas un gros problème. Juste planifier une fenêtre de maintenance.
Ce qui irait bien, je suppose, pour Phillip, tant qu'ils restent et reconstruit automatiquement en utilisant le nouveau Type de données. – Thilo
Lorsque je tente et exécuter ALTER INDEX [MYIndex] sur [MyTable] DISABLE je reçois l'erreur « syntaxe incorrecte près du mot-clé « INDEX ». Me manque quelque chose? Je –
Depuis de poster ce commentaire que j'ai trouvé que SQL Server 2000 ne vous permet pas de désactiver un index.Il doit être supprimé et créé.Nous avons quelques serveurs qui sont encore sur SQL Server 2000. Donc la commande de désactivation ne fonctionnera pas pour moi –
Si vous modifiez simplement la taille, l'index restera sur la table.
Si vous modifiez le type de données, un message d'erreur s'affiche indiquant que les objets dépendent de la colonne que vous essayez de modifier et que vous ne pourrez donc pas la modifier.
Vous pouvez écrire les index en question manuellement ou via un script. Dans SSMS, cliquez avec le bouton droit sur la table et écrivez l'objet en question.
Si vous voulez un script d'indexation programmatique, voici un proc stocké que j'ai utilisé avec un de mes anciens collègues.
Drop Proc ScriptIndex
GO
Create Proc ScriptIndex
@TableName VarChar (Max),
@IndexScript VarChar (Max) OUTPUT
AS
-- Get all existing indexes, EXCEPT the primary keys
DECLARE cIX CURSOR FOR
SELECT OBJECT_NAME(SI.Object_ID), SI.Object_ID, SI.Name, SI.Index_ID
FROM Sys.Indexes SI
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TC
ON SI.Name = TC.CONSTRAINT_NAME
AND OBJECT_NAME(SI.Object_ID) = TC.TABLE_NAME
WHERE 1=1
AND OBJECT_NAME(SI.Object_ID) = @TableName
AND TC.CONSTRAINT_NAME IS NULL
AND OBJECTPROPERTY(SI.Object_ID, 'IsUserTable') = 1
ORDER BY OBJECT_NAME(SI.Object_ID), SI.Index_ID
DECLARE @IxTable SYSNAME
DECLARE @IxTableID INT
DECLARE @IxName SYSNAME
DECLARE @IxID INT
-- Loop through all indexes
OPEN cIX
FETCH NEXT FROM cIX INTO @IxTable, @IxTableID, @IxName, @IxID
WHILE (@@FETCH_STATUS = 0)
BEGIN
DECLARE @IXSQL NVARCHAR(4000)
DECLARE @PKSQL NVARCHAR(4000)
SET @PKSQL = ''
SET @IXSQL = 'CREATE '
-- Check if the index is unique
IF (INDEXPROPERTY(@IxTableID, @IxName, 'IsUnique') = 1)
SET @IXSQL = @IXSQL + 'UNIQUE '
-- Check if the index is clustered
IF (INDEXPROPERTY(@IxTableID, @IxName, 'IsClustered') = 1)
SET @IXSQL = @IXSQL + 'CLUSTERED '
SET @IXSQL = @IXSQL + 'INDEX ' + @IxName + ' ON ' + @IxTable + '('
-- Get all columns of the index
DECLARE cIxColumn CURSOR FOR
SELECT SC.Name
FROM Sys.Index_Columns IC
JOIN Sys.Columns SC ON IC.Object_ID = SC.Object_ID AND IC.Column_ID = SC.Column_ID
WHERE IC.Object_ID = @IxTableID AND Index_ID = @IxID
ORDER BY IC.Index_Column_ID
DECLARE @IxColumn SYSNAME
DECLARE @IxFirstColumn BIT SET @IxFirstColumn = 1
-- Loop throug all columns of the index and append them to the CREATE statement
OPEN cIxColumn
FETCH NEXT FROM cIxColumn INTO @IxColumn
WHILE (@@FETCH_STATUS = 0)
BEGIN
IF (@IxFirstColumn = 1)
SET @IxFirstColumn = 0
ELSE
SET @IXSQL = @IXSQL + ', '
SET @IXSQL = @IXSQL + @IxColumn
FETCH NEXT FROM cIxColumn INTO @IxColumn
END
CLOSE cIxColumn
DEALLOCATE cIxColumn
SET @IXSQL = @IXSQL + ')'
-- Print out the CREATE statement for the index
PRINT @IXSQL
FETCH NEXT FROM cIX INTO @IxTable, @IxTableID, @IxName, @IxID
END
CLOSE cIX
DEALLOCATE cIX
GO
Declare @TableName VarChar (Max), @IndexScript VarChar (Max)
Exec ScriptIndex 'Client', @IndexScript OUTPUT
Print @IndexScript
Ceci est très utile SP, mais il ne fait pas de distinction entre les colonnes dans l'index et les colonnes incluses et menace ainsi toutes les colonnes comme étant les mêmes. –
La meilleure chose à faire est de créer une procédure qui retourne le script d'index d'une table/colonne donnée. Vous pouvez donc supprimer les index seulement de la colonne en cours de modification et pas tous les index de la table, tandis que la création d'index peut être un peu coûteuse.
- stocke le résultat de la procédure dans un datatable
- Supprimer les indices de la colonne
- Modifier votre colonne
Reconstruire les index stockés dans datatable
-- objective : Generates indices scripting using specified column -- Parameters : -- @Tabela -> Name of the table that the column belongs to -- @Coluna -> Name of the column that will be searched for the indices to generate the script --Use: proc_ScriptIndexColumn 'TableName', 'CollumnName' SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO Create Proc proc_ScriptIndexColumn (@Tabela VARCHAR(4000), @Coluna VARCHAR(4000)) AS BEGIN DECLARE @isql_key VARCHAR(4000), @isql_incl VARCHAR(4000), @tableid INT, @indexid INT DECLARE @tablename VARCHAR(4000), @indexname VARCHAR(4000) DECLARE @isunique INT, @isclustered INT, @indexfillfactor INT DECLARE @srsql VARCHAR(MAX) DECLARE @ScriptsRetorno TABLE (Script VARCHAR(MAX)) DECLARE index_cursor CURSOR FOR SELECT tablename = OBJECT_NAME(i.[object_id]), tableid = i.[object_id], indexid = i.index_id, indexname = i.name, isunique = i.is_unique, CASE I.type_desc WHEN 'CLUSTERED' THEN 1 ELSE 0 END AS isclustered, indexfillfactor = i.fill_factor FROM sys.indexes AS i INNER JOIN SYSOBJECTS AS O ON I.[object_id] = O.ID INNER JOIN sys.index_columns AS ic ON (ic.column_id > 0 AND (ic.key_ordinal > 0 OR ic.partition_ordinal = 0 OR ic.is_included_column != 0 )) AND ( ic.index_id = CAST(i.index_id AS INT) AND ic.object_id = i.[object_id] ) INNER JOIN sys.columns AS sc ON sc.object_id = ic.object_id AND sc.column_id = ic.column_id WHERE O.XTYPE = 'U' AND i.typE = 2 /*Non clustered*/ AND i.is_unique = 0 AND i.is_hypothetical = 0 AND UPPER(OBJECT_NAME(i.[object_id])) = UPPER(@Tabela) AND UPPER(sc.name) = UPPER(@Coluna) OPEN index_cursor FETCH NEXT FROM index_cursor INTO @tablename,@tableid, @indexid,@indexname , @isunique ,@isclustered , @indexfillfactor WHILE @@fetch_status <> -1 BEGIN SELECT @isql_key = '', @isql_incl = '' SELECT @isql_key = CASE ic.is_included_column WHEN 0 THEN CASE ic.is_descending_key WHEN 1 THEN @isql_key +COALESCE(sc.name, '') + ' DESC, ' ELSE @isql_key + COALESCE(sc.name, '') + ' ASC, ' END ELSE @isql_key END, --include column @isql_incl = CASE ic.is_included_column WHEN 1 THEN CASE ic.is_descending_key WHEN 1 THEN @isql_incl + COALESCE(sc.name, '') + ', ' ELSE @isql_incl + COALESCE(sc.name, '') + ', ' END ELSE @isql_incl END FROM sysindexes i INNER JOIN sys.index_columns AS ic ON ( ic.column_id > 0 AND ( ic.key_ordinal > 0 OR ic.partition_ordinal = 0 OR ic.is_included_column != 0 ) ) AND (ic.index_id = CAST(i.indid AS INT) AND ic.object_id = i.id) INNER JOIN sys.columns AS sc ON sc.object_id = ic.object_id AND sc.column_id = ic.column_id WHERE i.indid > 0 AND i.indid < 255 AND (i.status & 64) = 0 AND i.id = @tableid AND i.indid = @indexid ORDER BY i.name, CASE ic.is_included_column WHEN 1 THEN ic.index_column_id ELSE ic.key_ordinal END IF LEN(@isql_key) > 1 SET @isql_key = LEFT(@isql_key, LEN(@isql_key) -1) IF LEN(@isql_incl) > 1 SET @isql_incl = LEFT(@isql_incl, LEN(@isql_incl) -1) SET @srsql = 'CREATE ' + 'INDEX [' + @indexname + ']' + ' ON [' + @tablename + '] ' SET @srsql = @srsql + '(' + @isql_key + ')' IF (@isql_incl <> '') SET @srsql = @srsql + ' INCLUDE(' + @isql_incl + ')' IF (@indexfillfactor <> 0) SET @srsql = @srsql + ' WITH (FILLFACTOR = ' + CONVERT(VARCHAR(10), @indexfillfactor) + ')' FETCH NEXT FROM index_cursor INTO @tablename,@tableid,@indexid,@indexname, @isunique ,@isclustered , @indexfillfactor INSERT INTO @ScriptsRetorno VALUES (@srsql) END CLOSE index_cursor DEALLOCATE index_cursor SELECT * FROM @ScriptsRetorno RETURN @@ERROR END
- 1. SQL - Informix - Modification du type de données d'une colonne de numérique à caractère
- 2. colonne Alter type de données dans SQL
- 3. Définition du type de données lors de la lecture de données XML dans SAS
- 4. Préserver le type de contenu lors de la publication d'un fichier de l'iPhone vers Rails
- 5. Modification du nom de colonne dans SQL Server 2000
- 6. Comment ajouter une valeur de colonne constante lors du transfert de données de CSV vers SQL?
- 7. Comment préserver la valeur de la colonne gridview dynamique créée
- 8. Préserver la hiérarchie lors de la conversion du fichier .csv en xml ou json
- 9. Colonne DataTable avec type de données personnalisé
- 10. Modification du type de contenu Page ENTRÉE?
- 11. Préserver le Java-type d'un objet lors du passage de Java à Jython
- 12. Index SQL sur la colonne de la clé de la liste NHibernate?
- 13. Largeur de colonne GridView Modification
- 14. Modification du type de données de tables de varchar au texte postgressql
- 15. Utilisation correcte du type de données XML dans SQL Server?
- 16. Modification de la base de données SQL sur l'hébergement partagé
- 17. Gridview Modification de la largeur de la colonne
- 18. Longueur maximum de MIMEType lors du stockage du type dans la base de données
- 19. ORM et index de base de données
- 20. Préserver les anciennes données modifiées par l'utilisateur
- 21. Comment modifier le type de données de colonne sans affecter la largeur de colonne existante
- 22. Mappage de type de données
- 23. SQL Quand utiliser quel type de données
- 24. SQL Server 2005: Détermination du type de données de la variable
- 25. Modification du type de champ dans un Django ModelFormset
- 26. Utilisation du type de données XML SQL Server
- 27. Ajout de données au sous-réseau jqgrid lors de l'utilisation du type de données clientSide
- 28. Modifier en toute sécurité le type de données d'une colonne répliquée dans SQL Server 2005?
- 29. SQL SELECT FROM ... AS avec spécificateur de type de données?
- 30. Sql Type de données pour la clé primaire - SQL Server?
J'ai été capable de trouver la source sql derrière la création des index et j'ai pu les utiliser pour les supprimer avant de changer le type. En ce qui concerne la contrainte, j'ai trouvé une requête via google qui peut être utilisée pour déterminer le nom de la contrainte générée aléatoirement. –
déclarer @constraintName comme nvarchar (100) déclarer @sql nvarchar (1000) \t select @constraintName = O.name \t de sysobjects AS O \t jointure gauche sysobjects AS T \t \t sur O.parent_obj = T. id \t où est nul (objectproperty (O.id, 'IsMSShipped'), 1) = 0 \t \t et O.nom pas comme '% dtproper%' \t \t et O.name pas comme 'dt [_]%' \t \t et T.name = 'MyTable' \t \t et O.name comme 'DF__MyTabl__MyCol%' \t sinon @constraintName est nulle \t commencent \t \t select @sql = 'ALTER TABLE [MyTable] DROP CONSTRAINT [' + @constraintName + ']' \t \t execute sp_executesql @sql \t fin –