210

In my experience, they are not a good idea because they can result in surprising side effects, and are difficult to debug (especially when one trigger fires another). Often developers do not even think of looking if there is a trigger.

On the other hand, if you have logic that must occur every time a new FOO is created in the database, then it may be the most foolproof place to put it is an insert trigger on the FOO table.

The only time we're using triggers is for really simple things like setting the modified date field of a row.

I'm struggling to figure out whether triggers are necessary and would appreciate any input. If they are necessary, what are the most important issues to consider when implementing them?

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
WW.
  • 23,793
  • 13
  • 94
  • 121
  • 34
    This is a totally legitimate question but I don't quite like the sensationalist title. I think something like "What are the most important issues to consider when implementing database triggers?" would be much better. – Tamas Czinege Jan 20 '09 at 10:20
  • 2
    The question is closed for adding answers, but see also [Are database triggers safe for cross table integrity constraints?](http://stackoverflow.com/q/16881043/2032064). (Spoiler: no, they are not) – Mifeet Jun 02 '13 at 08:53
  • 1
    Business Logic in a trigger is problematic (evil, if you will). Database Logic in a trigger is not problematic (integrity, logging). – Greg Gum Jun 07 '18 at 01:36
  • 1
    I like to rely on IDE for code navigation and understanding what's going on. I can't do that if half the logic is in database and other half in the programming language of choice. Instead of triggers I find it easier to create a controller that every request has to go through. All 'triggers' can the be applied there instead. – Muhammad Umer Dec 14 '19 at 19:55

20 Answers20

177

The main problems with triggers are

  • They are completely Global - they apply no matter what the context of the table activity;
  • They are stealthy; it's easy to forget they are there until they hurt you with unintended (and very mysterious) consequences.

This just means they need to be carefully used for the proper circumstances; which in my experience is limited to relational integrity issues (sometimes with finer granularity than you can get declaratively); and usually not for business or transactional purposes. YMMV.

Nguyễn Văn Phong
  • 13,506
  • 17
  • 39
  • 56
dkretz
  • 37,399
  • 13
  • 80
  • 138
  • 24
    Those are 2 advantages, in some cases. – Johnno Nolan Jan 20 '09 at 10:30
  • 21
    "Stealthy" is a great word, yeah -- well said. That's exactly why I tend to shy away from them: too often they're forgotten or ignored. In my personal experience, revisiting triggers is often accompanied by a smack to my own forehead. – Christian Nunciato Jan 20 '09 at 10:49
  • 2
    You can build the context into the trigger. A simple if statement can achieve quite a lot. – tuinstoel Jan 20 '09 at 16:06
  • @Nolan, I can agree about Global being a benefit - that's when they are appropriate. But stealthy - I'm having a harder time seeing the advantage in that. @tuinstoel, I'm not sure how a trigger can have its context built in, since it takes no arguments. – dkretz Jan 20 '09 at 23:10
  • I'm curious about your "never for business or transactional purposes" quote, @le dorfier. Why do you think that's not appropriate? – paxdiablo Jan 21 '09 at 00:42
  • 1
    Several independent reasons, each of which could be debated but together I think they are pursuasive. 1. Business rules belong in the BL together, where they are accessible at the proper granularity for UI validation and exception handling. – dkretz Jan 21 '09 at 01:25
  • 1
    2. Triggers are global and comparatively immutable. Business rules are local and subject to local changes which shouldn't be coupled to global stealth triggers. 3. Personal experience. @Nunciato phrases it nicely above. – dkretz Jan 21 '09 at 01:25
  • 1
    I'd be extremely careful with using triggers to create anything related to relational integrity. About 90-99% of those triggers I have seen where a major data integrity problem waiting to happen. In the other 1-10% it actually happened. – Jens Schauder Jun 15 '10 at 19:56
  • 5
    Global is why they are good and necessary for data integrity and things like auditing. It isn't a minus, it's a plus. – HLGEM Jun 15 '10 at 21:34
  • 2
    Triggers are a way to hell in my opinion, messy, not a single developer I met knows how to deal with them properly. If you think you need a trigger, think again! That said, wise use of a trigger can help you avoid loads of coding. I'm surprised nobody noticed "instead of" triggers on views. view triggers can help a great deal with import-export to SQL aware tools and provide the means for a simple integration. – Robert Cutajar May 18 '11 at 14:05
  • 4
    so @RobertŠevčík-Robajz, you are saying all the developers you know are incomptent? – HLGEM Oct 16 '12 at 14:26
  • @HLGEM, pretty much so. They google the syntax, alright, but it takes much more than that to write a trigger that supports a set operation and is efficient. I think it's not that devs are useless, it's that this topic is not their main subject. – Robert Cutajar Nov 01 '12 at 09:10
  • 1
    @RobertŠevčík-Robajz, since no applicationthat extensively uses a database shoudl be without a database specialist who cis competent in databases, it si not the fault of triggers that you are staffed incorrectly. – HLGEM Jan 09 '15 at 21:04
  • 3
    @HGLEM, agree there should be a specialist to work out triggers. Real life scenario - there isn't. Real life scenario - days spent trying to identify a bug related to a forgotten trigger. Real life scenario - trigger logic is being desperately pushed out into application logic where it can be easily refactored and unit-tested. It's real life I deal with that makes me say "stay away from triggers"... it's not the fault of triggers as it's not the fault of stones that windows get broken. – Robert Cutajar Jan 12 '15 at 17:41
  • 1
    @Robert Ševčík - Robajz: And what are your unit-tests doing when a 3rd party program accesses the database and doesn't at all handle e.g. TerminationDates of subordinate objects ? Or someone executes a SQL-Script directly ? – Stefan Steiger Feb 06 '15 at 17:21
  • 1
    @Quandary, unit-tests are throwing a party for 3rd parties, but policies and ACLs cannot attend being strictly busy taking care of silly 3rd party ideas. I think I said enough, please don't feel offended if I stay quiet next time. Cheerio. – Robert Cutajar Feb 09 '15 at 22:19
  • @dkretz I plan to use trigger on my table to keep data integrity. What do you think? ref: https://i.stack.imgur.com/tIOyp.png – Yosua Lijanto Binar Jun 20 '17 at 11:09
  • I'd say that "triggers are stealthy" is one of a poor excuses of a poor documentation. – Ucello Dec 28 '17 at 08:57
  • Triggers are not evil, they can be good or bad, just like controller actions. You wouldn't say that Web API controllers are evil because some people write actions badly. It just takes a bit of discipline, and good peer review. – CompanyDroneFromSector7G Dec 14 '21 at 12:01
91

No, they're actually a good idea. If there's a problem with your specific triggers, then you're not doing them right, but that usually means there's a problem with your implementation, not the concept of triggers themselves :-).

