J'espère que c'est une question assez simple pour toutes les personnes SQL là-bas ...
Nous avons une table qui contient les données de configuration du système, et elle est liée à une table d'historique via des déclencheurs afin que nous puissions suivre qui a changé quoi et quand.
J'ai une exigence pour ajouter une autre valeur à cette table, mais c'est celle qui changera fréquemment du code, et a une exigence que nous ne suivons pas son historique (nous ne voulons pas obstruer la table avec plusieurs milliers de mises à jour par jour.
À l'heure actuelle, notre déclencheur est un peu comme ça ...
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
INSERT INTO SystemParameterHistory
(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
)
SELECT
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
FROM Inserted AS I
END
J'aimerais pouvoir ajouter de la logique pour l'empêcher de créer l'enregistrement si une valeur de colonne d'attribut est préfixée avec une chaîne spécifique (par exemple, "NoHist_")
Étant donné que je n'ai pratiquement aucune expérience de travail avec les déclencheurs, je me demandais comment il serait préférable de l'implémenter ... J'ai essayé une clause where comme la suivante
where I.Attribute NOT LIKE 'NoHist_%'
mais cela ne semble pas fonctionner. La valeur est toujours copiée dans la table d'historique.
Toute aide que vous pourriez offrir serait appréciée.
OK - comme prédit par Cade Roux, cela échoue de façon spectaculaire sur plusieurs mises à jour. Je vais devoir adopter une nouvelle approche à ce sujet. Quelqu'un a-t-il d'autres suggestions, s'il vous plaît?
Les gars - Veuillez me renseigner ici ... Pourquoi LEFT () serait-il préférable à LIKE dans ce scénario? Je sais que j'ai accepté la réponse, mais j'aimerais savoir pour ma propre éducation.
Étant donné qu'une clause WHERE n'a pas fonctionné, cela peut:
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
If (SELECT Attribute FROM INSERTED) LIKE 'NoHist_%'
Begin
Return
End
INSERT INTO SystemParameterHistory
(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
)
SELECT
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
FROM Inserted AS I
END
Que dis-tu de ça?
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
IF (LEFT((SELECT Attribute FROM INSERTED), 7) <> 'NoHist_')
BEGIN
INSERT INTO SystemParameterHistory
(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
)
SELECT
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
FROM Inserted AS I
END
END
Votre clause where aurait dû fonctionner. Je ne comprends pas pourquoi cela n'a pas été le cas. Permettez-moi de vous montrer comment j'aurais résolu le problème de la clause where, car cela pourrait vous aider à l'avenir.
Lorsque je crée des déclencheurs, je commence à la fenêtre de requête en créant une table temporaire appelée #insérée (et ou # supprimée) avec toutes les colonnes de la table. Ensuite, je le popultae avec des valeurs typiques (toujours plusieurs enregistrements et j'essaie de frapper les cas de test dans les valeurs)
Ensuite, j'écris ma logique de déclencheurs et je peux tester sans qu'il soit réellement dans un déclencheur. Dans un cas comme votre clause where ne faisant pas ce qui était attendu, je pourrais facilement tester en commentant l'insertion pour voir ce que la sélection renvoyait. Je pourrais alors probablement facilement voir quel était le problème. Je vous assure que là où les clauses fonctionnent dans les déclencheurs si elles sont écrites correctement.
Une fois que je sais que le code fonctionne correctement pour tous les cas, je remplace globalement #insertion par inséré et ajoute le code de déclenchement de création autour de lui et le tour est joué, un déclencheur testé.
Comme je l'ai dit dans un commentaire, je crains que la solution que vous avez choisie ne fonctionne pas correctement dans une insertion ou une mise à jour d'enregistrements multiples. Les déclencheurs doivent toujours être écrits pour tenir compte de cela, car vous ne pouvez pas prédire si et quand ils se produiront (et ils se produisent finalement à peu près à chaque table.)
Le _
le caractère est également un caractère générique, BTW, mais je ne sais pas pourquoi cela ne fonctionnait pas pour vous:
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
INSERT INTO SystemParameterHistory
(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate
)
SELECT
I.Attribute,
I.ParameterValue,
I.ParameterDescription,
I.ChangeDate
FROM Inserted AS I
WHERE I.Attribute NOT LIKE 'NoHist[_]%'
END
CREATE TRIGGER
[dbo].[SystemParameterInsertUpdate]
ON
[dbo].[SystemParameter]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
DECLARE @StartRow int
DECLARE @EndRow int
DECLARE @CurrentRow int
SET @StartRow = 1
SET @EndRow = (SELECT count(*) FROM inserted)
SET @CurrentRow = @StartRow
WHILE @CurrentRow <= @EndRow BEGIN
IF (SELECT Attribute FROM (SELECT ROW_NUMBER() OVER (ORDER BY Attribute ASC) AS 'RowNum', Attribute FROM inserted) AS INS WHERE RowNum = @CurrentRow) LIKE 'NoHist_%' BEGIN
INSERT INTO SystemParameterHistory(
Attribute,
ParameterValue,
ParameterDescription,
ChangeDate)
SELECT
I.Attribute,
I.ParameterValue,
I.ParameterDescription,
I.ChangeDate
FROM
(SELECT Attribute, ParameterValue, ParameterDescription, ChangeDate FROM (
SELECT ROW_NUMBER() OVER (ORDER BY Attribute ASC) AS 'RowNum', *
FROM inserted)
AS I
WHERE RowNum = @CurrentRow
END --END IF
SET @CurrentRow = @CurrentRow + 1
END --END WHILE
END --END TRIGGER