Ervan uitgaande dat u een unieke beperking heeft op n_id, field
wat betekent dat er maximaal één rij kan overeenkomen, kun je (in theorie tenminste) een INSTEAD OF
gebruiken trekker.
Dit zou gemakkelijker zijn met MERGE
(maar dat is niet beschikbaar tot SQL Server 2008) omdat u UPDATES
moet behandelen van bestaande gegevens, INSERTS
(Waar een NULL
waarde is ingesteld op NON NULL
one) en DELETES
waarbij een NON NULL
waarde is ingesteld op NULL
.
Een ding dat u hier zou moeten overwegen, is hoe u omgaat met UPDATES
die alle kolommen op een rij instelt op NULL
Ik deed dit tijdens het testen van de onderstaande code en was een minuut of twee behoorlijk in de war totdat ik me realiseerde dat dit alle rijen in de basistabel voor een n_id
had verwijderd (wat betekende dat de operatie niet omkeerbaar was via een andere UPDATE
uitspraak). Dit probleem kan worden vermeden door de VIEW-definitie OUTER JOIN
. te gebruiken op welke tafel dan ook n_id
is de PK van.
Een voorbeeld van het soort ding staat hieronder. U moet ook rekening houden met mogelijke race-omstandigheden in de INSERT
/DELETE
code aangegeven en of je daar wat extra vergrendelingstips nodig hebt.
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