Förutsatt att du har en unik begränsning på n_id, field
vilket innebär att högst en rad kan matcha du kan (i teorin åtminstone) använda en INSTEAD OF
utlösare.
Detta skulle vara enklare med MERGE
(men det är inte tillgängligt förrän SQL Server 2008) eftersom du behöver täcka UPDATES
av befintliga data, INSERTS
(Där en NULL
värdet är satt till NON NULL
one) och DELETES
där en NON NULL
värdet är satt till NULL
.
En sak du skulle behöva tänka på här är hur du hanterar UPDATES
som ställer in alla kolumner i en rad till NULL
Jag gjorde detta när jag testade koden nedan och var ganska förvirrad i en minut eller två tills jag insåg att detta hade tagit bort alla rader i bastabellen för en n_id
(vilket innebar att operationen inte var reversibel via en annan UPDATE
påstående). Detta problem kan undvikas genom att ha VIEW-definitionen OUTER JOIN
på vilken som helst tabell n_id
är PK för.
Ett exempel på typen av sak är nedan. Du skulle också behöva överväga potentiella tävlingsförhållanden i INSERT
/DELETE
koden anges och om du behöver några ytterligare låstips där.
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