We use triggers a great deal because it places the DBMS-specific activity under the control of the database where it belongs. Users of a DBMS should not have to worry about that sort of stuff. The integrity of data lies with the database itself, not the applications or users that use it. Without constraints and triggers and other features in the database, it's left to the applications to enforce the rules and it only takes one rogue or buggy application/user to destroy the data.

For example, without triggers, such wondrous things as auto-generated columns wouldn't exist and you'd have to process a function on each row when selecting them. That's likely to kill DBMS performance, far better to create the auto-generated column at insert/update time since that's the only time it changes.

Also, lack of triggers would prevent data rules from being enforced at the DBMS such as pre-triggers to ensure columns have a specific format. Note that this is different from data integrity rules which are generally just foreign key look ups.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 11
    "process a function on each row when selecting them". It is better to use a function based index for this purpose than a trigger. – tuinstoel Jan 20 '09 at 11:00
  • 11
    Not necessarily, the trigger will probably only run when the row is inserted or updated. The function-based index will run for every select. Depending on usage pattern one is probably better than the other. But neither is ALWAYS better than the other. – jmucchiello Feb 03 '10 at 20:43
  • @tuinstoel: I have to agree with your statement *some* of the time. Oracle, for example, will only create function-based indexes if it can prove that the function is deterministic. Sometimes that just cannot be proved (for example, if the function involves a look-up from a table, even if you *know* that the table's data never changes). – Adam Paynter Jun 15 '10 at 21:53
59

Tools are never evil. Applications of those tools can be evil.

Andy Webb
  • 1,712
  • 10
  • 16
  • 17
    I've never been more conflicted after reading a comment. On one hand, I'm pro second amendment and believe that guns aren't inherently evil: it's the person using them. On the other hand, I believe that triggers ARE evil... I think I'm having an existential meltdown... – vbullinger Dec 17 '12 at 04:55
  • 54
    @vbullinger guns aren't evil, but their triggers are ;) – Darragh Enright Oct 06 '14 at 12:49
  • 2
    :D Generalisations are dangerous (recursively). Have you come by the torture 'tools' used by inquisitors to 'trigger' a confession? +1 for the perspective anyway. – Robert Cutajar Feb 09 '15 at 22:37
21

I agree. The problems with triggers is people, not triggers. Although it's more to look at, more to consider and increases the onus on coders checking things correctly, we don't discard indexes to make our lives simpler. (Bad indexes can be just as bad as bad triggers)

The importance of triggers (in my mind) is that...
- Any system should always be in a valid state
- Code to enforce this valid state should be centralised (not written in every SP)

From a maintenance point of view, a trigger is very useful to competant coders and problems for more junior/amateur ones. Yet, these people need to learn and grow somehow.

I guess it comes down to your working environment. Do you have reliable people who learn well and can be trusted to be methodical? If not you seemingly have two choices:
- Accept that you'll have to lose functionality to compensate
- Accept that you need different people or better training and management

They sound harsh, and I guess that they are. But it's the basic truth, in my mind...

Dave Sherohman
  • 45,363
  • 14
  • 64
  • 102
MatBailie
  • 83,401
  • 18
  • 103
  • 137
  • 5
    >>>The problems with triggers is people. Yeah, if only people could code in assembly, work with crappy GUI, guess correctly whether to push or pull a badly designed door... Any "feature" people get repeatedly wrong is "evil". – Fakrudeen Dec 27 '11 at 06:57
  • 1
    @Fakrudeen, any developer that gets triggers wrong is incompetent to be accessing a database. – HLGEM Apr 03 '14 at 17:43
19

I think triggers are not only not evil, but necessary to good database design. Application programmers think that databases are only affected by their application. They are often wrong. If data integrity is to be maintained no matter where the data change came from, triggers are a requirement and it is foolish to avoid them because some programmers are too ethnocentric to consider that something other than their prized application may be affecting things. It isn't hard to design or test or troubleshoot a trigger if you are a competent database developer. Nor it is difficult to determine that a trigger is causing an unexpected result if it occurs to you (as it does to me) to look there. If I get an error saying a table that I'm not referencing in my sp has an FK error, I know without even thinking about it that trigger is causing the problem and so should any competent database developer. Putting business rules only in the application is the number one cause I have found of bad data as others have no idea that rule even exists and violate it in their processes. Data-centric rules belong in the database and triggers are key to enforcing the more complex ones.

HLGEM
  • 94,695
  • 15
  • 113
  • 186
14

Mostly, yes.

The difficulty with a trigger is that it does stuff "behind your back"; the developer maintaining the application could easily not realise it's there and make changes which screw things up without even noticing.

It creates a layer of complexity which just adds maintenance work.

Rather than using a trigger, a stored procedure / routine, can generally be made to do the same thing, but in a clear and maintainable manner - calling a stored routine means the developer can look at its source code and see exactly what's happening.

MarkR
  • 62,604
  • 14
  • 116
  • 151
  • 12
    This is the advantage of a trigger not the disadvatage! Stored procs cannot be guaranteed to be invoked for every change to the data. THere are many ways data can be changed besides the GUI. – HLGEM Jan 21 '09 at 15:49
  • 3
    HLGEM, that depends on your access control. You can deny any modification to tables directly except through a stored procedure. – Robert Cutajar May 18 '11 at 13:53
  • 1
    I think the point is that if, for example, records in two tables should ALWAYS be created and destroyed together, no matter how you access the database, and no matter who you are or what permissions you have, then triggers are the only legitimate solution. The mere fact that it's even *possible* to assign too many or incorrect permissions and to expect people to know which stored procedures are to be used, means the database is at risk of losing its integrity. Its exactly the same as foreign key relationships. It's simply BEST and MOST RELIABLY enforced by the database engine. – Triynko Oct 17 '13 at 22:42
  • 2
    If records should always be created / destroyed together, create a check constraint which ensures that they are. That way someone who breaks the rules gets an error, rather than a hidden behaviour which magically makes things right without their knowledge or consent. – MarkR Oct 19 '13 at 14:05
10

Triggers have their uses - logging/auditing and maintaining a "last modified" date are two very good uses which have been mentioned in previous replies.

However, one of the core tenets of good design is that business rules/business logic/whatever you want to call it should be concentrated in a single place. Putting some of the logic in the database (via triggers or stored procs) and some in the application violates that principle. Duplicating the logic in both places is even worse, as they will invariably get out of sync with each other.

There is also the "principle of least surprise" issue which has already been mentioned.

Dave Sherohman
  • 45,363
  • 14
  • 64
  • 102
  • 3
    That's correct it should be in one place, the database. Logic that affects the integrity of the data must ALWAYS be in the database and never in an application where it might or might not get called when affecting data in the database. – HLGEM Jun 15 '10 at 21:38
  • 1
    @HLGEM: That depends on whether the database can possibly have access to information that allows it to tell whether the data is valid. It's not always the case that it can; when the validator is in another organization (e.g., for credit card or bank account details) then the DB can't know whether it is right — assuming this isn't the bank's DB! — and it will have to rely on the application for enforcement. What you don't want is to have the database making random connections to third-party services, as that is bad when it comes to server deployment. – Donal Fellows Jun 15 '10 at 21:50
  • @HLGEM: While I'm not ready to completely rule out the option of putting all application logic into the database, I find that it tends to work better to put it elsewhere, generally a reusable OO layer that can be used for all apps accessing the database. So long as your app only accesses the database through the object layer, the same guarantees of the logic always being called will still apply. – Dave Sherohman Jun 16 '10 at 08:59
  • 2
    Never worked on a business application that only inserted data into the database through the Object layer and I wouildn't want to work on one. It's stupid to put million record imports or updates of all prices through a process designed to handle only one record ata time. THe Object layer is exactly the wrong place to enforce data integrity which is why so many datbases have integrity problems. – HLGEM Jun 16 '10 at 12:14
  • @HLGEM For that very reason I'm working on an extension to our ORM to work like a trigger using a changeset of everything within a transaction. It feels a little silly but will prevent us having all our business logic in the application except the few times it's not (Only a few tables ever need bulk updating). It will also allow all developers to write and use them in the language they're most comfortable with and where there is access to all the object abstractions we've built. – Adamantish Jul 11 '16 at 17:33
  • Many processes cannot use an ORM. I certainly can't use one in SSIS or SSRS. There will ad hoc queries to fix bad data or problem records, those will NEVER go through an ORM because they are one-time fixes not application fixes. Certainly large data imports should never go through an ORM either. Far better to have real triggers than fake something up for an ORM that is easily bypassed. – HLGEM Jul 11 '16 at 17:38
8

Triggers are extremely powerful and useful, there are any number of scenarios where a trigger is the best solution to a problem.

They are also a very good "hack" tool. There are often situations where you are not in immediate control of both the code and the database. If you have to wait 2 months for the next major release of your code, yet you can apply a patch to your database immediately then you can put a trigger on a table to perform some additional functionality. Then when the code release is possible you can replace this trigger with your coded version of the same functionality if desired.

At the end of the day, everything is "evil" if you don't know what it's doing. Deciding that triggers are because there are developers that don't understand them is the same as arguing that cars are evil because some people can't drive...

Robin Day
  • 100,552
  • 23
  • 116
  • 167
7

At a high level there are two use-cases for triggers1

1) To make stuff "automagically" happen. In this case triggers cause a side-effect, they change data in ways that were not expected given the (primitive) operator insert, update or delete that was executed and caused the trigger to fire.

