MySQL Trigger After Any Changes - mysql

I am looking for a way to create a trigger after any changes occur in a table on any row or field.
I want for my web app to automatically refresh if they're have been any changes to the data since it was last loaded. For this I need a "modified_on" attribute for a table which will apply to the whole table, not just a row.

Not sure what database triggers have to do with this problem, as they are not going to be able to trigger any behavior at the web application level. You will need to build logic in your web application to inspect the data looking for a change. Most likely, this would take the form of some some-client triggered refresh process (i.e. AJAX), which would need to call a application script that would take information from the client on when it last checked for an update and compare it to the most recently updated row(s) in the table. As long as you have a timestamp/datetime field on the table and update each row when it is updated, you can retrieve all updated rows via a simple query such as
SELECT {fields} FROM {table}
WHERE {timestamp field} > '{last time checked}'
I you want, you could use this to only update those rows in the application view which need updating rather than re-rendering the whole table (this would minimize response bandwidth/download time, rendering time, etc.). If you simply want to check if the table has been updated from some certain, but don't care about individual rows, you can just check that the above query returns 1 or more rows.
If you don't want the client application view to have to check at regular intervals (as would likely be done with AJAX), you might also consider websockets or similar to enable bi-directional client-server communication, but this still wouldn't change the fact that your server-side application would need to query the database to look for changed records.

Related

Duplicate DB Entries on Double Request even after SELECT First

