2010-11-14 4 views
2

je la situation suivante (SQL Server Express):Tables Trigger SQL Server avec des clés étrangères

  • 2 tables reliées par une contrainte pk-fk
  • une vue qui relie ces deux tables
  • la programme à utiliser la base de données n'a accès à la vue
  • un lieu de détente pour les inserts sur la vue

l'idée est que le tri gger entre les données dans la table 1.> un nouveau PK est créé via IDENTITY, la deuxième table doit maintenant contenir l'ID de la table 1. dans le cadre de sa clé primaire ...

Comment puis-je accéder au nouveau créé? PK de la table 1. dans un environnement multi-connexion? Ceci est une version simplifiée/modifed de la base de données:

CREATE TABLE Training ( 
Training_ID INT IDENTITY NOT NULL PRIMARY KEY, 
Name NVARCHAR(30) NOT NULL); 

CREATE TABLE Kilometer (
Training_ID INT NOT NULL REFERENCES Training(Training_ID), 
Kilometer_ID INT NOT NULL, 
Timestamp DATETIME NOT NULL, 
PRIMARY KEY(Training_ID, Kilometer_ID); 

CREATE VIEW TrainingView ( 
SELECT t.Name, k.Timestamp 
FROM Training t LEFT JOIN Kilometer k ON (t.Training_ID = k.Training_ID)); 

CREATE TRIGGER TrainingTrigger ON TrainingView INSTEAD OF INSERT AS BEGIN 
INSERT INTO Training(Name) SELECT Name FROM inserted; 
INSERT INTO Kilometer(Training_ID, Kilometer_ID, Timestamp) SELECT @@Identity, 0, Timestamp FROM inserted; 
END; 

La valeur par défaut « 0 » pour Kilometer_ID est obligatoire en raison d'autres définitions dans la base de données, la fusion de ces deux tables ne sont pas une option ... Alors que le déclenchement semble fonctionner correctement, je ne suis pas sûr si cela va dans un environnement multi-utilisateur (ce qui arrive à @@ Identity, si une autre connexion modifie la table?)

Y a-t-il une meilleure solution à ce déclencheur?

Greetz Michael

Répondre

2

Si votre préoccupation @@ Identity est la seule question l'utilisation SCOPE_IDENTITY(), qui retourne l'identifiant le plus récemment créé à partir CONFOND.

différences expliquées ici: http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/

+0

Merci pour le lien, avez-vous d'autres soucis avec le design? – MFH

+0

Je pourrais avoir simplement stocké une procédure pour les deux insertions à la place, mais votre déclencheur semble sain. Je ne suis pas sûr si j'ai vraiment ce que la table est sur, mais la structure semble ok aussi longtemps que cela ne vous dérange pas que vous ne pouvez pas insérer plusieurs lignes dans une déclaration comme Matt explique. –

+0

ok, je pourrais avoir trop simplifié l'exemple de code, l'insertion de plusieurs lignes dans une déclaration n'est pas vraiment nécessaire actuellement (au moins selon l'exigence actuelle :)) – MFH

0

Votre approche va probablement travailler à peu près tout le temps si elle est dans un environnement à faible volume d'inserts simples. Dans SQL Server, si vous utilisez SCOPE_IDENTITY, c'est mieux car il n'obtient que des identités de la portée actuelle.

Si vous souhaitez insérer plusieurs lignes dans cette vue à la fois (par exemple, insert into TrainingView select ...) cela va se casser parce que vous aurez besoin de plus d'un ID de formation. Pour cela, vous pouvez utiliser SQL Server's OUTPUT clause pour obtenir tous vos ID pour cet insert.

+0

Merci pour votre réponse, je ferais mieux de mettre à jour SCOPE_IDENTITY. Si je comprends bien, cette fonction retournera la dernière identité créée par le déclencheur, quelle que soit la fréquence à laquelle le déclencheur est exécuté en parallèle ou à quel endroit de la base de données une identité est mise à jour. Ai-je raison? – MFH

+0

Je ne sais pas exactement ce que vous voulez dire. SCOPE_IDENTITY() renverra la dernière identité de votre routine spécifique dans vos insertions de session spécifiques, indépendamment de ce qui se passe dans la base de données ou du temps nécessaire pour appeler SCOPE_IDENTITY. Donc, si vous insérez mais laissez votre fenêtre/connexion ouverte, quelqu'un d'autre insère, alors vous passez à appeler SCOPE_IDENTITY(), vous obtenez votre ID inséré en dernier et pas le leur. – Matt

Questions connexes