IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

Question pour remplacer le delete cascade


Sujet :

Développement SQL Server

  1. #1
    Membre confirmé Avatar de Monstros Velu
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2003
    Messages
    619
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 619
    Points : 601
    Points
    601
    Par défaut Question pour remplacer le delete cascade
    Bonjour,


    J'ai 2 tables (évidement, en vrai, j'ai plus de tables et c'est plus compliqué que ça) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    CREATE TABLE dbo.A
    (
    	IdA int NOT NULL IDENTITY PRIMARY KEY,
    	Lbl varchar(50) NOT NULL UNIQUE,
    	ValidFrom datetime2(7) GENERATED ALWAYS AS ROW START NOT NULL,
    	ValidTo datetime2(7) GENERATED ALWAYS AS ROW END NOT NULL,
    	PERIOD FOR SYSTEM_TIME ([ValidFrom], [ValidTo])
    )
    WITH
    (
     SYSTEM_VERSIONING = ON ( HISTORY_TABLE = dbo.A_TT )
    )
    GO
     
    CREATE TABLE dbo.B
    (
    	IdA int NOT NULL PRIMARY KEY FOREIGN KEY REFERENCES A(IdA),
    	IdReference int NOT NULL,
    	ValidFrom datetime2(7) GENERATED ALWAYS AS ROW START NOT NULL,
    	ValidTo datetime2(7) GENERATED ALWAYS AS ROW END NOT NULL,
    	PERIOD FOR SYSTEM_TIME ([ValidFrom], [ValidTo])
    )
    WITH
    (
     SYSTEM_VERSIONING = ON ( HISTORY_TABLE = dbo.B_TT )
    )
    GO
    Pour gérer les données de l'application, j'ai un type table qui sert comme paramètre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    CREATE TYPE UDT_MyType AS TABLE(
    	IdA int NOT NULL,
    	IdReference int NULL,
    	Lbl varchar(50)
    )
    GO
    pour la procédure stockée permet au client d'insérer/mettre à jour/supprimer les données, en 1 seul appel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
     
    CREATE OR ALTER PROC TR_B_Merge_DML
    @data UDT_MyType READONLY
    AS
    SET XACT_ABORT, NOCOUNT ON
    BEGIN TRY	
    BEGIN TRANSACTION
     
    -- Contrôles sur @data
     
    -- stockage temporaire modifiable
    	SELECT * INTO #data FROM @data
     
    	DECLARE @resultA AS TABLE(IdA int, Lbl varchar(50))
     
    -- merge dans A
    	MERGE INTO dbo.A AS b
    	USING (SELECT IdA, Lbl FROM #data) AS src
    		ON src.IdA = src.IdA
    	WHEN MATCHED AND EXISTS (SELECT src.IdA EXCEPT SELECT b.IdA) THEN
    		UPDATE SET IdA = src.IdA
    	WHEN NOT MATCHED THEN
    		INSERT(IdA, Lbl) VALUES(src.IdA, src.Lbl)
    	WHEN NOT MATCHED BY SOURCE THEN
    		DELETE
    	OUTPUT Inserted.IdA, inserted.LbL INTO @resultA;
     
    -- récupération des nouveaux IdA
    	UPDATE a
    	SET IdA = r.IdA
    	FROM #data AS a
    		INNER JOIN @resultA r
    			ON a.Lbl = r.Lbl
    	WHERE a.IdA IS NULL
     
    --utilisation de #a pour merge les infos dans B	
    -- ...	je vous passe ce détail	
     
    COMMIT TRANSACTION
    END TRY
    BEGIN CATCH
     
    	IF (XACT_STATE()) = -1  
        BEGIN
            ROLLBACK TRANSACTION;  
        END; 
     
    	THROW;
     
    END CATCH;
    GO
    Voici le problème :
    La foreign key B(IdA) qui référence A(IdA) empêche la suppression de lignes dans A.

    J'ai pensé au delete en cascade, mais toutes mes tables sont historisées (temporal tables), je ne peux donc pas l'utiliser (SQL Server 2016).
    Du coup, je vois 2 possibilités :
    1. Trigger : Je peux mettre un trigger sur A qui fera la suppression. Si le nombre de ligne supprimé n'est pas trop grand, c'est jouable.
      De plus, comme je supprime les données, ça ne peut pas être un "after delete", donc un "instead delete". Donc j'empêche la suppression des données pour les supprimer ensuite ? Pas joli tout ça...
    2. Merge différencié : Je fais un premier merge pour insert/update sur A. Puis je merge dans B. Puis je supprime dans A. Si le nombre de lignes dans A n'est pas trop grand, je peux me permettre 2 passes sur la table.

    Je n'ai pas d'idée de quelle est la meilleure solution. Ni s'il en existe un autre.

    Pouvez-vous me donner votre avis, s'il-vous-plait ?

  2. #2
    Membre confirmé Avatar de Monstros Velu
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2003
    Messages
    619
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 619
    Points : 601
    Points
    601
    Par défaut
    Je crois que j'ai partiellement résolu mon dilemme :
    "Impossible de créer un déclencheur sur une table temporelle avec version gérée par le système «*maDB.dbo.A*»."

Discussions similaires

  1. Réponses: 2
    Dernier message: 07/01/2010, 11h47
  2. [W3C] Question de débutant pour remplacement des frames
    Par Grizzzly dans le forum Balisage (X)HTML et validation W3C
    Réponses: 4
    Dernier message: 24/07/2009, 16h44
  3. Petite question pour Backup
    Par chicken92000 dans le forum Administration
    Réponses: 2
    Dernier message: 16/09/2004, 16h10
  4. [MIB] Questions pour construire une mib
    Par fadoua dans le forum Développement
    Réponses: 4
    Dernier message: 11/03/2004, 10h47
  5. Quel SGBD choisir pour remplacer Access ?
    Par ggl'Nouveau dans le forum Décisions SGBD
    Réponses: 11
    Dernier message: 17/11/2003, 10h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo