MySQL/PHP check for duplicate before INSERT - php

I'm trying to check for an existing entry in MySQL before executing the INSERT statement. If the user enters a name already in the database (field is set to unique) then they should be prompted to re-enter the name.
The problem I'm having is that if the new entry matches a record in any form then the error message displays and no INSERT happens.
For example, if the user enters DUMMY_NEW and there is a record DUMMY_OLD they aren't able to add the record even though DUMMY_NEW does not exist in the table.
I've searched and tried other answers already but can't seem to get this to work.
Code with extraneous bits removed for clarity:
//Create connection to database using mysqli
$conn = new mysqli($dbhost, $dbuser, $dbpass, $db);
//Set variables according to user input on previous form
$Server_Name = $_POST['Server_Name'];
//Check for duplicate server name - if exists inform user else run INSERT ($stmt)
$checkdup = "SELECT * FROM dcr_table WHERE SERVER_NAME = '".$Server_Name."'";
$dupresult = $conn->query($checkdup);
if($dupresult = 1)
{
print "<br>Error! <p></p>";
echo "" . $Server_Name . " already exists in the DCR";
print "<p></p>Please check the Server Name and try again";
}
else {
//Define the INSERT statement
$stmt = "INSERT INTO dcr_master (Server_Name, Description,..., ... , ... )";
//Execute the INSERT statement
$conn->query($stmt);
//Success and return new id
echo "<br><p></p>Record Added!<p></p>";
echo "New id: " . mysqli_insert_id($conn);
//Drop the connection
$conn->close();
};
Edit:
I'm aware of the injection vulnerability. The MySQL account only has SELECT, INSERT and UPDATE rights to the table. The end user must supply the password or submit will fail. This is small app with limited user access at the moment. MySQL escape strings will be implemented after current issue is resolved.
Edit 2:
Using Hobo Sapiens method does work in reporting an existing entry however a new (empty) row is still added to the table. The record ID still auto-increments so what I get is id#300 - record, id#301 - blank, id#302 - record. Is this a result of the IGNORE in the INSERT statement?

Your code creates a race condition if two people attempt to create the same ame at the same time and you're not handling the fallout properly.
If you have set the SERVER_NAME column to UNIQUE then you needn't check for the existence of a server name before you perform your INSERT as MySQL will do that for you. Use INSERT IGNORE ad check the number of affected rows after the query has executed to find out if it worked:
//Create connection to database using mysqli
$conn = new mysqli($dbhost, $dbuser, $dbpass, $db);
//Set variables according to user input on previous form
$Server_Name = $_POST['Server_Name'];
//Define the INSERT statement with IGNORE keyword
$stmt = "INSERT IGNORE INTO dcr_master (Server_Name, Description,..., ... , ... )";
if ($conn->query($stmt) === false) {
die("Database error:".$conn->error);
}
// Check for success
if ($conn->affected_rows == 0) {
print "<br>Error! <p></p>";
echo "" . $Server_Name . " already exists in the DCR";
print "<p></p>Please check the Server Name and try again";
} else {
//Success and return new id
echo "<br><p></p>Record Added!<p></p>";
echo "New id: " . $conn->insert_id;
}
This is an atomic operation so no race condition, and it involves only one call to the database.
I recommend you use either the OOP style or the procedural style for mysqli_*() but don't mix them. Usual warnings about SQL injection apply.

Use mysqli_num_rows
$row_cnt = $dupresult->num_rows;
if ($row_cnt > 0) {
echo "There is a matching record";
}else {
//insert into table
}

This statement:
if($dupresult = 1)
will always return 1. You should first retrieve the first query result (if any), like so:
$row=$dupresult->fetch_array(MYSQLI_NUM);
and then compare the result against NULL:
if(!$row)

Related

How to store data from form builder in database

