En supposant que vous ayez une contrainte unique sur n_id, field
ce qui signifie qu'au plus une ligne peut correspondre, vous pouvez (en théorie au moins) utiliser un INSTEAD OF
gâchette.
Ce serait plus simple avec MERGE
(mais cela n'est pas disponible avant SQL Server 2008) car vous devez couvrir les UPDATES
de données existantes, INSERTS
(Où un NULL
la valeur est définie sur un NON NULL
un) et DELETES
où un NON NULL
la valeur est définie sur NULL
.
Une chose que vous devez considérer ici est de savoir comment gérer les UPDATES
qui définit toutes les colonnes d'une ligne sur NULL
Je l'ai fait pendant le test du code ci-dessous et j'ai été assez confus pendant une minute ou deux jusqu'à ce que je réalise que cela avait supprimé toutes les lignes de la table de base pour un n_id
(ce qui signifiait que l'opération n'était pas réversible via une autre UPDATE
déclaration). Ce problème pourrait être évité en ayant la définition VIEW OUTER JOIN
sur n'importe quelle table n_id
est le PK de.
Un exemple du type de chose est ci-dessous. Vous devrez également tenir compte des conditions de concurrence potentielles dans le INSERT
/DELETE
code indiqué et si vous avez besoin d'indications de verrouillage supplémentaires.
CREATE TRIGGER trig
ON pivoted
INSTEAD OF UPDATE
AS
BEGIN
SET nocount ON;
DECLARE @unpivoted TABLE (
n_id INT,
field VARCHAR(10),
c_metadata_value VARCHAR(10))
INSERT INTO @unpivoted
SELECT *
FROM inserted UNPIVOT (data FOR col IN (fid, sid, NUMBER) ) AS unpvt
WHERE data IS NOT NULL
UPDATE m
SET m.c_metadata_value = u.c_metadata_value
FROM metadata m
JOIN @unpivoted u
ON u.n_id = m.n_id
AND u.c_metadata_value = m.field;
/*You need to consider race conditions below*/
DELETE FROM metadata
WHERE NOT EXISTS(SELECT *
FROM @unpivoted u
WHERE metadata.n_id = u.n_id
AND u.field = metadata.field)
INSERT INTO metadata
SELECT u.n_id,
u.field,
u.c_metadata_value
FROM @unpivoted u
WHERE NOT EXISTS (SELECT *
FROM metadata m
WHERE m.n_id = u.n_id
AND u.field = m.field)
END