If I create a VIEW using this pivot table query, it isn\'t editable. The cells are read-only and give me the SQL2005 error: \"No row was updated. The data in row 2 was n
You'll have to create trigger on view, because direct update is not possible:
CREATE TRIGGER TrMyViewUpdate on MyView
INSTEAD OF UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE MyTable
SET ...
FROM INSERTED...
END
Assuming you have a unique constraint on n_id, field
which means that at most one row can match you can (in theory at least) use an INSTEAD OF
trigger.
This would be easier with MERGE
(but that is not available until SQL Server 2008) as you need to cover UPDATES
of existing data, INSERTS
(Where a NULL
value is set to a NON NULL
one) and DELETES
where a NON NULL
value is set to NULL
.
One thing you would need to consider here is how to cope with UPDATES
that set all of the columns in a row to NULL
I did this during testing the code below and was quite confused for a minute or two until I realised that this had deleted all the rows in the base table for an n_id
(which meant the operation was not reversible via another UPDATE
statement). This issue could be avoided by having the VIEW definition OUTER JOIN
onto what ever table n_id
is the PK of.
An example of the type of thing is below. You would also need to consider potential race conditions in the INSERT
/DELETE
code indicated and whether you need some additional locking hints in there.
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