Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Tabela przestawna SQL jest tylko do odczytu i nie można edytować komórek?

Zakładając, że masz unikalne ograniczenie na n_id, field co oznacza, że ​​co najwyżej jeden wiersz może pasować, możesz (przynajmniej teoretycznie) użyć INSTEAD OF cyngiel.

Byłoby to łatwiejsze dzięki MERGE (ale to nie jest dostępne do SQL Server 2008), ponieważ musisz uwzględnić UPDATES istniejących danych, INSERTS (Gdzie NULL wartość jest ustawiona na NON NULL jeden) i DELETES gdzie NON NULL wartość jest ustawiona na NULL .

Jedną rzeczą, którą musisz wziąć pod uwagę, jest to, jak radzić sobie z UPDATES które ustawiają wszystkie kolumny w wierszu na NULL Zrobiłem to podczas testowania poniższego kodu i byłem dość zdezorientowany przez minutę lub dwie, dopóki nie zdałem sobie sprawy, że to usunęło wszystkie wiersze w tabeli bazowej dla n_id (co oznaczało, że operacja nie była odwracalna przez inną UPDATE oświadczenie). Tego problemu można uniknąć, stosując definicję VIEW OUTER JOIN na jakąkolwiek tabelę n_id jest PK.

Przykład tego typu rzeczy znajduje się poniżej. Musisz również wziąć pod uwagę potencjalne warunki wyścigu w INSERT /DELETE wskazany kod i czy potrzebujesz tam dodatkowych wskazówek dotyczących blokowania.

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Odejmij minutę od DateTime w SQL Server 2005

  2. Klasyczny ADO.NET — jak przekazać UDT do procedury składowanej?

  3. Dołączanie do tabeli na podstawie wartości oddzielonych przecinkami

  4. Dane hierarchiczne w Linq - opcje i wydajność

  5. Jak używać SignalR na farmie internetowej, używając serwera Sql jako płyty bazowej?