I'm new to triggers and I need to fire a trigger when selecting values from a database table in sql server. I have tried firing triggers on insert/update and delete. is there any way to fire trigger when selecting values?
There are only two ways I know that you can do this and neither are trigger.
You can use a stored procedure to run the query and log the query to a table and other information you'd like to know.
You can use the audit feature of SQL Server.
I've never used the latter, so I can't speak of the ease of use.
No there is no provision of having trigger on SELECT operation. As suggested in earlier answer, write a stored procedure which takes parameters that are fetched from SEECT query and call this procedure after desired SELECT query.
SpectralGhost's answer assumes you are trying to do something like a security audit of who or what has looked at which data.
But it strikes me if you are new enough to sql not to know that a SELECT trigger is conceptually daft, you may be trying to do something else, in which case you're really talking about locking rather than auditing - i.e. once one process has read a particular record you want to prevent other processes accessing it (or possibly some other related records in a different table) until the transaction is either committed or rolled back. In that case, triggers are definitely not your solution (they rarely are). See BOL on transaction control and locking
Related
I've got database ApressFinancial which i created from the book. (Robin Dewson - Beginning SQL Server for Developers (The Expert's Voice in SQL Server) - 2014)
I was asked a question: "How to check the correctness of adding records to the transaction log?" (And there was Hint that i can use trigger instead of)
Could not figure out.
Thank you.
I think you need a INSTEAD OF INSERT trigger in order to catch all your inserted data.
Basically, you create a trigger, which is a special type of stored procedure that lets you hook some functionality inside the transaction that should perform the INSERT (instead of will cause the insert intent to not fulfill). The trigger will expose a special table (not sure this is the exact term, but it behaves like one) called inserted that contains the information that is supposed to be inserted.
A more relevant example can be found here.
NOTE: also take a look upon AFTER INSERT trigger, as this type allows values to be inserted and provide a mechanism to use the values to perform other operations.
I am aware of DB triggers and not seeking that option. I am wondering if its possible to observe DB tables with a reader from the middle ware.
Question - is it possible to get a observable wrapper using the SQL CLR types in C# on a Database table, for e.g. I have a table of tickets, how do I watch the table.
No, SQLCLR does not provide any special means of doing this.
The best, most appropriate, and only way to accomplish getting notifications of table modifications is through Triggers. That is what they are meant to do. You can capture data changes via DML Triggers (for INSERT, UPDATE, and DELETE operations), and you can capture structural changes via DDL Triggers (for ALTER TABLE, CREATE / ALTER / DROP TRIGGER, and CREATE / DROP INDEX operations).
You can create either type of Trigger using either pure T-SQL or using SQLCLR, though the SQLCLR option doesn't afford much benefit over T-SQL besides being able to access the inserted and deleted pseudo-tables via Dynamic SQL. The other reason to use a SQLCLR Trigger would be if you just need all rows of data from one or both of those pseudo-tables for a single operation. Else you could just call a SQLCLR User-Defined Function in a T-SQL Trigger if you needed to handle something on a per-row basis.
Remember, Triggers are part of the Transaction that is internally created (if no Transaction is currently active) when the DML operation starts. This way any changes made by the Trigger can be rolled-back if the DML operation ultimately fails.
If you want very light-weight notifications, you can do one of the following, but keep in mind that both will side-step the Transaction (i.e. cannot take back notification of an operation that fails to complete) and so can easily result in false-positives (i.e. notifications of modifications that never committed):
Send emails via sp_send_dbmail. This is asynchronous so should not adversely impact performance. But you do need to format the full data modification report as a string (perhaps as HTML?) in the trigger rather than attaching the results of a query since the query for the email won't have access to the pseudo-tables.
Use SQLCLR to dump desired info to a text file. You just need to be careful to allow for multiple, concurrent write-requests to the file, else concurrent DML statements will be negatively impacted.
A quick note about Query Notifications since the question was tagged with SqlDependency:
Query Notifications are not really helpful here. In addition to a list of restrictions on what queries are eligible for Query Notifications, they only indicate that the result set of a particular query has changed. So even if you set up simple notifications for SELECT * FROM table;, it won't tell you what changed specifically (i.e. the rows in the INSERTED and/or DELETED pseudo-tables available in Triggers). Still, if you are interested in reading up on them, here are two helpful links:
Working with Query Notifications
Query Notifications in SQL Server
Can I find out when the last INSERT, UPDATE or DELETE statement was performed on a table in an Oracle database and if so, how?
A little background: The Oracle version is 10g. I have a batch application that runs regularly, reads data from a single Oracle table and writes it into a file. I would like to skip this if the data hasn't changed since the last time the job ran.
The application is written in C++ and communicates with Oracle via OCI. It logs into Oracle with a "normal" user, so I can't use any special admin stuff.
Edit: Okay, "Special Admin Stuff" wasn't exactly a good description. What I mean is: I can't do anything besides SELECTing from tables and calling stored procedures. Changing anything about the database itself (like adding triggers), is sadly not an option if want to get it done before 2010.
I'm really late to this party but here's how I did it:
SELECT SCN_TO_TIMESTAMP(MAX(ora_rowscn)) from myTable;
It's close enough for my purposes.
Since you are on 10g, you could potentially use the ORA_ROWSCN pseudocolumn. That gives you an upper bound of the last SCN (system change number) that caused a change in the row. Since this is an increasing sequence, you could store off the maximum ORA_ROWSCN that you've seen and then look only for data with an SCN greater than that.
By default, ORA_ROWSCN is actually maintained at the block level, so a change to any row in a block will change the ORA_ROWSCN for all rows in the block. This is probably quite sufficient if the intention is to minimize the number of rows you process multiple times with no changes if we're talking about "normal" data access patterns. You can rebuild the table with ROWDEPENDENCIES which will cause the ORA_ROWSCN to be tracked at the row level, which gives you more granular information but requires a one-time effort to rebuild the table.
Another option would be to configure something like Change Data Capture (CDC) and to make your OCI application a subscriber to changes to the table, but that also requires a one-time effort to configure CDC.
Ask your DBA about auditing. He can start an audit with a simple command like :
AUDIT INSERT ON user.table
Then you can query the table USER_AUDIT_OBJECT to determine if there has been an insert on your table since the last export.
google for Oracle auditing for more info...
SELECT * FROM all_tab_modifications;
Could you run a checksum of some sort on the result and store that locally? Then when your application queries the database, you can compare its checksum and determine if you should import it?
It looks like you may be able to use the ORA_HASH function to accomplish this.
Update: Another good resource: 10g’s ORA_HASH function to determine if two Oracle tables’ data are equal
Oracle can watch tables for changes and when a change occurs can execute a callback function in PL/SQL or OCI. The callback gets an object that's a collection of tables which changed, and that has a collection of rowid which changed, and the type of action, Ins, upd, del.
So you don't even go to the table, you sit and wait to be called. You'll only go if there are changes to write.
It's called Database Change Notification. It's much simpler than CDC as Justin mentioned, but both require some fancy admin stuff. The good part is that neither of these require changes to the APPLICATION.
The caveat is that CDC is fine for high volume tables, DCN is not.
If the auditing is enabled on the server, just simply use
SELECT *
FROM ALL_TAB_MODIFICATIONS
WHERE TABLE_NAME IN ()
You would need to add a trigger on insert, update, delete that sets a value in another table to sysdate.
When you run application, it would read the value and save it somewhere so that the next time it is run it has a reference to compare.
Would you consider that "Special Admin Stuff"?
It would be better to describe what you're actually doing so you get clearer answers.
How long does the batch process take to write the file? It may be easiest to let it go ahead and then compare the file against a copy of the file from the previous run to see if they are identical.
If any one is still looking for an answer they can use Oracle Database Change Notification feature coming with Oracle 10g. It requires CHANGE NOTIFICATION system privilege. You can register listeners when to trigger a notification back to the application.
Please use the below statement
select * from all_objects ao where ao.OBJECT_TYPE = 'TABLE' and ao.OWNER = 'YOUR_SCHEMA_NAME'
i have a table named "LogDelete" to save information about users that deleted any rows on any tables. the table fields are like this :
create table LogDelete
(
pk int identity(1,1) primary key,
TableName varchar(15),
DeleteUser nvarchar(20),
DeleteDate datetime
)
Actually i wanna create a trigger that fire on all tables on update action that on every update write proper information on LogDelete Table,
at now i use a stored procedure and call it on every update action on my tables.
Is there a way to do this?
No. There are 'event' triggers, but they are mainly related to loggin in. These kinds of triggers are actually DDL triggers, so they are not related to updating data, but to updating your database scheme.
Afaik, there is no trigger that fires on every update. That means that the way you are handling it now, through a stored procedure, is probably the best way. You can create triggers on each table to call the procedure and do the logging.
You might even write a script that creates all those triggers for you in one run. That will make the initial creating and later updating of the triggers a bit easier.
Here is some MSDN documentation, which says (in remarks about DML triggers):
CREATE TRIGGER must be the first statement in the batch and can apply to only one table.
There is no magic solution for your request, not such a thing as event triggers to all DML (INSERT, UPDATE, DELETE) as you like, but there are some alternatives that you can consider:
If you are using SQL Server 2008 or after, the best thing you could use is CDC (Change Data Capture), you can start with this article by Dave Pinal, I think this will be the best approach since it is not affected by any change in structures.
Read the log file. You'll need analyze it find each DML activity in the log and so you could build an unified operation to log the changes that you need, obviously this is not on-line and not trivial
Same as option two but using traces on all the DML activities. The advantage of this approach is that it can be almost online and it will not require analyzing the log file, you'll just need to analyze a profiler table.
To eliminate the potential problems with triggers, what are some of the alternatives one may use to get the same functionality of reacting to an event fired on a INSERT action?
I have a database that needs to have some additional values added on insert. The INSERT is controlled by compiled code and cannot be changed.
EXAMPLE: The program inserts a string and from this string I need to supply an integer to a new field that points to a look-up table.
If there is an alternative to a trigger then please let me know some pros and cons to any alternative. The main reason for this is that Triggers are not allowed in our DB standards.
SQL Server 2008 Enterprise
Alternatives to plain-old inserts can be done using stored procedures, triggers, or more complicated insert statements. Since you have no control over the insert statements, you won't be able to use stored procedures, either. So your only option is triggers.
What you're describing is precisely why triggers exist. If you need to accomplish this task then it can't be done under the constraints you've listed.
Triggers are the best option. Get the DB standards changed (or at least allow this task to be an exception) because they are flawed.
How do you determine your integer, based on the string being inserted?
One alternative you might want to look into are computed columns in SQL Server. If that matching is a pretty straightforward one (e.g. extract the character 10 through 14 from the string) or something like that, you could create a computed column to do so automagically - no trigger needed.
You can even make those computed columns persisted (physically stored as part of your tables) and create indices on these fields!
Computed columns are available from SQL Server 2000 on, persisted columns from SQL Server 2005.
I know that was asked a long time ago. With SQL Server 2008 "Change Data Capture" MSDN was introduced. Another alternative, but only valid after 2008 R2 is "Change Tracking" Setting up change tracking. While you can query rows to filter (look here) what was changed, this may or may not "resolve" the issues with triggers.
Triggers are the way to perform an action after an event (insert, update, delete) occurs on a SQL table; the fact that they exist makes it unlikely that there's any tenable alternative. It's unfortunate to say, but the DB standards you say are in place effectively prevent you from doing what you want without having some process running that periodically watches your table and then performs the action you need it to, or changing all your database CrUD operations to go through stored procedures which do what you want them to. Since you say that the latter isn't possible -- you can't change the INSERT statements -- then you're left with just triggers.
SQL Server 2005 now has something called an OUTPUT clause that can do additional processing after an INSERT (or other action) occurs. This article covers more of the details. For instance, if you need to do processing after an INSERT command, you could do something like...
INSERT INTO Contact
(FirstName, MiddleName, LastName)
OUTPUT INSERTED.ContactID, INSERTED.FirstName, INSERTED.MiddleName, INSERTED.LastName
INTO Contact_Audit
VALUES
(##SCOPE_IDENTITY, 'Joe', 'D.', 'Schmoe')
And you'd have your uniquely created ID for them available.
If you want to use data history then go with system version history tables. you don't need to create trigger explicitly.
https://learn.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables?view=sql-server-ver15
Your options are limited here. I think your only other alternative is to do your inserts via a stored procedure call and put the extra code in the stored procedure.
I think we can implement trigger with hibernate event system nowdays despite of the performance impact.I didn't do that before.but I think it works