INSERT command inserting duplicates - php

I am writing a quiz website.
What should happen is:
A page has a question on it and four buttons or a textbox.
When you click a button, it calls itself with
the answer number in the address
like: ?q=[question number]&a=[answer].
If the question
uses a textbox it POSTs the answer.
This code should then detect that
something has been sent to it and
write that to a database.
The user id is stored in a cookie.
There is also a key column in the database. the idea is that it stores all answers a user has submitted over time and users can change their answers.
<?PHP
mysql_connect("------", "------", "------") or die();
mysql_select_db("------") or die();
$q=$_GET['q'];
if(isset($_GET['a'])){
$a=$_GET['a'];
} else {
$a=$_POST['longanswer'];
}
if(isset($a)){
$u=$_COOKIE['id'];
if($qust['atype']==1){
mysql_query("INSERT INTO answers (`userid` ,`answer` ,`qid`) VALUES ($u, $a, $q);");
} else {
mysql_query("INSERT INTO answers (`userid` ,`answer` ,`qid`) VALUES ($u, '$a', $q);");
}
}
?>
I don't think it should matter, but later on on the code, it queries the database with the SELECT command.
When i run this code, it seems to enter 2 or 3 entries to the database. The trend seems to be that when i run the code it enters the previous answer, followed by the new answer.
Any help would be greatly appreciated. Thanks,
Logan

It seems like what you want to do is to allow only one answer per question per user. If that's the case, you'll want a UNIQUE constraint on your table on userid and qid:
ALTER TABLE answers ADD UNIQUE(userid,qid);
This will result in an error when you try to insert a row with the same userid and qid. If you want to allow users to change their error, you can change your INSERT query to:
INSERT INTO answers (userid ,answer ,qid) VALUES ($uid, '$answer', $qid) ON DUPLICATE KEY UPDATE answer='$answer'
This will prevent multiple records from showing up in the database, but multiple INSERTs might still be called from your PHP code. To fix that, we'd have to see some more of your code.

Another option would be to first try to retrieve the data you're about to enter into the database. If you find it, it's already there, so don't add it again. The suggestions for using constraints are sound but if the data you're trying to prevent duplicates of isn't easily added to the constraints or the data you don't want duplicates of is not exactly the same data (say just similar data) then this is another option.

The unique constraint mentioned by cmptrgeekken should definately be added if you only allow one answer per user, but then you must also handle the primary key violation if it occurs: Inform the user it has already replied OR replace the previous value, depending of how you want the site to work.
Also, Is for some reason the request triggered more than once? Maybe by javascript, or some other logic of yours? If duplicate answers appears when you only click once, this seems to be the case.
/B

Related

Maintaining history table for PHP Application

I want to maintain the history table for my application to track what all the fields were changed by the user.
The following is my bugs_history table structure -
id, bugsid, userid, field_changed, old_value, new_value, created_on, created_by
So my query is, when I'll update my form and submit, how to get the field name that was changed along with old value and new value. And add the modified changes in the above history table.
I have googled a lot for this but didn't get as per my requirments. Please let me know how to achieve this.
If you know the field names (you have a HTML form containing them, so you probably know the names) then build a list of them that you then loop through, building a new SELECT query to get old_value and then an INSERT query to save it. The select would order on created_on DESC and LIMIT 1.
But I see a clear problem here: concurrency. What happens when two users try to edit the same bug (with the same bugsid) at the same time? They would expect the old_value to be the same for both? Or should the two operations be executed sequentially? Or should the last one to edit be warned that he's trying to edit stale data? Which one would get the "latest" created_on?
This right here is your real problem, not writing the code that generates two SQL queries.

How to get id(Auto increment) of last row inserted

