Give the following table:
CREATE TABLE User (
Email VARCHAR(256) PRIMARY KEY,
Name VARCHAR(256),
);
I am trying to insert date into the table.
To check for duplication, should I use SQL to select email from user where email = $email and check the number or rows return is 1 and if it is 1, I just use php to print error message
OR
Should I just try to insert the data into table and use the following to print error?
mysql_query('INSERT INTO ...');
if (mysql_errno() == 1062) {
print 'no way!';
}
Which is a better way?
You can go for a query like this :
$sql = "INSERT INTO `table` VALUES ('$email','$Name')"
." WHERE NOT EXISTS (SELECT * FROM `table` WHERE `email`='$email')";
mysql_query($sql) or die("There's a duplicate.");`
Generally it's better to let the DBMS do the checking, because the functionality is already there and tested. You just need to handle the error messages.
If you insist on using your own code to do the checking, be prepared for many hours of brainstorming (given the complexity of the problem solved).
Related
I have the below code, which works perfect. What i want to do is to check the refNo first to see if there are duplicates entries in MySQL. If there is then appear a warning message, otherwise appear a "ok" message. How can i do that with PDO? Any help?
(include("db.php"));
$SQLquery = "INSERT INTO mydatabase (refNo, name)
VALUES ('".$_POST["refNo"]."', '".$_POST["name"]."');";
$STH = $dbc->query($SQLquery);
?>
edit: Hello guys,
i prefer not to add primary keys. Is there any other way?
Set up refNo as a primary key. You could also create it as unique but that defeats the purpose - your reference number appears to be a unique primary identifier. Perfect choice for a primary key.
Further, change your query
try {
$SQLquery = "INSERT INTO mydatabase (refNo, name) VALUES (:refNo, :name)";
$SQLquery = $dbc->prepare($SQLquery);
$SQLquery->bindValue(':refNo', $_POST['refNo']);
$SQLquery->bindValue(':name', $_POST['name']);
$SQLquery->execute();
} catch (Exception $e) {
die("Insert error");
}
$count = $SQLquery->rowCount();
if ($count == 1) {
echo "Record added!";
}
This binds the post value to prevent SQL injection too.
Edit: You could follow this up with $count = $SQLquery->rowCount(); which will be 1 if the insert was successful, as it appears you've edited your question since you posted it for more info.
If you want to do this without using a database level constraint, you'll need to do an extra SELECT statement before inserting into the table. But that gives you no absolute guarantees, as it might be two processes want to insert the same row at the same time and they will still succeed.
-- it'll look a little something like this; I'm not familiar with PDO but the structure should be the same
$selectQuery = "SELECT * FROM mydatabase
WHERE refno = '".$_POST["refNo"]."'";
$res = $dbc->query( $selectQuery );
if( $res->count() > 0 ) {
// this result already exists; show error
}
else {
// this result is new; put the insert query here
}
I have a table viewer with id, ip, date_last_viewed & blog_id as the columns. I'm first checking whether a particular entry having the same IP and blog_id is present or not. If yes, it updates the date. Else, it inserts a new entry.
My code is below:
$search_ip = mysql_query("SELECT ip FROM viewer WHERE ip = '".$_SERVER['REMOTE_ADDR']."' AND blog_id= '".$b_id."' ");
if ($search_ip == false){
$insert_ip = mysql_query("INSERT INTO viewer (ip, blog_id, date_last_viewed) VALUES ('".$_SERVER['REMOTE_ADDR']."', '".$b_id."', NOW())");
}
else {
$update_ip = mysql_query("UPDATE viewer SET date_last_viewed = NOW() WHERE ip = '".$_SERVER['REMOTE_ADDR']."' AND blog_id='".$b_id."' ");
}
The table is not inserting anything. What am I doing wrong here? Also, as I'm new to PHP programming, could someone tell me how to modify the above code to PDO?
You can actually do it in just one query.
MySQL has a special feature called INSERT ... ON DUPLICATE KEY UPDATE which basically insert if the record does not exist or update if it already exists. One thing you need to do is to define a unique column(/s)
INSERT ... ON DUPLICATE KEY UPDATE Syntax
Based on your statement, you need to define a unique constraint on both column,
ALTER TABLE viewer ADD CONSTRAINT vw_uq UNIQUE (ip, blog_id)
and execute this statement,
INSERT INTO viewer (ip, blog_id, date_last_viewed)
VALUES ($_SERVER['REMOTE_ADDR'], b_id, NOW())
ON DUPLICATE KEY UPDATE date_last_viewed = NOW()
As a sidenote, the query is vulnerable with SQL Injection if the value(s) of the variables came from the outside. Please take a look at the article below to learn how to prevent from it. By using PreparedStatements you can get rid of using single quotes around values.
How to prevent SQL injection in PHP?
Assuming your mysql_query executes correctly, it wont return false. What you should do is check the number of rows it returns. You can do this using mysql_num_rows.
Also, take note of the big red warning box at the top of the mysql_* man pages.
You should first add error handlers. Then move to mysqli_ and use prepared statements.
$search_ip = mysql_query( "SELECT ... " ) or die( mysql_error() );
if( mysql_num_rows($search_ip) == 0 ) {
$insert_ip = mysql_query( "INSERT ... " ) or die( mysql_error() );
}
else {
$update_ip = mysql_query( "UPDATE ... " ) or die( mysql_error() );
}
$search_ip will never == false, because it is a reference to the result. Use mysql_num_rows($earch_ip) instead. Also note that mysqli replaces this and your code is actually deprecated
That's not the right way to check if a query returned a value:
$search_ip = mysql_query("SELECT ip FROM viewer WHERE ip = '".$_SERVER['REMOTE_ADDR']."' AND blog_id= '".$b_id."' ");
if (mysql_num_rows($search_ip)==0) {
....
}
i want that if a record doesnt exist i add it otherwise update it... but it doesnt work, whats the wrong with this code:
<?php
$user_id=$_POST['user_id'];
$user_email="user_email";
$last_stage=$_POST['last_stage'];
$score=$_POST['score'];
$note=$_POST['note'];
$con=mysqli_connect("localhost","ferfer","Drfrj","ferfw");
$result = mysqli_query($con,"SELECT user_email FROM rating WHERE user_email='".$user_email."'");
$num_rows = mysqli_num_rows($result);
if ($num_rows > 0) {
//echo "exist";
mysqli_query($con,"UPDATE rating SET user_id=".$user_id.", user_email='".$user_email."', last_stage=".$last_stage.", score=".$score.", note='".$note."' WHERE user_email='".$user_email."'";
mysqli_close($con);
}else{
//echo "does not exist";
mysqli_query($con,"INSERT INTO rating(user_id, user_email, last_stage, score, note)VALUES (".$user_id.",'".$user_email."',".$last_stage.",".$score.",'".$note."') ");
mysqli_close($con);
}
?>
You can actually do it in a single query since MySQL has implemented INSERT ... ON DUPLICATE KEY UPDATE which basically INSERTs a record if it does not exists otherwise UPDATEs it.
The first thing you need to do is to add a UNIQUE column on the table. In your example I see that user_email is the column you are searching for existence. If this is not unique, you need to alter the table for UNIQUE constraint
ALTER TABLE rating ADD CONSTRAINT tb_uq UNIQUE(user_email)
after it has been implement, build a query like this,
INSERT INTO rating(user_id, user_email, last_stage, score, note)
VALUES($user_id, '$user_email', last_stage, score, '$note')
ON DUPLICATE KEY UPDATE
user_id = $user_id,
last_stage = $last_stage,
score = $score,
note= '$note'
As a sidenote, the query is vulnerable with SQL Injection if the value(s) of the variables came from the outside. Please take a look at the article below to learn how to prevent from it. By using PreparedStatements you can get rid of using single quotes around values.
How to prevent SQL injection in PHP?
$user_email="user_email";
should be changed to
$user_email=$_POST['user_email'];
And missing ( simbol, as #Yogesh Suthar said. You should also consider escaping characters in strings, using i.e. mysql_real_escape_string function.
you forgot ) here
mysqli_query($con,"UPDATE rating SET user_id=".$user_id.", user_email='".$user_email."', last_stage=".$last_stage.", score=".$score.", note='".$note."'
WHERE user_email='".$user_email."'");
^ // here
Better way is to use
REPLACE INTO `rating` (user_id,user_email,last_stage,score,note)
VALUES(#user_id,#user_email,#last_stage,#score,#note) WHERE user_email=#email
use also binding and prepared statements to make it more secure. Your code is very insecure because you have nor escape functions neither casting.
Example of using binding with PHP. $dbh is PDO object.
$stmt = $dbh->prepare("REPLACE INTO `rating` (user_id,user_email,last_stage,score,note)
VALUES(#user_id,#user_email,#last_stage,#score,#note) WHERE user_email=#email");
$stmt->bindParam('#name', (int)$user_id);
$stmt->bindParam('#user_email', $user_email);
$stmt->bindParam('#last_stage', $last_stage);
$stmt->bindParam('#score', $score);
$stmt->bindParam('#note', $note);
more on http://pl1.php.net/pdo
with binding you don't have to escape strings because it goes straight into the database layer without it having to be crudely spliced into the SQL statement.
The MySQL REPLACE statement works like the INSERT statement with the additional rules:
If the record which you want to insert does not exist, the MySQL REPLACE inserts a new record.
If the record which you want to insert already exists, MySQL REPLACE deletes the old record first and then insert a new record.
$user_email="user_email"; should be $user_email=$_POST["user_email"];
I'm using MySQL 5.1 hosted at my ISP. This is my query
mysql_query("
IF EXISTS(SELECT * FROM licensing_active WHERE title_1='$title_1') THEN
BEGIN
UPDATE licensing_active SET time='$time' WHERE title_1='$title_1')
END ELSE BEGIN
INSERT INTO licensing_active(title_1) VALUES('$title_1')
END
") or die(mysql_error());
The error is
... check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF EXISTS(SELECT * FROM licensing_active WHERE title_1='Title1') THEN ' at line 1
My actual task involves
WHERE title_1='$title_1' AND title_2='$title_2' AND version='$version' ...ETC...
but I have reduced it down to make things simpler for my problem solving
In my searches on this, I keep seeing references to 'ON DUPLICATE KEY UPDATE', but don't know what to do with that.
Here is a simple and easy solution, try it.
$result = mysql_query("SELECT * FROM licensing_active WHERE title_1 ='$title_1' ");
if( mysql_num_rows($result) > 0) {
mysql_query("UPDATE licensing_active SET time = '$time' WHERE title_1 = '$title_1' ");
}
else
{
mysql_query("INSERT INTO licensing_active (title_1) VALUES ('$title_1') ");
}
Note: Though this question is from 2012, keep in mind that mysql_* functions are no longer available since PHP 7.
This should do the trick for you:
insert into
licensing_active (title_1, time)
VALUES('$title_1', '$time')
on duplicate key
update set time='$time'
This is assuming that title_1 is a unique column (enforced by the database) in your table.
The way that insert... on duplicate works is it tries to insert a new row first, but if the insert is rejected because a key stops it, it will allow you to update certain fields instead.
The syntax of your query is wrong. Checkout http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html
Use the on duplicate key syntax to achieve the result you want. See http://dev.mysql.com/doc/refman/5.0/en/insert-select.html
Another solution
$insertQuery = "INSERT INTO licensing_active (title_1) VALUES ('$title_1')";
if(!$link->query($insertQuery)){ // Insert fails, so update
$updateQuery = "UPDATE licensing_active SET time='$time' WHERE title_1='$title_1'";
$link->query($updateQuery);
}
Here is the example I tried and its works fine:
INSERT INTO user(id, name, address) VALUES(2, "Fadl", "essttt") ON DUPLICATE KEY UPDATE name = "kahn ajab", address = "Address is test"
I am amazed to see so many useless codes and answers...
Just replace INSERT with REPLACE.
¯\(ツ)/¯
Is there a way to retrieve the ID of a record (primary key) after an insert when the mysql error returns a duplicate key?
E.G. How I would go about it:
$sql = "INSERT INTO table (`col1`, `col2`) VALUES ('$val1', '$val2')";
$result = mysql_query($sql);
if($result){
$id = mysql_insert_id();
}
else {
if(stristr(mysql_error(), "duplicate"){
$sql = "SELECT `id` FROM `table` WHERE `col1`='$val1' AND `col2`='$val2'";
$result = mysql_query($sql);
$row = mysql_fetch_array($result);
$id = $row['id'];
}
else {
die(mysql_error());
}
}
Here I've had to do two sql statements which not only take time and effort, but duplicate code as well.
I cannot use ON DUPLICATE KEY UPDATE because I want to update a different table using the either the last inserted id, or the id of the record that cannot be duplicated.
So, am I right in what I'm doing? Or is there a way to get the id of the row?
Thanks
MySQL will not tell you which record holds the original value, you'll have to find out yourself. Here you are some tips:
Looking for the duplicate substring in the text of the error message does not look very robust. You can just test the value of mysql_errno() against the code for duplicate entry, which is 1062 (you can find all codes in the manual).
The mysql extension does not provide a mechanism to find out name of the violated key, so you'll have to use the non-robust approach of parsing the text of the error message:
if( preg_match("/Duplicate entry '.*' for key '(.*)'/Ui", mysql_error(), $matches) ){
$violated_key = $matches[1];
}else{
throw new Exception('Could not find violated key name');
}
Alternatively, just run a previous query (there's no reason to avoid it):
SELECT id
FROM table
WHERE col1=... AND col2=...
FOR UPDATE
The FOR UPDATE clause will lock matching rows to avoid race conditions (assuming InnoDB).