Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Le tableau croisé dynamique SQL est en lecture seule et les cellules ne peuvent pas être modifiées ?

En supposant que vous ayez une contrainte unique sur n_id, field ce qui signifie qu'au plus une ligne peut correspondre, vous pouvez (en théorie au moins) utiliser un INSTEAD OF gâchette.

Ce serait plus simple avec MERGE (mais cela n'est pas disponible avant SQL Server 2008) car vous devez couvrir les UPDATES de données existantes, INSERTS (Où un NULL la valeur est définie sur un NON NULL un) et DELETES où un NON NULL la valeur est définie sur NULL .

Une chose que vous devez considérer ici est de savoir comment gérer les UPDATES qui définit toutes les colonnes d'une ligne sur NULL Je l'ai fait pendant le test du code ci-dessous et j'ai été assez confus pendant une minute ou deux jusqu'à ce que je réalise que cela avait supprimé toutes les lignes de la table de base pour un n_id (ce qui signifiait que l'opération n'était pas réversible via une autre UPDATE déclaration). Ce problème pourrait être évité en ayant la définition VIEW OUTER JOIN sur n'importe quelle table n_id est le PK de.

Un exemple du type de chose est ci-dessous. Vous devrez également tenir compte des conditions de concurrence potentielles dans le INSERT /DELETE code indiqué et si vous avez besoin d'indications de verrouillage supplémentaires.

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