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 la référencent?
# EDIT 1: lorsque j'exécute une requête de suivi
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 (extrait d' 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';
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
CREATE
déclaration, comme si vous faisiez unCASCADE 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écuteREAD COMMITTED
par défaut) en arrière-plan, alors surveillez les problèmes de blocage.Des informations supplémentaires sur les niveaux d'isolement sont disponibles dans cet article: http://msdn.microsoft.com/en-us/library/ms173763.aspx
la source
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
la source