Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

SQL-Pivot-Tabelle ist schreibgeschützt und Zellen können nicht bearbeitet werden?

Angenommen, Sie haben eine eindeutige Einschränkung für n_id, field was bedeutet, dass höchstens eine Zeile übereinstimmen kann, können Sie (zumindest theoretisch) einen INSTEAD OF verwenden Abzug.

Einfacher geht das mit MERGE (aber das ist bis SQL Server 2008 nicht verfügbar), da Sie UPDATES abdecken müssen vorhandener Daten, INSERTS (Wo ein NULL value wird auf NON NULL gesetzt eins) und DELETES wo ein NON NULL Wert wird auf NULL gesetzt .

Eine Sache, die Sie hier beachten sollten, ist der Umgang mit UPDATES die alle Spalten in einer Zeile auf NULL setzen Ich habe dies beim Testen des folgenden Codes getan und war ein oder zwei Minuten lang ziemlich verwirrt, bis mir klar wurde, dass dies alle Zeilen in der Basistabelle für einen n_id gelöscht hatte (was bedeutete, dass der Vorgang nicht über ein weiteres UPDATE rückgängig gemacht werden konnte Aussage). Dieses Problem könnte durch die VIEW-Definition OUTER JOIN vermieden werden auf eine beliebige Tabelle n_id ist die PK von.

Ein Beispiel für die Art der Sache ist unten. Sie müssten auch potenzielle Rennbedingungen im INSERT berücksichtigen /DELETE angezeigten Code und ob Sie dort zusätzliche Hinweise zum Sperren benötigen.

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