I am not sure if I have put right words in title to explain. But here it is.
Application: Coldfusion/MySQL
Problem exceptionally occurred during bad internet reception which triggered double requests before the first one completed. In result two database entries were made.
Application is only handling double request with a SELECT query first to check if there is already a same record in db. In that case old record is updated with an UPDATE statement. Otherwise an INSERT statement is used to insert a new record. The SELECT/INSERT/UPDATE are enclosed within CFTRANSACTION.
<cftransction>
<cfquery></cfquery> //SELECT
<cfif SELECT.found>
<cfquery></cfquery> //UPDATE
<cfelse>
<cfquery></cfquery> //INSERT
</cfif>
</cftransaction>
In most cases when there is some delay in two requests, it works fine. To reproduce the problem,
I first tried initiating two simultaneous requests via browser and it didn't trouble in many tries.
To make two requests quick, I used two post statements right after one on the page (it's an AJAX app). It also worked as expected as second request was only updating the previously entered record.
What I could do to make those two requests even quicker, I reached out at the server itself (where both the ColdFusion and MySQL are running) and opened the browser. Now one browser request with two post statements started frequent double entries.
Above code might insert two entries when the REQUEST.2 SELECT runs before REQUEST.1 INSERT. What could be possible solution on the server end?
Handling on the client side with disabling subsequent requests before the first request completes. but want to secure it on the server.
So I used the solution porvided by #Leigh in comments to original question. Just answering to make it standout and what other things I had to do to actually use this solution.
Instead of the SELECT .. INSERT approach have you looked at db options such as REPLACE or INSERT ... ON DUPLICATE KEY UPDATE? – Leigh
While both the solutions seemed good to solve the problem but REPLACE was more attractive as it only required me to change "INSERT" keyword in the queries with "REPLACE"
With a quick overview from the docs, REPLACE exactly replaces and works like INSERT statement but performs the purpose only when a row is found with duplicate PRIMARY KEY or UNIQUE index.
1- As I required three columns to be unique in that sense which I was using in a WHERE clause with SELECT before inserting them. I had to add a UNIQUE index on those three columns before REPLACE could work to restrict duplicate rows.
2- If duplicate row found, REPLACE first deletes the old row and then inserts the new one. This process also could loose some values from other columns in the table. But in my application, these columns are updated on every REQUEST while the values for those are derived from other tables. So it was not problem for me as the data can be updated for the new row inserted.
The <cftransaction> will group together the select + insert/update queries but will not prevent a second+ request from executing, even from the same browser before the transaction is completely finished.
I have run into similar problems with the IE browser. The user could spam-click the submit and IE would submit for each time the submit button was clicked.
The most common solution that I've employed is to disable the submit button after it is clicked, or replace (hide it) it with a message that says something like "please wait, submitting form...". I've used JavaScript/jQuery for this task. It isn't 100% effective and does depend on what browser is being used and if JavaScript is enabled.
Another option is to use a named <cflock> to make sure that code can only be executed as a batch. This could cause a performance bottleneck if several people are using the form at the same time. So, I would plan to use a session variable as part of the named <cflock> name. That way the lock is unique to each user.
Below is a CF 11 example:
<cflock name="lckInsUpdt_#listFirst(session.sessionid, '.')#" timeout="300" throwontimeout="no" type="exclusive">
<cftransction>
<cfquery></cfquery> //SELECT
<cfif SELECT.found>
<cfquery></cfquery> //UPDATE
<cfelse>
<cfquery></cfquery> //INSERT
</cfif>
</cftransaction>
</cflock>

Editing table row data populated with with classic asp

I'm hoping this will be a rather simple question to answer, as I'm not looking for any specific code. I have a table on a classic asp page populated from an sql server. I've just set the table up so that each row is clickable and takes you to a page to edit the data in the row. My question is this: Would I be better off trying to use the recordset that populated the table or should I reconnect to the db and pull just the record I want edited.
As always; It Depends. It depends on what you need to edit about the record. It depends on How far apart your DB and site are from each other. It depends on which machine, if the DB and site are on separate machines, is more powerful.
That being said, you should make a new call for that specific record. The reason mainly being because of a specification you made in your question:
...and takes you to a page to edit the data in the row
You should not try to pass a record set between pages. There are a few reasons for this
Only collect what you need
Make sure data is fresh
Consider how your program will scale
On point 1 there are two ways to look at this. One is that you are trying to pass the entire record set across a page when you only need 1 record. There are few situations where another DB call would cost more than this. The other is you are only passing one record which would make me question your design. Why does this record set have every item related to a record. You are selecting way too much for just a result list. Or if the record is that small then Why do you need the new page. Why can you not just reveal an edit template for the item if it is that minimal.
On point 2 consider the following scenario. You are discussing with a coworker how you need to change a customer's record. You pull up this result set in an application but then nature calls and you step away from you desk. The coworker gets called by the customer and asked why the record is not updated yet. To placate the customer your coworker makes the changes. Now you are using an old record set and may overwrite additional changes your coworker made while you were away. This all happens because you never update the record set, you always just pass the old one from page to page.
On point 3 we can look back a point 1 a bit. let us say that you are passing 5 fields now. You decide though that you need a comments field to attach to one of your existing fields. do you intend to pass 2000 characters of that comment field to the next page? How about if each of the 5 need a comment field? Do you intend to pass 10,000 characters for a properly paged record set of 10? do you not do record set paging and need to pass 10,000 characters for a full 126 records.
There are more reasons too. Will you be able to keep your records secure passing them this way? Will this effect your user's experience because they have a crummy computer and cannot build that quick of a post request quickly? Generally it is better to only keep what you need and in most situations your result set should not have everything you need to edit.

Making a table that keeps logs of updates in mysql

I'd like to make a table that will keep track of a separate updating table on a day to day basis. For example, I have a table currently that keeps track of inventory and once a day I'd like to run a report that gives me information like how many new items were added, how many items were sold etc, and have each of those queries be stored as separate columns in the table. Is this possible? I've done some research trying to find a solution but haven't had any luck yet.
way 1: use database trigger, which could issue an event when you insert/update/delete a line,
way 2: in your code, like java, keep track of the insert/remove event in a memory counter(you can use spring aop to detect event, and use memory or memcache to keep the numbers), and use a scheduled program to write the data to a table, and reset them every day,(in java, jdk provide there class, or you can use quartz framework),

what happens to a change-data-capture instance when the underlying table is altered?

If I enable change-data-capture for a table, and then somebody else adds a column to the table, will my capture be affected? Will I still get updates for the original columns? For the new column?
What if a column is deleted?
(This answer from my colleague Steve, but he doesn't have a SO account so I'll post it...)
If you ADD a column, the CDC does not change ... you continue to receive updates on the same column set as before.
If you DELETE a column, the CDC continues to capture changes, but the deleted column will always have the value NULL.
If you ALTER a column, the CDC continues to capture changes, but values in the altered column will have the new column type.
From MSDN's About Change Data Capture (SQL Server)
"Handling Changes to Source Tables
To accommodate column changes in the source tables that are being tracked is a difficult issue for downstream consumers. Although enabling change data capture on a source table does not prevent such DDL changes from occurring, change data capture helps to mitigate the effect on consumers by allowing the delivered result sets that are returned through the API to remain unchanged even as the column structure of the underlying source table changes. This fixed column structure is also reflected in the underlying change table that the defined query functions access.
To accommodate a fixed column structure change table, the capture process responsible for populating the change table will ignore any new columns that are not identified for capture when the source table was enabled for change data capture. If a tracked column is dropped, null values will be supplied for the column in the subsequent change entries. However, if an existing column undergoes a change in its data type, the change is propagated to the change table to ensure that the capture mechanism does not introduce data loss to tracked columns. The capture process also posts any detected changes to the column structure of tracked tables to the cdc.ddl_history table. Consumers wishing to be alerted of adjustments that might have to be made in downstream applications, use the stored procedure sys.sp_cdc_get_ddl_history.
Typically, the current capture instance will continue to retain its shape when DDL changes are applied to its associated source table. However, it is possible to create a second capture instance for the table that reflects the new column structure. This allows the capture process to make changes to the same source table into two distinct change tables having two different column structures. Thus, while one change table can continue to feed current operational programs, the second one can drive a development environment that is trying to incorporate the new column data. Allowing the capture mechanism to populate both change tables in tandem means that a transition from one to the other can be accomplished without loss of change data. This can happen any time the two change data capture timelines overlap. When the transition is effected, the obsolete capture instance can be removed.
Note Note
The maximum number of capture instances that can be concurrently associated with a single source table is two."

Delete Mysql Values

I have a mysql table with several values that I output to a web page. How can I add an option to delete the value from the webpage? Like, have a button that deletes its respective value?
Add a button that posts back some row identifier, and have the code at the back-end delete the corresponding row.
If you want to be smarter, use AJAX to post the deletion request, while deleting the row in the UI with JavaScript.
If you want to be even smarter, use Comet to deliver table updates, and have the back-end that deletes the row broadcast the deletion event to all connected browsers, so that everyone viewing the row, including the user who requested the deletion, can see the change.
Execute a mysql delete statement.