开发者

SQL pivoted table is read-only and cells can't be edited?

开发者 https://www.devze.com 2023-02-10 22:42 出处:网络
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 not committed.Update or insert of v

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 not committed. Update or insert of view or function 'VIEWNAME' failed because it contains a derived or constant field."

Any ideas on how this could be solved OR is a pivot like this just never editable?

SELECT     n_id,
MAX(CASE field WHEN 'fId' THEN c_metadata_value ELSE ' ' END) AS fId,
MAX(CASE field WHEN 'sID' THEN c_metadata_val开发者_开发问答ue ELSE ' ' END) AS sID,
MAX(CASE field WHEN 'NUMBER' THEN c_metadata_value ELSE ' ' END) AS NUMBER
FROM   metadata
GROUP BY n_id


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  


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
0

精彩评论

暂无评论...
验证码 换一张
取 消