Can any one give me SQL query to get id (Which is primary key and auto_incremented) of last row inserted
I know there are many answers on this forum about this but no one consider about concurrency problems (or may be i just missed them) that if in mean time any other person execute insert query before getting me last id(from the code below) so this creates problem.
Here is the code that i think is not worked well in my situation
$result = mysql_query("
SHOW TABLE STATUS LIKE 'Media'
");
$data = mysql_fetch_assoc($result);
$next_increment = $data['Auto_increment'];
but here also a code may solve my problem
<?php
$id = mysql_insert_id();
?>
I just want to know if this code gets the insert id of row executed from actual user or the row id of user who inserted after the actual users row execution(or the last row of table).
I know this may be a silly question but i am a PHP developer doesn't know about MYSQL
Any help is appreciated.
mysql_insert_id will return the ID of the last row inserted in the transaction. If you create a new connection to MySQL for each page and don't use multiple threads within a page, mysql_insert_id should do what you want even in the presence of multiple INSERTs happening on different connections, provided you're not doing anything tricky within your PHP page.

Update post/row, instead of creating new one

I am building a system, where you can create blog posts for your website.
In there I have an ajax-function which is saving a draft of your post every two minutes.
In this way you're not losing your work if your computer or internet crashes.
But right now, it is saving a new row every time it auto-saves. How to I do, so instead of creating multiple rows, it is updating the row instead?
I have already tried with ON DUPLICATE KEY UPDATE, which didn't work. I think it might be because that it requires an unique field in the form. But the only unique in my database is the actual ID of the post/row.
This is the code I tried:
INSERT INTO blog (title, text, date)
VALUES ('$blog_title','$blog_text','".time()."')
ON DUPLICATE KEY UPDATE
title='$blog_title', text='$blog_text', modified_date='".time()."'
I have an idea, to get the post/row ID, when the post is auto-saved the first time. Here I could use mysql_insert_id(). Then this ID could be stored in a hidden input field and when it auto-saves again, it will see that there already is a post/row with that ID, and then it will just update instead of creating a new one.
Is that a good and safe solution, or should I do something else?
I can't seem to find a better one.
I have found some other similar questions, but they where using JSON, which I haven't worked with yet.
Hope someone can help me with this :)
When you create a new row, put the ID into a hidden field. Then the code to process the input can do:
if ($_POST['id']) {
// update existing row
} else {
// insert new row and put ID into hidden field
}
There's no need to use ON DUPLICATE KEY because you know from the input data whether it's indended as a new entry or an update.

Duplicate Id entry when a few users try to insert information into database - Php

When a few users try to insert a row into the table, this error appears:
(325 is the ID of the row. there is no auto increasment because I'm doing it myself because I need it.)
I remember that in asp they have the lock() method that actually prevents this kind of errors.
Is there something similiar in PHP?
Code will be added if asked although I dont think its required.
Thank you very much!
Now you see why you shouldn't assign IDs manually :)
Change your table to start assigning IDs automatically:
ALTER TABLE your_table AUTO_INCREMENT=last_assigned_id+1
If you insist on implementing a lock, you can use sem_acquire

Using mysql for a mini game

I'm new to mysql and wanted to consult about using mysql for my mini game. The idea is that from a game i get two variables - one is email, and another is score.
I'm thinking of creating a table with two columns and setting email as the primary.
The question is how do I make php script replace score value for a player which tries for the second time?
For example user#user.com scores 100 in the first try, script adds that as INSERT INTO table VALUES ($email,$score); then user tries another time, same script tries to add but gets duplicate error. Any help on script logic would be great! cheers
INSERT
INTO mytable (email, score)
VALUES ($email, $score)
ON DUPLICATE KEY
UPDATE
SET score = $score
This requires email to be the PRIMARY KEY of mytable.
It's difficult to answer without more details. If there is some sort of session or pre-registering of the player, you could insert a "default score" of zero, for instance, and then always update instead of insert. If not, Queassnoi's solution is probably the best.
You need to use UPDATE rather than INSERT
UPDATE table SET score = $newScore where email=$email
You are trying to add a new record with the same primary key, hence the error message

Categories