web-dev-qa-db-fra.com

Est-ce que une suppression puis insère dans une cascade de transaction?

J'ai eu une question sur le comportement attendu et réel pour le scénario suivant.

Le scénario est celui où une table de base de données ([table1]) est effacé et rechargé tous les jours. La table a une colonne id qui fait référence par plusieurs autres tables à l'aide de clés étrangères. Si je réglais la clé étrangère ON DELETE action à CASCADE, évidemment, cela supprimera des lignes dans les autres tables si je publie un seul DELETE FROM [table1] commande sur cette table. Cependant, ce qui se passerait si je devais supprimer toutes les lignes, puis réinsérez les mêmes lignes avec les mêmes identifiants sous la même transaction? Cela déclenchera-t-il la transaction intermédiaire de la cascade, ou le rapprochement de la clé étrangère se produira-t-il une fois que j'ai appelé commettre?

De toute évidence, je pense que SQL Server ici, mais je me demande si ce comportement est également cohérent entre autres DBS.

Dans le cas où la cascade est déclenchée même au milieu de la transaction, quelle serait la meilleure façon de gérer les clés et les relations étranger avec une table complètement effacée et rechargée tous les jours?

4
growse

Je connais seulement avec SQL Server:

Chaque opération est atomique. Si vous exécutez une suppression et que cela cascades à d'autres tables, ces enregistrements sont également partis, dès que la déclaration est terminée. Ils ne reviennent pas comme par magie à moins que la transaction ne soit renvoyée.

Si vous comptez sur les valeurs d'identité et que vous ne voulez pas cascader les tables correspondantes, envisagez de passer à une stratégie de fusion (où vous utilisez UPDATE ou, de préférence MERGE) au lieu de tout souffler loin et à partir de zéro.

Je suppose que vous pourriez essayer quelque chose comme invalidant les relations lors de la chargement de données, mais que je pense que vous essayez de faire, cela semble semé de péril. Essayez certainement une stratégie de fusion d'abord.

11
Jon Seigel

Non, ce ne sera pas. En cas de doute, testez-le:

create table Parent
(
    ParentId int identity(1, 1) not null primary key clustered,
    Data nvarchar(30) not null default 'some data here...',
    Num int not null
)
go

create table Child
(
    ChildId int identity(1, 1) not null,
    ParentId int not null foreign key references Parent(ParentId) on delete cascade
)
go

insert into Parent(Num)
values(15), (17), (23)
go

select *
from Parent

insert into Child(ParentId)
values(2), (3)
go

select *
from Child

begin tran
    delete from Parent
    where ParentId = 3

    set identity_insert Parent on
    insert into Parent(ParentId, Num)
    values(3, 64)
    set identity_insert Parent off
commit tran

(Vous devriez probablement passer à travers ce code au lieu d'une exécution d'une couverture). Puis en faisant un simple

select *
from Child

Vous verrez que la ligne contenant ParentId avec une valeur de 3 n'est plus dans la table. Donc la réponse est non. Ce ne sera pas encore disponible.

Maintenant, si vous deviez retourner la transaction qui a fait la suppression avec un on delete cascade, alors l'enregistrement serait toujours dans la table enfant. En visionnant sys.dm_tran_locks DMV, il y aura une serrure exclusive sur la table contenant la contrainte de clé étrangère.

Quant à d'autres RDBMS, je ne peux pas dire à coup sûr. Seul SQL Server.

4
Thomas Stringer