How to validate duplicate entry in SQL using PHP? - php

I'm trying to validate and show a message to the user whenever a duplicate entry is submitted. Also, I am using this validation to generate an entry in my database whenever a user registers for the first time. I'm aware my code might be SQL Injection compromised, but I'm not worried about that in this exercise.
My table has a primary key "RUT", it is unique. I need to validate if the user is submitting a RUT already in the database.
Code:
$datos;
#$db = mysqli_connect("localhost","root","","speedomart");
if($db){
$sql = "insert into cliente values('".$rut."','".$nombre."','".$apellido."','".$correo."','".$pass."')";
$query = $db->prepare($sql);
$query ->execute();
if(mysql_errno() == 1062){
$datos = array('mensaje' => "no fue posible insertar datos");
echo json_encode($datos);
}
else{
$sql2 = "insert into carrito values(NULL,'".$rut."')";
$query = $db->prepare($sql2);
$query ->execute();
$datos = array('mensaje' => "Registrado correctamente");
echo json_encode($datos);
};
}
else{
$datos = array('mensaje' => "No hay conexion.");
echo json_encode($datos);
};

I am assuming that it is the email which can not be duplicate. So when you submit the form you can first select the data using the particular email id as follows:
$sql = "select *from table where email ='".$email."'";
$query = $db->prepare($sql);
$user_array = $query ->execute();
if(count($user_array) > 0){
//You can use insert query here
}else{
//email already exist.
}

Two comments:
(1) If "the nature of the data is" that there should be no duplicates for any field or particular combination of fields, then you should define a UNIQUE index so that SQL will never allow a duplicate to be inserted by any means. (You will not be able to create such an index if any duplicates now exist.) This is a "data integrity rule" which SQL will enforce for you.
(2) SQL injection is trivially easy to avoid here, and you should always do so. Simply use parameters in your SQL query text: ? (without quotation marks ... this not a one-character literal string). Now, you simply supply an array of parameter-value substitutions each time you execute the prepared SQL. The parameters will be substituted left-to-right in order of occurrence. This not only avoids injection problems but also is more efficient: the statement does not have to be re-prepared each time. Please just get in the habit of doing this all the time ... you'll be glad you did.

IF Exists(SELECT 1 FROM Table WHERE FieldValue='$') THEN
--record exists, get ID you need.
BEGIN
SELECT TableID FROM Table WHERE FieldValue='$';
END;
ELSE
BEGIN
INSERT INTO Table (FieldValue) VALUES('$');
SELECT LAST_INSERT_ID() AS TableID;
END;
END IF;

Related

Can While Loop be used for Error Catching?

I am using try catch algorithm when inserting a record to a MySQL table. My scripting language is PHP.
try {
/*
UDID generation algo goes here.
*/
$sql = "INSERT INTO tablex (udid, name)
VALUES ('$udid', 'Doe')";
$conn->exec($sql);
echo "New record created";
}
catch(PDOException $e)
{
echo "Error"
}
$conn = null;
How do I re-write the above so that instead of try catch, I use a loop. If there is an error, try again. Break out of the loop if there is no error.
There is "While True" but I don't know if the "Try Catch" should be part of the While True loop..
The purpose of this is to save a UDID - the unique value is set in MYSQL. If I generate the same value, I may get the error. Hence, why the loop.
I feel like you're going about this the wrong way. Instead of trying to insert a value that might not be unique, I would try to see if that value exists first. You could perform a query such as
do {
//$udid = create uuid
$query = "SELECT COUNT(*) FROM tablex WHERE udid = :udid";
$statement = $pdo->prepare($query);
$statement->bindValue("udid", $udid);
$result = $statement->fetchAll();
} while ($result["count"] === 1);
//insert row into table
This is just off the top of my head and it can be refactored even better. You could also leverage your database to generate the UDID for you if you prefer. You could run a query to get all of the udid's from your table and just run in_array to check to see if the value is there, then you're only hitting your database twice. Anyway, you really don't want to try to abuse a try catch like that.
mysql has a function for something like this you would add an "ON DUPLICATE KEY UPDATE" to your insert statement
Example:
INSERT INTO table(x, y, z) values (?, ?, ?) ON DUPLICATE KEY UPDATE x=?;
Also see this link for more info:
http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

