Zakładając, że masz unikalne ograniczenie na n_id, field
co oznacza, że co najwyżej jeden wiersz może pasować, możesz (przynajmniej teoretycznie) użyć INSTEAD OF
cyngiel.
Byłoby to łatwiejsze dzięki MERGE
(ale to nie jest dostępne do SQL Server 2008), ponieważ musisz uwzględnić UPDATES
istniejących danych, INSERTS
(Gdzie NULL
wartość jest ustawiona na NON NULL
jeden) i DELETES
gdzie NON NULL
wartość jest ustawiona na NULL
.
Jedną rzeczą, którą musisz wziąć pod uwagę, jest to, jak radzić sobie z UPDATES
które ustawiają wszystkie kolumny w wierszu na NULL
Zrobiłem to podczas testowania poniższego kodu i byłem dość zdezorientowany przez minutę lub dwie, dopóki nie zdałem sobie sprawy, że to usunęło wszystkie wiersze w tabeli bazowej dla n_id
(co oznaczało, że operacja nie była odwracalna przez inną UPDATE
oświadczenie). Tego problemu można uniknąć, stosując definicję VIEW OUTER JOIN
na jakąkolwiek tabelę n_id
jest PK.
Przykład tego typu rzeczy znajduje się poniżej. Musisz również wziąć pod uwagę potencjalne warunki wyścigu w INSERT
/DELETE
wskazany kod i czy potrzebujesz tam dodatkowych wskazówek dotyczących blokowania.
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