Если у вас есть уникальное ограничение на n_id, field
, что означает, что может соответствовать не более одной строки, вы можете (по крайней мере в теории) использовать триггер INSTEAD OF
.
Это было бы проще с MERGE
(но это не доступно до SQL Server 2008), так как вам нужно охватить UPDATES
существующих данных, INSERTS
(где значение NULL
установлено на NON NULL
один) и DELETES
, где значение NON NULL
установлено на NULL
.
Одна вещь, которую вы должны рассмотреть здесь, - это как справиться с UPDATES
, который устанавливает все столбцы в строке на NULL
Я делал это во время тестирования приведенного ниже кода и был довольно смущен в течение минуты или двух Я понял, что это удалило все строки в базовой таблице для n_id
(что означало, что операция не была обратимой через другой оператор UPDATE
). Эту проблему можно избежать, если иметь определение VIEW OUTER JOIN
для любой таблицы n_id
, представляющей собой PK.
Пример типа вещи приведен ниже. Вам также необходимо учитывать потенциальные условия гонки в указанном коде INSERT
/ DELETE
и знать, нужны ли там дополнительные подсказки о блокировке.
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