Duplicate DB Entries on Double Request even after SELECT First - mysql

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>

Related

Complex fill in the blanks query in MS Access 2010

I have looked and haven't found a method on here to do this. I am assuming my search is skewed and I just missed it, if this is the case, please let me know.
Anywhooo, I have a large and unwieldy report coming out of SAP every day. Because it will often have some strangeness, we import that into an Access database so we can keep an eye on the stuff we need in our department. I am using a combination of 6 fields to create a primary key in Access. The information in those fields is about the only thing consistent I get out of this SAP report, but the remainder of the data can be considered dynamic and can change from day to day. Usually this is a matter of filling in a few blanks, Occasionally this is changing existing data, and on rare occasions, it may involve deleting data out of a handful of fields.
The SAP report is around 130 columns of data, So I'm looking for an efficient way to roll in the changes without overwriting what folks put in there manually.
EDIT:
Here is the way this is used. SAP (for reasons I'm not going to go into) sometimes will have bad data show up in the daily report. We are using Access to track and put the correct data in to something that we can generate much more accurate summaries. What the users put in is to be considered true and accurate.
The transactions we are tracking can take a long time to complete. Most take around 30 days to complete. That's why I will have blank fields on one day, and several of them to be filled in on the next. We might not get any for the next few days and then a bunch more are filled in later. That is the normal flow.
What I have to account for is the odd occasion where a mistake is made early in the process. At a certain point, an error will break SAP's ability to update anything at all in the report we have to use.
I have 3 fields set up that trigger what my users daily work is going to be. There is a logical flow so that user 1 completes what he needs to do and then that record will show up on User 2's report. These fields will also stop the general update process in an exception report if there is a difference in what is coming in from SAP, and what is already in my database.
What I am looking for is some way to systematically fill in blank fields, on existing records in access. I do not want to overwrite if something is in a field, only the null values. I can do this on one field at a time, but each record has about 130 fields. I'm wondering if there is a way I could do this in just 1 query?
Thanks all! I hope the edit makes more sense now
A simple google for "Access SQL update null values" could have yeilded you what you need. But if all you need to do is fill constant values into empty fields then something like:
UPDATE Table SET Table.field1 = VALUE
WHERE Table.field2 is NULL;
Now if this data is different for each record based on; say data from another field, then you may need to write some VBA to build that value/string for you. But otherwise if you are JUST updating null fields to include data, then a simple UPDATE statement will do
EDIT Based on new info:
So if I'm understanding correctly: you have two tables. One table with the blank fields and another table that contains the values you need.
If this is the case, you can use a similar UPDATE statement, but use an inner join to get the data you need from table B to fill in table A
UPDATE TableA INNER JOIN TableB ON TableA.KeyField = TableB.KeyField
SET TableA.NullField = TableB.NotNullField
WHERE TableA.NullField Is NULL;

MySQL Trigger After Any Changes

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.

MS Access trigger?

I have two tables named [Insert_Record] and [Delete_Record] in MS Access. Both tables have the same fields but one table has records whereas another table has no record.
Question: I want, whenever I delete any record from the table [Insert_Record] that entire record should automatically insert into another table, i.e: [Delete Record].
How can I accomplish this?
Access 2010 introduced event-driven Data Macros that are similar to triggers. The process described in the question can easily be done with an After Delete data macro on the [Insert_Record] table:
As I understand it, Access doesn't have triggers.
The best you can probably do is put this sort of logic into the forms that edit the table. In other words, handle the deleted event at the form level and put your insert logic there.
If you want triggers, you'll want to use a proper RDMS that supports them (MySQL, MS SQL, Oracle, many others).
EDIT: Another way to do this (which may or may not work for you) would be to add a boolean column 'IsDeleted'. That way, you can just logically delete a record instead of moving it to another table. The downside of this approach is the deleted records stay in the main table which could cause performance woes if there are lots of deletes.
Create an append query, to add records into the second table, that is executed in the On Delete Confirm event of the form you are using to delete the record from the first table.
I imagine this 'Delete' is button driven...
So program the button to first Insert the record into one table before deleting it.
Just add the VBA for the insert above the delete.
Another method which nullifies your need for another table entirely is just one column that is a boolean... Active Yes/No (Default to yes.)
If Active then it is not actually deleted when they hit delete, just set the flag to False then nothing is actually deleted, no SQL code is required and there is no risk, you can even have a column with the user who updated it print in another column
Me.Active = False
Me.UserName = 'CurrentUser Location here
Me.RecordSet.Requery
Then there is no risk of actually losing anything is there and you have a record of who flagged it last.
In the continuous form just add the Where flag Active = True then no false flags will show and it looks to the user base as if it was deleted.

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.

What are some alternatives to using a cursor in SQL Server 2008?

I've been creating imports that use SSIS to import data into a temp table, then using a stored procedure, steps through the data one by one with a cursor to process the data and insert information into 3 different tables. The inserts in the first 2 tables are complicated because if there is a record that already exists with the same data the record is not created. Whether the a record is inserted or not in the first 2 tables the ID of the record or matching record is returned to be used on the 3rd table. Is there an alternative to using the cursor?
Without seeing your current code it is difficult to know whether this would be suitable but I'd look at
the MERGE statement (allows actions to be specified for the different cases "when matched", "when not matched by target", "when not matched by source") and
the OUTPUT clause (allows you to capture the newly updated records for processing).
Hopefully some ideas from this will help. If you still need help avoiding a cursor, we need to see a better example of the processing you are doing in the cursor.
http://wiki.lessthandot.com/index.php/Cursors_and_How_to_Avoid_Them
This sounds like the perfect candidate for replacing a cursor with a combination of table variables and a while loop (which, multiple people have tested and confirmed, is nearly always more performant than a cursor).