PHP MySQL PDO duplicates

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
}

mysqli insert - but only if not a duplicate [duplicate]

This question already has answers here:
if not exists insert in MySql
(2 answers)
Closed 9 years ago.
I'm a Java developer who just got handed the task of "some quick easy DB stuff" - except I don't know much about PHP/MySQL...I need to insert a record into a DB - but only if the email field doesn't match one that already exists in the DB. Here's what I've gleaned so far for my PHP code:
// Grab the values from the HTML form:
$newUserName = $_POST['newUserName'];
$newUserName = $mysqli->real_escape_string($newUserName);
$newUserEmail = $_POST['newUserEmail'];
$newUserEmail = $mysqli->real_escape_string($newUserEmail);
// Now search the DB to see if a record with this email already exists:
$mysqli->query("SELECT * FROM RegisteredUsersTable WHERE UserEmail = '$newUserEmail'");
Now I need to see if anything came back from that search - meaning the email already exists - and if so I need to alert the user, otherwise I can go ahead and insert the new info into the DB using:
$mysqli->query("INSERT INTO RegisteredUsersTable (UserName, UserEmail) VALUES ('".$newUserName."', '".$newUserEmail."')");
Any ideas?
Working from your code, this should point you in the right direction. there are, perhaps, better ways to structure your database that will make better use of it.
<?php
$mysqli = new mysqli("localhost", "iodine", "iodine","iodine");
// Grab the values from the HTML form:
/*
$newUserName = $_POST['newUserName'];
$newUserName = $mysqli->real_escape_string($newUserName);
$newUserEmail = $_POST['newUserEmail'];
$newUserEmail = $mysqli->real_escape_string($newUserEmail);
*/
$newUserName = "Test User";
$newUserEmail = "test4#example.com";
// Now search the DB to see if a record with this email already exists:
echo "SELECT * FROM RegisteredUsersTable WHERE UserEmail = '$newUserEmail'", "\n";
$result = $mysqli->query("SELECT * FROM RegisteredUsersTable WHERE UserEmail = '$newUserEmail'");
if (!$result) {
die($mysqli->error);
}
echo "num_rows = ".$result->num_rows."\n";
if ($result->num_rows > 0) {
echo "Duplicate email\n";
// do something to alert user about non-unique email
} else {
$result = $mysqli->query("INSERT IGNORE INTO RegisteredUsersTable (UserName, UserEmail) VALUES ('".$newUserName."', '".$newUserEmail."')");
if ($result === false) {echo "SQL error:".$mysqli->error;}
}
?>
Consider putting a unique index on this particular table. The following code will add the index and remove any current duplicates:
ALTER IGNORE TABLE `RegisteredUsersTable` ADD UNIQUE INDEX unique_email (`UserEmail`);
Once this is added, use INSERT IGNORE or INSERT...ON DUPLICATE KEY UPDATE. They will only preform the insert if there is no duplicates.
$mysqli->query("INSERT IGNORE INTO RegisteredUsersTable (UserName, UserEmail) VALUES ('".$newUserName."', '".$newUserEmail."')");
Mysql will throw an error because the email is already in the database. However, the IGNORE command is telling the script to not pay any attention to errors for this query because, in this case, you expect it for a duplicate row.
Also, there is a way to alert your user with a failure or success message, even with INSERT IGNORE. Use MYSQL LAST_INSERT_ID(). If an ID was given, it was inserted. If not, then the email was already there (or there was another error).
As for your first query, to soften the load on servers, use count() instead.
$mysqli->query("SELECT count(*) FROM RegisteredUsersTable WHERE UserEmail = '$newUserEmail'");
This way, you can just check if you've gotten a result higher than 1. If the result is greater than 1, then the username exists (Since a row was returned).
To check the data returned, you need to simply execute the statement, then fetch the results. Part of the fun is learning, so here's the documentation

insert a record or if exist then update in mysql doesnt work

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"];

Use PHP or SQL for error check

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).

Categories