I am trying to create a form builder that will enable users generate survey form/page.
After the form is generated the form attribute is stored on a table.
Question 1:
Where can I store the form attribute knowing fully well that the number of fields user might add in the form is unknown.
Question 2:
Where and how do I store data submitted through the generated form when some one for example completes the survey form.
Should I create new tables on fly for each of the form attributes? If yes what if over a million forma are created which translates to a million tables.
Is this where multi-tenancy comes into play.
Please provide your answer based on best practices.
I think I get what you're asking, but why not create one table with 100 columns, labelled 1-100. Set a limit on the amount of fields a user can create(Limit 100).
Then, POST the fields and add a sql query to store the values...?
COMMENT ANSWER
If the user is already signed in filling this form I would personally do the POST request on the same page.
<?php if (isset($_POST['field1'])){
$valueforField1 = $_POST['field1'];
$valueforField2 = $_POST['field2'];
$valueforField3 = $_POST['field3'];
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "INSERT INTO Survey (field1, field2, field3) // I guess you would `have to add 100 fields here to accommodate the fields in your DB Also, you can set a default value in MySQL that way if field 56-100 is not set it has a value like 0 or add the value in this php file`
VALUES ('$valueforField1', '$valueforField2', '$valueforField3')";
if ($conn->query($sql) === TRUE) {
echo "New record created successfully";
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
$conn->close(); ?>
COMMENT ANSWER or if you want to wait for the user to log in you can store all the values in a SESSION variable.
<?php
session_start();
if (isset($_POST['field1'];)){
if (!(isset($_SESSION['email']))){
$_SESSION['field1'] = $_POST['field1'];
// You would have to do 100 of these
}
}
?>

display message to let user know that the value already exist

I want to display an error message if the insert already exists.
I've made name unique in the database and if I enter the same value, it does not insert. Just as I wanted. Here is my code:
$query = "INSERT INTO register(name) VALUES('$foo')";
mysql_query($query) or die('An Error occurred' . mysql_error());
Now I want to echo a message to let the user know that the value he has entered is already present in the database and will not be inserted. Anyone?
I take it you are collecting $foo from a form?
what I would do is an sql query of the table register collecting the name field then when you collect the name entered in the form and its posted you can run an if condition against the name field you have already gathered using the sql statement and if there is a name = to the name they enter on the field they can receive a message and exit before the sql injection into the register table.
The simpliest way:
$res = mysql_query($query):
if ($res)
echo 'Insertion ok';
else
echo 'error: name already exists';
A better way: do first a SELECT query to see if name exists or not.
Note: you should think about moving from mysql_* to mysqli_* or PDO
Try this :
$query = "INSERT INTO register(name) VALUES('$name')";
$user = mysql_query($query):
if ($user)
echo 'User Register';
else
echo 'User Already Exist';
As per Melon's comment, you should use mysqli.
// Create your connection
$mysqli = new mysqli($host, $user, $pass, $dbname);
// Do your query
$mysqli->query("INSERT INTO register(name) VALUES('$foo')");
if($mysqli->affected_rows == 0) {
// Your chosen method of alerting the user goes here
}
\\this first part collects name information from your table.
$name="SELECT name FROM register";
$name_query = mysqli_query($db_conx, $name);
$numrows = mysqli_num_rows($name_query);
if($numrows < 1){
echo "cannot find user";
header ("location: index.php");
}
while ($row = mysqli_fetch_array($name_query, MYSQLI_ASSOC)){
$name = $row["name"];
}
\\ this part gets the name from your form
if (isset($_POST['class']) && ($_POST['class'] !='')){
$foo = $_POST['foo'];
\\this part checks to see if the 2 values are equal
if ($name == $foo){
echo "This name has already been used try again";
\\this part then adds the name if its not already in the database
}else{
$query = "INSERT INTO register(name) VALUES('$foo')";
mysql_query($query) or die('An Error occurred' . mysql_error());
}
}
//then all you need to do is create your form to post the foo or name so it can be collected and passed through the querys.

prevention from duplicated input in a form

i have a problem, this is my code and when I add a new input with same name(nazov) it gets in database so it is duplicated. help please
if(isset($_POST['submit']))
{
//get the name and comment entered by user
$nazov = $_POST['nazov'];
//connect to the database
$prip=mysqli_connect("xxx","xxx","xxx","xxx") or die('Error connecting to MySQL server');
//insert results from the form input
$sql = "INSERT IGNORE INTO trieda (nazov) VALUES('$_POST[nazov]')";
$result = mysqli_query($prip, $sql) or die(mysqli_errno($prip) == 1062 ? "Trieda už existuje" : 'Chyba načítavania databázy.');
mysqli_close($prip);
}
you can set the filed you want to be unique in your MYSQL database. So if you try to add the same value you just get error.
You can also do a select first and check if data exists in database before you insert it.
You can do the lazy solution and use REPLACE instead of INSERT. REPLACE updates it, if it exists and insert if not.

Duplicate User accounts

I just recently asked a question and got my code fixed to the one below:
{
//Check if user already exists
$un_check = mysql_query("SELECT Username FROM users WHERE Username = '$un'");
if(mysql_num_rows($un_check) >0) {
echo "Username already exists";
}
else{
// Username Free
}
And when signing up it states that "username already exists" however, it still allows me to create the account anyway and it adds the same information to the database.
Is this a problem with my code or the database?
If you want to forbid entering the same values twice in a table create a unique index.
Checking for an existent entry is one thing - prohibiting that another row with same values can be inserted is another thing.
Adding such an index works like this:
ALTER TABLE `users` ADD UNIQUE `MY_UNIQUE_INDEX` ( `username` )
You can simply put the mysql query code that adds a user to the database inside the else block. This way, you will never insert into the database if the user already exists.
Another way is to murder the script. I mean, use the die(); function. This stops the script wherever you place it. You would want to insert it like this:
//Check if user already exists
$un_check = mysql_query("SELECT Username FROM users WHERE Username = '$un'");
if(mysql_num_rows($un_check) >0) {
echo "Username already exists";
die(); // Don't continue, as we don't want to insert a username
}
else{
// Username Free
}
Although this would work, if there is any other code that you still want to execute regardless of whether the username exists or not, simply place the code that inserts your users inside the else{} block as others have suggested.
Possible cases
Username is not unique in your database.
(If you don't want to change your table structure) Put the insert part of the code inside else statement.
if(mysql_num_rows($un_check) >0) {
echo "Username already exists";
}
else{
// insert new username
}
BTW don't use mysql_ functions. DEPRECATED
The problem is two fold.
First, strictly from the data storage - aka database - point of view, a problem is from poorly executed database design. If the username is a field that needs to be unique, then that should be declared in the database by adding a unique index to the username column. This creates the proper database design so no a new record cannot be added if the username value already exists in the table - hence the unique index.
Sencond, your code that is checking if the username exists. Is it still creating the account after you check the database for duplicates or are you just saying that you can duplicate usernames manually in the database? If the codes is still duplicating the user, then it could be because the result is an empty set - ie no results cuz no username exists and so it won't return number of rows so change > to >=.
I was Passed through the same problem and my solution was this
<?php
//Connection Script Start
$mysql_host = "localhost";
$mysql_user = "root";
$mysql_password = "*******";
$mysql_database = "db_name";
$connect = mysqli_connect($mysql_host, $mysql_user, $mysql_password, $mysql_database);
//Connection Script Ends
$un = "userabc";
$search = "SELECT * FROM table_name WHERE username='$un'";
$query = mysqli_query($connect, $search);
$i = mysqli_num_rows($query);
if($i==0){
//username free
}else{
echo "This username is already taken";
}
?>

Duplicate check before adding into database

I have a code which kinda works, but not really i can't figure out why, what im trying to do is check inside the database if the URL is already there, if it is let the user know, if its not the go ahead and add it.
The code also makes sure that the field is not empty. However it seems like it checks to see if the url is already there, but if its not adding to the database anymore. Also the duplicate check seems like sometimes it works sometimes it doesn't so its kinda buggy. Any pointers would be great. Thank you.
if(isset($_GET['site_url']) ){
$url= $_GET['site_url'];
$dupe = mysql_query("SELECT * FROM $tbl_name WHERE URL='$url'");
$num_rows = mysql_num_rows($dupe);
if ($num_rows) {
echo 'Error! Already on our database!';
}
else {
$insertSite_sql = "INSERT INTO $tbl_name (URL) VALUES('$url')";
echo $url;
echo ' added to the database!';
}
}
else {
echo 'Error! Please fill all fileds!';
}
Instead of checking on the PHP side, you should make the field in MySQL UNIQUE. This way there is uniqueness checking on the database level (which will probably be much more efficient).
ALTER TABLE tbl ADD UNIQUE(URL);
Take note here that when a duplicate is INSERTed MySQL will complain. You should listen for errors returned by MySQL. With your current functions you should check if mysql_query() returns false and examine mysql_error(). However, you should really be using PDO. That way you can do:
try {
$db = new PDO('mysql:host=localhost;db=dbname', $user, $pass);
$stmt = $db->query('INSERT INTO tbl (URL) VALUES (:url)');
$stmt->execute(array(':url' => $url));
} catch (PDOException $e) {
if($e->getCode() == 1169) { //This is the code for a duplicate
// Handle duplicate
echo 'Error! Already in our database!';
}
}
Also, it is very important that you have a PRIMARY KEY in your table. You should really add one. There are a lot of reasons for it. You could do that with:
ALTER TABLE tbl ADD Id INT;
ALTER TABLE tbl ADD PRIMARY KEY(Id);
You should take PhpMyCoder's advice on the UNIQUE field type.
Also, you're not printing any errors.
Make sure you have or die (mysql_error()); at the end of your mysql_* function(s) to print errors.
You also shouldn't even be using mysql_* functions. Take a look at PDO or MySQLi instead.
You're also not executing the insert query...
Try this code:
if(isset($_GET['site_url']) ){
$url= $_GET['site_url'];
$dupe = mysql_query("SELECT * FROM $tbl_name WHERE URL='$url'") or die (mysql_error());
$num_rows = mysql_num_rows($dupe);
if ($num_rows > 0) {
echo 'Error! Already on our database!';
}
else {
$insertSite_sql = "INSERT INTO $tbl_name (URL) VALUES('$url')";
mysql_query($insertSite_sql) or die (mysql_error());
echo $url;
echo ' added to the database!';
}
}
else {
echo 'Error! Please fill all fileds!';
}
As PhpMyCoder said, you should add a unique index to the table.
To add to his answer, here is how you can do what you want to do with only one query.
After you add the unique index, if you try to "INSERT INTO" and it result in a duplicate, MySQL will produce an error.
You can use mysql_errno() to find out if there was a duplicate entry and tell the user.
e.g.
$sql = "INSERT INTO $tbl_name (URL) VALUES('$url')";
$result = mysql_query($sql);
if($result === false) {
if(mysql_errno() == $duplicate_key_error) {
echo 'Error! Already in our database!';
} else {
echo 'An error has occurred. MySQL said: ' . mysql_error();
}
}
mysql_error() will return the mysql error in plain english.
mysql_errno() returns just the numeric error code. So set $duplicate_key_error to whatever the code is (I don't know it off the top of my head) and you are all set.
Also note that you don't want to print any specific system errors to users in production. You don't want hackers to get all kinds of information about your server. You would only be printing MySQL errors in testing or in non-public programs.
ALSO! Important, the mysql functions are deprecated. If you go to any of their pages ( e.g. http://php.net/manual/en/function.mysql-errno.php) you will see recommendations for better alternatives. You would probably want to use PDO.
Anyone who wants to edit my answer to change mysql to PDO or add the PDO version, go ahead.

Categories