Est-il possible de mettre à jour une valeur de colonne de clé primaire en cascadant la mise à jour parmi toutes les clés étrangères qui y font référence?
# EDIT 1: Lorsque j'exécute la requête followinq
select * from sys.foreign_keys where referenced_object_id=OBJECT_ID('myTable')
, Je vois que update_referential_action est mis à 0. Ainsi, AUCUNE ACTION n'est prise après la mise à jour de mes colonnes de clés primaires. Comment puis-je mettre à jour les clés étrangères pour les rendre À LA MISE À JOUR EN CASCADE ?
# EDIT 2:
Afin de créer un script pour la création ou la suppression de toutes les clés étrangères dans votre schéma, exécutez le script suivant (tiré de ici )
DECLARE @schema_name sysname;
DECLARE @table_name sysname;
DECLARE @constraint_name sysname;
DECLARE @constraint_object_id int;
DECLARE @referenced_object_name sysname;
DECLARE @is_disabled bit;
DECLARE @is_not_for_replication bit;
DECLARE @is_not_trusted bit;
DECLARE @delete_referential_action tinyint;
DECLARE @update_referential_action tinyint;
DECLARE @tsql nvarchar(4000);
DECLARE @tsql2 nvarchar(4000);
DECLARE @fkCol sysname;
DECLARE @pkCol sysname;
DECLARE @col1 bit;
DECLARE @action char(6);
DECLARE @referenced_schema_name sysname;
DECLARE FKcursor CURSOR FOR
select OBJECT_SCHEMA_NAME(parent_object_id)
, OBJECT_NAME(parent_object_id), name, OBJECT_NAME(referenced_object_id)
, object_id
, is_disabled, is_not_for_replication, is_not_trusted
, delete_referential_action, update_referential_action, OBJECT_SCHEMA_NAME(referenced_object_id)
from sys.foreign_keys
order by 1,2;
OPEN FKcursor;
FETCH NEXT FROM FKcursor INTO @schema_name, @table_name, @constraint_name
, @referenced_object_name, @constraint_object_id
, @is_disabled, @is_not_for_replication, @is_not_trusted
, @delete_referential_action, @update_referential_action, @referenced_schema_name;
WHILE @@FETCH_STATUS = 0
BEGIN
IF @action <> 'CREATE'
SET @tsql = 'ALTER TABLE '
+ QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name)
+ ' DROP CONSTRAINT ' + QUOTENAME(@constraint_name) + ';';
ELSE
BEGIN
SET @tsql = 'ALTER TABLE '
+ QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name)
+ CASE @is_not_trusted
WHEN 0 THEN ' WITH CHECK '
ELSE ' WITH NOCHECK '
END
+ ' ADD CONSTRAINT ' + QUOTENAME(@constraint_name)
+ ' FOREIGN KEY (';
SET @tsql2 = '';
DECLARE ColumnCursor CURSOR FOR
select COL_NAME(fk.parent_object_id, fkc.parent_column_id)
, COL_NAME(fk.referenced_object_id, fkc.referenced_column_id)
from sys.foreign_keys fk
inner join sys.foreign_key_columns fkc
on fk.object_id = fkc.constraint_object_id
where fkc.constraint_object_id = @constraint_object_id
order by fkc.constraint_column_id;
OPEN ColumnCursor;
SET @col1 = 1;
FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol;
WHILE @@FETCH_STATUS = 0
BEGIN
IF (@col1 = 1)
SET @col1 = 0;
ELSE
BEGIN
SET @tsql = @tsql + ',';
SET @tsql2 = @tsql2 + ',';
END;
SET @tsql = @tsql + QUOTENAME(@fkCol);
SET @tsql2 = @tsql2 + QUOTENAME(@pkCol);
FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol;
END;
CLOSE ColumnCursor;
DEALLOCATE ColumnCursor;
SET @tsql = @tsql + ' ) REFERENCES ' + QUOTENAME(@referenced_schema_name) + '.' + QUOTENAME(@referenced_object_name)
+ ' (' + @tsql2 + ')';
SET @tsql = @tsql
+ ' ON UPDATE ' + CASE @update_referential_action
WHEN 0 THEN 'NO ACTION '
WHEN 1 THEN 'CASCADE '
WHEN 2 THEN 'SET NULL '
ELSE 'SET DEFAULT '
END
+ ' ON DELETE ' + CASE @delete_referential_action
WHEN 0 THEN 'NO ACTION '
WHEN 1 THEN 'CASCADE '
WHEN 2 THEN 'SET NULL '
ELSE 'SET DEFAULT '
END
+ CASE @is_not_for_replication
WHEN 1 THEN ' NOT FOR REPLICATION '
ELSE ''
END
+ ';';
END;
PRINT @tsql;
IF @action = 'CREATE'
BEGIN
SET @tsql = 'ALTER TABLE '
+ QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name)
+ CASE @is_disabled
WHEN 0 THEN ' CHECK '
ELSE ' NOCHECK '
END
+ 'CONSTRAINT ' + QUOTENAME(@constraint_name)
+ ';';
PRINT @tsql;
END;
FETCH NEXT FROM FKcursor INTO @schema_name, @table_name, @constraint_name
, @referenced_object_name, @constraint_object_id
, @is_disabled, @is_not_for_replication, @is_not_trusted
, @delete_referential_action, @update_referential_action, @referenced_schema_name;
END;
CLOSE FKcursor;
DEALLOCATE FKcursor;
Pour générer le script de clés étrangères DROP, modifiez la valeur @action pour qu'elle soit égale à "DROP" dans la clause de déclaration:
DECLARE @action char(6) = 'DROP';
Si vous avez défini les contraintes de clé étrangère comme ON UPDATE CASCADE
, la valeur de la clé primaire qui a été modifiée doit se répercuter sur toutes les clés étrangères avec cette contrainte.
Si vous n'avez pas le ON UPDATE CASCADE
contrainte, vous devrez alors créer des scripts pour terminer la mise à jour.
EDIT: Puisque vous n'avez pas le ON UPDATE CASCADE
contrainte, mais vous voulez que cela soit configuré, c'est un peu de travail. SQL Server ne prend pas en charge la modification des contraintes d'un nouveau paramètre.
Il est nécessaire de parcourir chaque table qui a une contrainte FK à la table PK. Pour chaque table avec le FK:
Cela prend un peu d'effort, mais entraînerait que votre contrainte soit correctement définie pour votre cas.
EDIT 2: Les informations dont vous avez besoin se trouvent dans sys.foreign_keys. Vous pouvez sélectionner dans ce tableau pour obtenir toutes les informations dont vous avez besoin.
Un article de John Paul Cook peut être trouvé ici:
Ce code supprimera et créera TOUTES les contraintes FK dans une base de données. Vous devriez pouvoir travailler à partir de cela pour effectuer uniquement les modifications souhaitées dans votre base de données.
Vous pouvez certainement. ON UPDATE CASCADE
est ce que vous recherchez.
Voici un petit guide pratique: http://sqlandme.com/2011/08/08/sql-server-how-to-cascade-updates-and-deletes-to-related-tables/
Fondamentalement, lorsque vous modifiez le PK, la cascade s'éteint et met à jour tous les FK qui le référencent. Cela peut être fait dans votre instruction CREATE
, comme si vous faisiez un CASCADE DELETE
Gardez un œil sur les choses lorsque vous faites cela car, si je comprends bien, CASCADE s'exécute en fait au niveau d'isolement SERIALIZABLE
(normalement, SQL s'exécute à READ COMMITTED
par défaut) dans les coulisses, alors surveillez les problèmes de blocage.
Des informations supplémentaires sur les niveaux d'isolement peuvent être trouvées dans cet article: http://msdn.Microsoft.com/en-us/library/ms173763.aspx
Définissez toutes les clés étrangères comme CASCADE UPDATE
Si vous ne l'avez pas fait, alors vous devrez
.. dans une transaction bien sûr et attention aux autres contraintes qui pourraient échouer