Hacker News new | ask | show | jobs
by taffer 2421 days ago
You still have to call a method if you want it to do something. It doesn't simply happen as a side effect of something else. A method call only ever does one thing at a time, not multiple things in a random order. Read this if you still think triggers are a good idea: https://blogs.oracle.com/oraclemagazine/the-trouble-with-tri...
2 comments

> A method call only ever does one thing at a time, not multiple things in a random order.

That's...not at all guaranteed if it is possible for the method call to make use of concurrency and parallelism constructs. It's actually not at all uncommon for method calls to do a unknown number of things in an unknown order (and it can even have an unknown number of them still in progress when the method returns!)

Exactly.
Yeah, and in SQL that's INSERT/UPDATE/DELETE on a table/view. Syntactically, using a stored procedure is really no different, and it can have function calls you don't know about because its body could dispatch just like triggers do.

This whole thing about triggers being implied/hidden is not based on anything other than taste.

> and it can have function calls you don't know about because its body could dispatch just like triggers do.

Please give an example of a stored procedure that does something else than what the code says it will do.

> This whole thing [...] is not based on anything other than taste.

Good taste: Insert, update and delete doing exactly what the statement says. Procedures doing exactly what the code says.

Bad taste: Insert, update and delete surprising you with magic tricks.

> > and it can have function calls you don't know about because its body could dispatch just like triggers do.

> Please give an example of a stored procedure that does something else than what the code says it will do.

That's not what I wrote. I wrote that the caller of an SP need not know anything about the SP's body any more than the caller of a DML need not know anything about triggers. Of course that is true. And of course it's also true that the caller could know all those details in either case.

Let's say customer 1234 wants us to delete his/her customer record, so we issue the following statement:

  DELETE FROM customers WHERE customer_id = 1234;
The statement runs successfully and of course we would expect the customer record to be deleted, because that's what we just said, isn't it? However, the customer is still there somehow. What has happened? Was our statement wrong?

It turns out our applications has triggers and by surprise the DELETE changed into

  UPDATE customers SET contract_status = 'terminated' WHERE emp_id = 1234;
just because a few years ago someone thought that the logic of terminating a contract should be wrapped in a now long-forgotten trigger that magically transforms a straightforward DELETE into an UPDATE.

If the developer had instead put the logic into a procedure like terminate_contract(customer_id), we wouldn't have had this problem in the first place.

There's nothing wrong with having a trigger that turns deletes into updates, if that's what you want. Why would you be surprised that you can do this, or that it's been done?

Your schema is an interface here, so read its docs!

EDIT: BTW, it's quite reasonable to have a policy to not delete, but mark deleted/terminated, rows in certain tables. This is especially important for security-relevant tables where the names of entities are liable to get written down in external (to the DB) ACLs. It's quite reasonable to implement such a policy in the DB as triggers -- indeed, there's no better way to do it, since otherwise a user who doesn't read the docs (like you) but does have privilege, might break the database.

So, actually, I really think you've completely misunderstood. What you thought was a problem was likely a solution to a bigger problem that you were not aware of. If you removed that trigger, you likely broke something. Meanwhile you're convinced triggers are a bad idea and spread that around as gospel.

> Why would you be surprised[...]

The statement says DELETE and that is what I want, the rdms executes it and tells me "deleted 1" (yes, it does). What am I supposed to think?

> Your schema is an interface here, so read its docs!

What docs? Apparently triggers are obvious and self-documenting, or at least that's what the guy who wrote them thought.

> there's no better way to do it, since otherwise a user who doesn't read the docs (like you) but does have privilege, might break the database.

Why properly revoke the deletion permission and offer terminate_contract(customer_id) as an alternative if you can use a magic trick instead?

> There's nothing wrong with having a trigger that turns deletes into updates, if that's what you want.

While I wouldn't use it on base tables, a view that provides a “current” picture where deletes are updates (or even inserts of a deletion event) into a base tabl with (potentially along with others) provides a complete historical picture of the status of the data of which the view presents a current snapshot is a useful approach.

Yes, a DELETE trigger on a table that reports successful deletion but doesn't actually delete the row referenced, leaving it still in the table, is bad design.

It's not evidence that triggers are bad, it's just bad design.

(An INSTEAD OF DELETE trigger on a view that marks a base table entry as logically deleted, causing the corresponding data to be removed from the view is, OTOH, not bad in the same way.)

> If the developer had instead put the logic into a procedure like terminate_contract(customer_id), we wouldn't have had this problem in the first place.

Or if they put it as an INSTEAD OF DELETE trigger on a current contracts view, with the design described above; conversely a badly-named store proc would have the same basic problem as the trigger at issue here. This isn't a trigger problem.

I disagree. The logical operation is "delete", and "mark deleted" is a perfectly fine concrete implementation of "logical delete".