I want to write a log system about building table. I want that if someone wants to change building table record, the trigger is performed. Triggers task is write to building_log table,which column in building table wants to change. Important: building table is not effected this operation. Is it possible,i am informed when someone wants to change building table but building table is not effected this operation.
It sounds like you are just asking for a 'trigger': you can read about them in the excellent Concepts guide.
But Oracle has a built-in feature that does what you want called Flashback Data Archive—if you can use that instead I suggest you look into it.
--- edit:
Ok, I think I misread the question. You want to silently prevent the update. Leaving aside whether or not this is a good idea, for a before update trigger, you can override the :new values with the original :old values. There is no simple way of doing something similar with an insert, but I don't think you are asking for that.
If you really need to silently prevent inserts too, perhaps you could look at exposing a view to your users instead of the table itself, and creating instead of triggers
Related
For some reason I only recently found out about unique constraints for Core Data. It looks way cleaner than the alternative (doing a fetch first, then inserting the missing entities in the designated context) so I decided to refactor all my existing persistence code.
If I got it right, the gist of it is to always insert a new entity, and, as longs as I have a proper merge policy, saving the context will take care of the uniqueness and in a more efficient way. The problem is every time I save a context with the inserted entity I get a NSCoreDataConstraintViolationException, no error though. When I do the fetch to make sure
there is indeed only one instance with a unique field
other changes to this entity were applied
everything seems to be okay, but I’m still concerned about this exception, since I do saves and therefore get it quite often, a few times per second in some cases.
My project is in objective-c and I know exceptions are expensive there so I’m having doubts if I’m missing something.
Here is a sample project with this issue (just a few lines of code, be sure to add an exception breakpoint)
NSMergeByPropertyObjectTrumpMergePolicy and constraints are not useful tools and should also never be used. The correct way to manage uniqueness is with a fetch before the insert as it appears you have already been doing.
Let's starts with why the only correct merge policy is NSErrorMergePolicy. You should only be writing to core data in on synchronous say (performBackgroundTask is not enough you also need an operation queue). If you have two performBackgroundTask running at the same time and they contradict then you will lose data. Merge policy is answer the question of "which data would you like to lose?" the correct answer is "Don't lose my data!" which is NSErrorMergePolicy.
The same issue happens when you have a constraint. Let's says you have an entity with a unique constraint on the phone number. And you try to insert another entity with the same phone number. What would you like to happen? It depends on what exactly the data is. It might be two different people, and the phone number should be made different (perhaps they were lacking area code), or it might be one person and the data should be merged. Or you might have a constraint on an uniqueID and the number should just be incremented. But on the database level it doesn't know. It always just does a merge. It will silently lose data.
You can create a custom NSMergePolicy and inspect NSConstraintConflict to decide what do to. But in practice you'd have to think about every time you edit the database and what each change means, which can be very hard outside of the context of writing a change to the database. In other words, the problem with a constraints and merge policy is that it the run is on the wrong level of your application to effectively deal with the problem.
Using constraints with a merge policy of error is OK, as it is a way to find problems with your app (as long as you are monitoring crashes and fixing them). But you still need to do the fetch before the insert to make sure the error doesn't happen.
If you want to clean up code then just have one place that you create your objects. Something like objectWithId:createIfNeed:inContext: which does the fetch and create.
I'm currently writing an application that uses SQLite. SQLite doesn't have the ON UPDATE function for timestamps so I wrote my first trigger for it. Then I wrote a trigger to add the current timestamp on the modified and created fields on an insert.
The problem came when I went and deleted the setting of the modified/created fields for the insert. I felt like I was hiding something from developers that might see my code in the future. It could be a source of confusion.
How will they know that the sql is coming from a trigger. Should I comment it? Is it bad practice?
As a rule of thumb, triggers are meant to implement SQL functional rules, such as inclusions, exclusions, partitions etc.
This kind of thing belongs to the model and should be implemented as triggers whenever it is possible. It has to be delivered with the database otherwise the model would be broken.
Regarding to your case, it is more a hack than anything. If you can't do differently, do it and then add a comment like you said. But it should remain an exception.
Keep in mind that almost everything a trigger is doing could be done at the application layer (whichever you want)
Good observation. There are some things only triggers can do. However I suggest that if there is any alternative to using a trigger then use the alternative. I'm not familiar with SQLite, but in any other database I would use a DEFAULT rather than a trigger to timestamp a new record. To capture updated date I would enclose this in a stored procedure, or whatever database side logic you have (kind of what RandomUs1r suggested). I might consider a trigger but only for very basic operations.
You are correct that triggers can be confusing and difficult to debug.
"I felt like I was hiding something from developers..." - this is a very good point. I've came across many developers who use ##Identity and were genuinely shocked that if somebody put a trigger on the table which inserted another row, they'd end up with the wrong identity. (As opposed to SCOPE_IDENTITY() - I know these are sql server specific, but that's pretty much all I know...)
It is hidden - other than documentation I'm not sure you can make it more visible either.
Which is why many avoid them where possible - I guess if there's no easy way around using them in some cases then as long as its well documented, etc. I think like cursors, although scorned by many they can be very powerful and useful...but if they can be avoided probably for the best.
On the code that modifies the record, to get the current timestamp... in SQLLite, try:
DATETIME('NOW')
I just have a very quick question about the use of compound triggers.
I'm very new to database/sql/oracle and have a uni task where i have had to create triggers for the following:
Insert into log table when sales person creates an order
Update on order table whe order is ready to ship (plus insert into log)
Prevent INSERT, UPDATE, DELETE after 5pm friday until 9am monday.
I have succesfully implemeted the triggers but have just become aware of the compound triggers in 11g. Would it be appropriate to look into combining the above into one complound trigger? Is that what they are for or am I missing the point?
Many thanks for looking at this rather vague question.
IMO it wouldn't be appropriate. A compound trigger allows you to trap the four different trigger points (before statement, before action, after action, and after statement) for a given action on a given table, but it looks like A) you're triggering on multiple tables, and B) you don't have a need to service all the different trigger points. (BTW, "action" as I've used it here can mean different statement types, e,g. BEFORE INSERT, UPDATE, DELETE...).
Compound triggers make for a nice, clean, and compact way to work around the never-popular ORA-04091 MUTATING TABLE error, but for the most part I don't find them necessary or useful as a general-purpose do-all replacement for "normal" triggers. For an example, see my answer to this question.
Share and enjoy.
wow - compound triggers - didn't know they even existed...
I quickly looked up the documentation
The main reason to use compound triggers is explained as follows:
The compound trigger makes it easier to program an approach where you
want the actions you implement for the various timing points to share
common data. To achieve the same effect with simple triggers, you had
to model the common state with an ancillary package. This approach was
both cumbersome to program and subject to memory leak when the
triggering statement caused an error and the after-statement trigger
did not fire.
So unless you needed package variables to implement your functionality there wouldn't be a reason for using them. And your code wouldn't be 10g compatible anymore.
I hate triggers. I've been tripped up by them way too many times. But I'd like to know if it's a better to specify the time every time a row is updated or let a trigger take care of it to keep code to a minimum?
Just to clarify, the table the trigger would be on would have a column called something like LastModified
The particular scenario I'm dealing with is I am one of the developers who uses a database with about 400 stored procedures. There are about 20 tables that would have this LastModified column. These tables would be updated by about 10 different stored procedures each.
Triggers can definitely be a huge problem, especially if there are multiple layers of them. It makes debugging, performance tuning, and understanding the data logic almost impossible.
But if you keep your design to a single layer (a trigger for the table), and it is used soley for auditing (i.e. putting the updated time), I don't think that'll be a big problem at all.
Equally, if you are using a stored procedure to be the actor to your tables and views, I think it would make just as much sense (and be a lot easier to remember and look back on) to have your stored procedure put in the current datetime stamp. I think that's a great design.
But if you're using ad hoc queries, and you have a datetime field as not null, it will be a hindrance to remember to call the current datetime. Obviously this won't be a problem with the aforementioned two ideas with the stored procedure or the trigger.
So I think in this situation, is should be personal preference (as long as you don't make a string of triggers that become spaghetti).
You can always use a TimeStamp column (in MySql). If it's MSSQL, just note that the timestamp column is a serial number, not a DateTime data type.
Generally, I avoid triggers like the plague (close to on par with cursors) and so always just update the column manually. To me, it helps reinforce the business logic. But in truth, "better" is a a personal opinion.
Generally, triggers are most useful as a bottleneck if you have a table that needs certain business logic applied for every update, and you have updates coming from different sources.
For example suppose you have php and python apps that both use the database. You could try and remember to update the python code every time you update the php, and vice versa, and hope that they both work the same. Or you could use a trigger, so that no matter what client connects, the same thing will happen to the table.
In most other cases triggers are a bad idea and will cause more pain than they are worth.
Its true that some triggers can often be a source of confusion and frustration when debugging, especially when there are cascading foreign key updates.
But they do have their use.
In this case, you have a choice of updating 400 stored procedures, and updating the date manually. If you miss one of those stored procs, then the field is as good as useless.
Also while triggers 'hide' functionality, the same can be said of explicitly updating it in a stored procedure. What happens when someone writes a new stored procedure, you need to document that the field should be updated.
Personally if its critical the field is up to date, I would use a trigger. Use an INSTEAD OF trigger, so that instead of doing an update and that triggering the trigger, you are simply overriding the insert statement.
General Info:
ASP.NET MVC app
using ADO.NET Entity Framework
SQL Server 2005
I have a few tables that more or less have a hierarchical structure of mostly one-to-many relationships. Most if not all of them have a Last Modified column and my question is simply how best to go about making sure that this column is updated properly throughout the hierarchy. I would prefer to have it done at the database level automatically, I'm just not sure how. A colleague mentioned triggers while at the same time mentioning that they might not be the best way to go. I don't know whether to do this within the class I'm using to manage the model or at the database level. I'd prefer not to have to keep updating each reference individually as that gets tedious and I'd have to make a bunch of separate functions for each level.
My questions then are:
Is there some way to do this at the database level with a stored procedure I could call?
If not, what would you suggest I do on the application side of things to best handle this programmatically?
If any more info would be helpful, I'll be happy to provide it, I had a difficult time trying to figure out how to even ask this question.
Another person had the same/similar question here. Their opinion use a trigger. Here's the full response:
Sql Server (Entity Framework): created_at , updated_at Columns
It depends on where you want your penalty to be. You can have it one of two ways.
Use a trigger to propagate changes up your hierarchy. This might be best when you write once and read a lot. eg: Update an address and the last modified gets set on the parent records as well as the address itself.
Just update one last modified and then query for everything when you need to see when something has been modified. This might be best if you write a lot, but read very little. eg: Only update the last modified on an address. When you query for changed records, query for records that have a last modified or records with addresses that have a last modified.
It's hard to say without knowing your situation. If you need to update all related last modified dates, then I would go the trigger route just to keep things simple.