2009-10-25 5 views
5

Je modifie une base de données existante en développant un nouveau logiciel. Il y a aussi beaucoup de logiciels existants qui utilise la base de données qui doit continuer à travailler, à savoir que je voudrais maintenir les tables de base de données existants, procs, etc.AU LIEU DE LA MISE À JOUR Déclencher et mettre à jour la clé primaire

Actuellement, j'ai la table

 
CREATE TABLE dbo.t_station (
    tx_station_id  VARCHAR(4) NOT NULL, 
    tx_description  NVARCHAR(max) NOT NULL, 
    tx_station_type  CHAR(1)  NOT NULL, 
    tx_current_order_num VARCHAR(20) NOT NULL, 

    PRIMARY KEY (tx_station_id) 
) 

Je dois inclure un nouveau champ dans cette table qui fait référence à une installation (installation de production) et déplacer le tx_current_order_num dans une autre table car il n'est pas requis pour toutes les lignes. J'ai donc créé de nouvelles tables: -

 
CREATE TABLE Private.Plant (
    PlantCode INT   NOT NULL, 
    Description NVARCHAR(max) NOT NULL, 

    PRIMARY KEY (PlantCode) 
) 
CREATE TABLE Private.Station (
    StationId VARCHAR(4) NOT NULL, 
    Description NVARCHAR(max) NOT NULL, 
    StationType CHAR(1)  NOT NULL, 
    PlantCode INT   NOT NULL, 

    PRIMARY KEY (StationId), 

    FOREIGN KEY (PlantCode) REFERENCES Private.Plant (PlantCode) 
) 
CREATE TABLE Private.StationOrder (
    StationId VARCHAR(4) NOT NULL, 
    OrderNumber VARCHAR(20) NOT NULL, 

    PRIMARY KEY (StationId) 
) 

Maintenant, je ne veux pas avoir les mêmes données dans deux endroits alors j'ai décidé de changer la table de dbo.t_station en vue et à fournir au lieu de déclencheurs à effectuez les opérations DELETE, INSERT et UPDATE. Pas de problème, je les ai [la plupart] d'entre eux.

Ma question concerne le déclencheur INSTEAD OF UPDATE, la mise à jour de la colonne Primary Key (tx_station_id) et la mise à jour de plusieurs lignes.

A l'intérieur du bloc de déclenchement, est-il possible de joindre les tables [psuedo] insérées et supprimées afin que je connaisse la 'clé primaire avant mise à jour' et la 'clé primaire après mise à jour'? Quelque chose comme ça ...

 
UPDATE sta 
    SET sta.StationId = ins.tx_station_id 
    FROM Private.Station AS sta 
     INNER JOIN deleted AS del 
      INNER JOIN inserted AS ins 
       ON ROW_IDENTITY_OF(del) = ROW_IDENTITY_OF(ins) 
      ON del.tx_station_id = sta.StationId 

A ce stade, je l'ai mis un chèque dans le bloc de déclenchement qui rollbacks la mise à jour si la colonne de clé primaire est mis à jour et il y a plus d'une ligne dans la insérée ou supprimée , table.

+1

J'avais espéré que quelqu'un pourrait avoir une meilleure réponse! Ce problème m'a aussi contrarié dans le passé. –

Répondre

3

La réponse courte est non.

Vous pouvez mettre une clé de substitution sur Private.Station, et l'exposer à travers la vue, et l'utiliser pour identifier les valeurs avant et après. Vous n'auriez pas besoin de modifier la relation de clé primaire ou de clé étrangère, mais vous devrez exposer des images non modifiables à travers la vue, afin qu'elles apparaissent dans les pseudo-tables. par exemple:

alter table Private.Station add StationSk int identity(1,1) not null 

Notez que cela peut casser l'application héritée si elle utilise SELECT *. Les instructions INSERT sans listes de colonnes d'insertion explicites devraient cependant convenir.

court de cela, il peut être une commande cohérente & non documentée entre inserted et deleted, de sorte que ROW_NUMBER() OVER (ORDER BY NULLIF (StationID, StationID)) vous permettrait de joindre les deux, mais je être très hésitant à prendre la route. Très, très hésitant.

Avez-vous intentionnellement désactivé les mises à jour en cascade? Ils sont utiles lorsque les valeurs de clé primaire peuvent être mises à jour. par exemple:

CREATE TABLE Private.Station (
    StationId VARCHAR(4) NOT NULL, 
    Description NVARCHAR(max) NOT NULL, 
    StationType CHAR(1)  NOT NULL, 
    PlantCode INT   NOT NULL, 
    PRIMARY KEY (StationId), 
    FOREIGN KEY (PlantCode) REFERENCES Private.Plant (PlantCode) 
     ON UPDATE CASCADE 
     -- maybe this too: 
     -- ON DELETE CASCADE 
) 

Quelqu'un pourrait avoir un meilleur tour. Attendez et regardez!

+0

Oui, pensé à l'idée de clé de substitution, mais je voulais conserver le nom de la table et les colonnes exactement. En ce qui concerne les mises à jour en cascade et les suppressions qui ne fonctionneront pas pour ma principale préoccupation. StationId est référencé partout dans la base de données et je veux m'assurer que les tables référencées continuent à référencer la bonne station logique. – Kepboy

+0

Je tiens à souligner que je ne suis pas totalement mécontent de ma solution à une rangée, je pensais juste que je demanderais parce que j'aime savoir ces choses. – Kepboy

+0

Les mises à jour de t_station.tx_station_id sont-elles autorisées dans le schéma actuel? Sinon, testez les mises à jour avec COLUMNS_UPDATED(), rollback et déclenchez une erreur si vous détectez des modifications. –

Questions connexes