The general consensus here is that triggers are indeed harmful. Because they change the well known semantics of an INSERT, UPDATE or DELETE statement. Changing the semantics of these three primitive SQL operators will bite other developers who later in the future need to work on your database tables that do not behave in expected ways anymore when operated upon them with the SQL primitives.

2) To enforce data integrity rules, other than the ones we can deal with declaratively (using CHECK, PRIMARY KEY, UNIQUE KEY and FOREIGN KEY). In this use-case all the triggers do is QUERY (SELECT) data to verify if the change that is being made by the INSERT/UPDATE/DELETE is allowed or not. Just like declarative constraints do for us. Only in this case we (the developers) have programmed the enforcement.

Using triggers for the latter use-case is not harmful.

I'm blogging on that at: http://harmfultriggers.blogspot.com

Toon Koppelaars
  • 154
  • 1
  • 3
  • When using triggers for referential integrity it is harder than it looks to handle concurrency issues. – WW. Nov 30 '11 at 23:49
  • 2
    Agreed. But is it easier when using some other means? – Toon Koppelaars Dec 01 '11 at 06:52
  • There are a LOT of incompetent developers though lol. – hashtable Apr 19 '17 at 15:55
  • I wouldn't agree that triggers are harmful. If you know exactly what the trigger is doing, and you program it well, it should always work as expected. The only pain point here is inaccurately implementing or using it. – Delali Oct 21 '20 at 13:41
