Μάλλον δεν έχεις καταλάβει πως δουλεύουν οι triggers και τί περιέχουν οι πίνακες @Inserted και @Deleted. Όταν εκτελείται ένα trigger, ο πίνακας inserted περιέχει όλες τις νέες ή τροποποιημένες γραμμές, με τις νέες τους τιμές. Ο @Deleted περιέχει όλες τις διαγραμμένες ή τροποποιημένες γραμμές, με τις παλιές τους τιμές. Οπότε, για να αλλάξεις τις γραμμές που θέλεις, αρκεί να κάνεις:
update products
set Flag=1
from Products INNER JOIN inserted ON Products.ID=inserted.ID
Και τελείωσες.
Αν θέλεις το UPDATE να εκτελείται μόνο όταν έχει τροποποιηθεί το πεδίο Price, μπορείς να χρησιμοποιήσεις το function UPDATE() για να δεις αν έχει τροποποιηθεί όπως παρακάτω:
IF ( UPDATE(Price))
BEGIN
update products
set Flag=1
from Products
INNER JOIN inserted
ON Products.ID=inserted.ID
END
Όλα αυτά μπορείς να τα βρεις στο documentation του SQL Server, καθώς στα βιβλία ή άρθρα που καλύπτουν τα triggers. Οπότε δεν μιλάμε ούτε για bug, ούτε για feature, αλλά για παρανόηση του documentation.
Τέλος, ο τρόπος με τον οποίο χρησιμοποιείς τα inserted και deleted είναι εξαιρετικά αργός. Κάνεις 4 queries για να επιτύχεις ότι θα μπορούσε να γίνει σε 1. Λογικά, είναι το ίδιο να κάνεις ελέγχους αν υπάρχουν τιμές στον inserted και τον deleted και μετά να τραβάς τις τιμές από αυτούς, με το να κάνεις ένα update στο οποίο οι πίνακες θα γίνονται join μεταξύ τους. Ο δεύτερος τρόπος όμως είναι πολύ γρηγορότερος. Ο SQL Server είναι αρκετά έξυπνος για να καταλάβει ότι δεν υπάρχουν εγγραφές, ή ότι δεν υπάρχουν εγγραφές που να ταιριάζουν, πριν προσπαθήσει να κάνει το update. Επιπλέον, η χρήση του COUNT(*) κλειδώνει ολόκληρους τους πίνακες. Αυτό μπορεί να μην είναι μεγάλο πρόβλημα για τους inserted, deleted, θα είναι όμως μεγάλο πρόβλημα αν το εφαρμόσεις σε πίνακες της βάσης και θα οδηγήσει σε σημαντικό blocking και μείωση της ταχύτητας σε καταστάσεις φόρτου.
Παναγιώτης Καναβός, Freelancer
Twitter: http://www.twitter.com/pkanavos