SQL pivoted表是只读的,单元格不能编辑?

时间:2011-02-16 02:33:24

标签: sql sql-server-2005

如果我使用此数据透视表查询创建VIEW,则无法编辑。单元格是只读的,并给我SQL2005错误:“没有更新行。第2行中的数据未提交。更新或插入视图或函数'VIEWNAME'失败,因为它包含派生或常量字段。”< / p>

关于如何解决这个问题的任何想法或者像这样的支点永远不可编辑?

SELECT     n_id,
MAX(CASE field WHEN 'fId' THEN c_metadata_value ELSE ' ' END) AS fId,
MAX(CASE field WHEN 'sID' THEN c_metadata_value ELSE ' ' END) AS sID,
MAX(CASE field WHEN 'NUMBER' THEN c_metadata_value ELSE ' ' END) AS NUMBER
FROM   metadata
GROUP BY n_id

2 个答案:

答案 0 :(得分:3)

假设您对n_id, field有一个唯一约束,这意味着最多只能匹配一行,您可以(理论上至少)使用INSTEAD OF触发器。

使用MERGE(但在SQL Server 2008之前无法使用)会更容易,因为您需要覆盖UPDATES现有数据INSERTS(其中NULL } value设置为NON NULL one)和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  

答案 1 :(得分:2)

您必须在视图上创建触发器,因为无法直接更新:

CREATE TRIGGER TrMyViewUpdate on MyView
INSTEAD OF UPDATE
AS
BEGIN
   SET NOCOUNT ON;
   UPDATE MyTable
   SET ...
   FROM INSERTED...
END