6

Triggers are a good tool when used properly. Expecially for things like auditing changes, populating summarization tables, etc.

Now they can be "evil" if you end up in "trigger hell" with one trigger that kicks off other triggers. I once worked on a COTS product where they had what they called "flex triggers." These triggers were stored in a table as dynamic sql stings are were compiled every time they were executed. Compiled triggers would do a look up and see if that table had any flex triggers to run and then compile and run the "flex" trigger. In theory this sounded like a really cool idea because the product was easily customized but the reality was the database pretty much exploded due to all the compiles it had to do...

So yeah, they're great if you keep what you're doing in perspective. If it is something pretty simple like auditing, summarizing, auto-sequencing, etc, no prob. Just keep in mind the growth rate of the table and how the trigger will impact performance.

tmeisenh
  • 1,504
  • 1
  • 13
  • 11
5

Not evil. They actually simplify things like

1.Logging/auditing of changes to records or even database schemas

You could have a trigger on ALTER TABLE that rolls back changes in your production environment. This should prevent any accidental table modifications.


2.Enforcing referential intrgrity (primary/foreign key relationships, etc) across multiple databases

Chris
  • 433
  • 1
  • 4
  • 8
4

They are definitely not evil. I found triggers precious during refactoring of database schemas, while renaming a column, or splitting a column into two columns or vice-versa (example: name/surname case) and assisting the transition.

They are also very useful for auditing.

Stefano Borini
  • 138,652
  • 96
  • 297
  • 431
4

I know developers who think triggers should always be used where it is the most direct way of achieving the functionality they want, and developers who never will. It's almost like dogma between the two camps.

However I personally completely agree with MarkR - you can (nearly) always write code functionally equivalent to the trigger that will be more perspicuous and therefore easier to maintain.

DanSingerman
  • 36,066
  • 13
  • 81
  • 92
4

To say that they are evil is an exageration but they can cause of mesh. When the firing of one trigger causes other triggers to fire it becomes really complicated. Let's say they are troublesome: http://www.oracle.com/technology/oramag/oracle/08-sep/o58asktom.html

Doing business logic in Oracle with triggers is harder than it seems because of multi concurrency issues. You don't see changes in another session until the other sessions commits.

tuinstoel
  • 7,248
  • 27
  • 27
4

This answer applies specifically to SQL Server. (though It may also apply to other RDBMSs I have no idea. I would have preferred to give it as an answer here but that was closed as a dupe of this.)

One aspect not mentioned in any of the answers so far is security. Because, by default, triggers execute under the context of the user that executes the statement that causes the trigger to fire this can cause a security threat unless all triggers are reviewed.

The example given in BOL under the "Managing Trigger Security" heading is of a user that creates a trigger containing the code GRANT CONTROL SERVER TO JohnDoe ; in order to escalate their own permissions.

Community
  • 1
  • 1
Martin Smith
  • 438,706
  • 87
  • 741
  • 845
3

If there are side effects, it's a problem by design. In some database systems, there is no other possibility to set an autoincrement field i.e. for a primary key ID field.

Xn0vv3r
  • 17,766
  • 13
  • 58
  • 65
3

I think they can be evil, but only as evil as anything else in development.

Although I don't really have much experience with them I did have them on a recent project I worked on which has lead me to this conclusion. The problem I have with them is they can cause business logic to end up in two locations, a code library and a database.

I see it as a similar argument with using sprocs. You'll often have developers who are really good at SQL writing business logic into the database, while people who are not will have their business logic elsewhere.

So my rule-of-thumb is look at what the structure of your project is. If it seems viable to have business logic stored in the database then it could be useful to have triggers.

Aaron Powell
  • 24,927
  • 18
  • 98
  • 150
3

Nah, they're not evil - they're just misunderstood :-D

Triggers have a valid use, but far too often as a retro-hack that ultimately makes things worse.

If you're developing a DB as part of an application the logic should always be in the code or sprocs making the call. Triggers will just lead to debug-pain later on.

If you understand how locking, deadlocking and how DBs access files on disk then using triggers in the right way (for instance auditing or archiving direct DB access) can be really valuable.

Keith
  • 150,284
  • 78
  • 298
  • 434
1

Idea of triggers is not evil, limiting nesting of triggers is evil.

alpav
  • 2,972
  • 3
  • 37
  • 47
1

Indeed, quite often triggers are being misused. Actually in most cases you don't even need them. But that doesn't make them necessarily bad.

A scenario that comes to my mind where triggers are useful is when you have a legacy application for which you don't have the source code and there is no way to change it.

ibz
  • 44,461
  • 24
  • 70
  • 86