Check for Duplicates in a Database Before Entering Data - php

Before Entering data into a database, I just want to check that the database doesn't have the same username in the database already.
I have the username in SQL set as a key, so it can't be duplicated on that end, but I am looking at finding a more user-friendly error message then "KEY already exists".
Is there are simple way to check if the variable value already exists in a row?

Either preform a check before attempting the insert, or catch the exception and display it in a more clean and user-friendly way in your application.
Edit: Take a look at this tutorial on PHP exception handling. You probably want to wrap your query execution in a try-catch block, like so:
try
{
// do your query here (it's been forever since I've used PHP)
}
catch(Exception $e)
{
// display a clean error to the user
}
Except, instead of catching a general type Exception, you'll want to figure out what sort of exception you're actually getting (something like MySQLDuplicateKeyException, or whatever it may be - echo the exception you get when testing, and use that). This way, you won't display an error informing the user of an existing username, if in fact, there is another problem (like a DB connection error, for instance).
Good luck!

The technique to check whether data exists is to issue the query:
SELECT COUNT(*) FROM YourTable WHERE YourKeyCol = YourKeyValue
and then examine the first returned column of the only returned row in the dataset. If it contains 0, the data wasn't there, otherwise it was found.
But as others have pointed out, you can just go ahead and issue your INSERT. Examine the error code to determine whether it failed. This is more performant because, for those cases where the data is not already in the database, you will execute only one query instead of two.

There might be a special way to do this depending on what RDBMS you are using.
For example, using MySQL, you can say
INSERT INTO table (username,value) VALUES ('foo',123) ON DUPLICATE KEY UPDATE value = 123;
Since you've already set username to be a unique key, this will insert ('foo',123) into table only if foo is not already in the table. If it does exist, then the value is updated.
Or, you could use something like
INSERT IGNORE INTO table (username,value) VALUES ('foo',123)
which ignores the insert if foo is already in the table.

I can think of two ways to do this.
The first is simply to do a select statement beforehand on that username to detect any duplicates. If a row is returned then you know that that username already exists.
The other is that you can get mysql to return the error number using mysql_errno, you can then simply have an if statement that checks for a specific error number. The only problem with this that it may not indicate which field is a duplicate of the key.
I have used a pre select statement in my scripts.

Related

Mysql INSERT IGNORE INTO ignore only one column

I have used the following sql on my website
$sql = "INSERT IGNORE INTO names VALUES ('akku#gmail.com','19','akku');";
This code only works if both three values are same. .I need to Insert the data to the database only if first value (akku#gmail.com) is not exists on the database. Else it should display "email already exists". Also it should work even if the second and third values are different.
Make the email address the primary key of your table. Don't use the IGNORE keyword in the statement. Catch the error that arises when a duplicate email is entered (attempting to insert the duplicate into MySQL will cause an exception in your front end code) and display an "email already exists" message
The database doesn't care what your values are so I don't really understand what you mean by "it only works if the last two are he same" unless you have a trigger that raises an error if you attempt to insert differing values for your last two columns
You can use SELECT first to find if the data is there, and then insert if it isn't or update if it is. This would be the best way as you can use php to handle any case using this.
Second way would be to make first value primary key. This way your insert would throw an error and you can catch that to do whatever you want.
Third way, in which if you want to update data if it exist would be using- INSERT ON DUPLICATE KEY UPDATE https://mariadb.com/kb/en/library/insert-on-duplicate-key-update/

Finding out why a mysqli INSERT failed - which unique index was duplicated?

I'm currently writing a REST style php server that needs to allow user registration. The basics are working but I am focusing on error handling now. My users table has a unique index on the 'user_name' field and the 'user_email' field. When I try to insert a duplicate value I can read the error and get a string like
Duplicate entry 'noggin182' for key 'user_name'
I need to translate this into something that I can display to the user. Is there is an easy way to get more details of why the insert failed? I could easily parse the string to find out but this feels messy, things would break if the string gets changed in an update or the language changes.
If you're trying to do what I think you're trying to do, it might be worth taking a different approach, and putting the logic for adding a user in to a Stored Procedure, in a single transaction, and doing any checks beforehand to see if the user already exists.
You could then return your own logic as to whether the user added, or a reason why it couldn't be. Or raise your own error or something maybe.
The error message normally contains more information
ERROR 1146 (42S02): Table 'test.no_such_table' doesn't exist
A numeric error code (1146). This number is MySQL-specific and is not portable to other database systems.
You could return this number and display the corresponding text on the client but normally what we do is catch the exception and log the full stacktrace but return only simple text to the client.
Your users don't want to know that there was an attempted duplicate key insert as they can do nothing about that they want to know that the save failed and that the administrator of the site has been alerted to the problem as is looking into it and a solution will be forthcoming..
because of unique key added on that column.
unique does not allow duplicate data.
try this:
$query="select * from table where user_email='".$_POST["user_email"]."'";
$result=mysql_query($query);
if(mysql_num_rows($result)>0)
{
your insert query.....
}
else
{
echo "email already exists";
}

Ignore errors and mismatch types while inserting row to mysql

I have a MySQL database as above, with all Null set to Yes except UID. The data will be collected from a survey and it works when all the entries fit the "Type" defined by MySQL.
Here's a problem though, sometimes users may input something that doesn't fit the criteria, for e.g.: "a user input varchar(4) in age instead of int(3)".
What happens now, is the whole row will not be inserted as a result of that single error. What I want to do is to have a way, so that only age's entry will be omitted. I thought setting Null to Yes can solve the problem but apparently it can't. Please help :)
ALLOW NULL doesn't mean "if invalid, insert NULL". You should validate the data prior to the insert.
You can use the IGNORE key word when inserting like this:
INSERT IGNORE INTO tbl
Which provides the following functionality:
Data conversions that would trigger errors abort the statement if
IGNORE is not specified. With IGNORE, invalid values are adjusted to
the closest values and inserted; warnings are produced but the
statement does not abort. You can determine with the mysql_info() C
API function how many rows were actually inserted into the table.
So data conversion errors will not abort, but constraint errors will abort like a duplicate unique or primary key.
In most cases you should be validating the data yourself to make sure it's the right type, and possibly giving the user an error message if they enter something invalid. Use the simple function is_numeric($age) to find out if age is a valid number. If it is, you can go on to use $age = intval($age) to prevent some smartypants from entering their age as 18.1667. If $age isn't a number, you can manually set it to null and it will be entered into your database that way.
A slightly faster way would be to just include the code (int)$age as part of your insert query. However, casting a string to an int gives 0, and for some fields 0 may also be a valid response! So don't do that.

ORM (RedBean) and duplicate keys

I am currently using RedBean for ORM in my models.
I need to insert data into a MySQL table where one of the columns is set to unique.
Currently, data is inserted via a form like so:
//Create
$object = R::dispense('object');
//Need to check if supplied name is a duplicate
$object->name = $name
$object->description = $description
//Save
R::store($object)
Now the problem is that if $name was not duplicated in the database, everything goes well. If it is a duplicate, I can catch the exception and get the SQL error code: 23000
If I echo the exception, I get:
[23000] - SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'abc' for key 'name_UNIQUE'
Another problem is that if I have multiple fields which are set to UNIQUE, the exception will only tell me the first field that's duplicated. Therefore, in order to get the next field, I need to make sure the user corrects the first duplicate and run the query again.
This seems to be quite inefficient. I need to be able to check if the user has inserted duplicate data in multiple fields while not executing too many SQL statements.
What are some best practices for doing this? Also, what's the best practice when it comes to returning whether the action was a success, or if on failure, why and which fields back to the controller?
Thank you :)
You must first perform a "select" to check that the unique entries do not already exist, there is no other way... If you do not want to perform multiple requests from you code, you can implement a stored procedure.
It allows you to perform multiple requests within the same transaction, and that limits the network overhead.
It will also allow you to manage multiple kinds of error (through error codes AFAIR), which will give you a way to identify clearly the problematic field.
Check out this link
Hope that helps !

MySQL Insert: Test first?

As an example, when inserting a record into a table with a unique index, is it best to test first? e.g.,
$mysqli->query('SELECT email FROM tblUser WHERE email = 'foo#bar.org');
then make sure 0 rows are returned, then do the insert?
$mysqli->query('INSERT INTO tblUser ...');
Or is it better to just skip the test and handle the error in the event there's a duplicate entry?
THANKS!
It's better to insert and handle any duplicate key errors.
The reason is that if you test first, some other client can still insert the value in the brief moment between your test and your insert. So you'd need to handle errors anyway.
Broadly speaking, there are three ways to handle this situation with a single query (fewer queries is usually a good thing to shoot for), but none of them is a universal "best way". Which you should use depends on your needs.
The first is, as you mention, running the INSERT … blindly and handling any errors PHP. This is the best approach when a duplicate key indicates a procedural problem (a bug in the software, a user trying to register a name that's already been used, etc.), as it allows you to perform additional operations before committing to a database update.
Second, there is the INSERT IGNORE … syntax. I would tend to call this the least commonly-useful approach, as it discards your INSERT completely if the key already exists. Primarily useful when a row (or rows) may or may not have been added to the table previously, but the data is known not to have changed.
Lastly, you can use an INSERT … ON DUPLICATE KEY UPDATE … statement. These can get rather verbose, but are very handy, as they allow you to insert data into your table without worrying about whether older data exists. If so, the existing row is updated. If not, a new one is inserted. Either way, your table will have the latest data available.
MySQL supports insert ignore if you want to ignore an insert that creates a row that has a key value that already exists for another row.
Just make sure there's a unique index on email in tblUser and do
$mysqli->query('INSERT IGNORE INTO tblUser ...');
It depends on if you want to ensure that the values you are inserting don't exist or not. If you have a unique key on the file then it is going to be important that you do not create a duplicate key (which will throw an error). A lot of times too you want to test to see if a record exists, if so returning the primary key of the record so you can update the record and if not then inserting the record.
But if you have no unique keys and don't care if information is duplicated across a field or combination of fields then it isn't necessary and can save a little time. It just depends on the situation.
HTH
Often depends on what rules about data duplication apply.
In your example, does your app permit more than one user to have the same email address? If not then you'd need to perform that check.
You definitely want to test first and you may want to test a few things so you can tell the user what went wrong.
For example I just finished a job where a user needed a unique username and a unique email address.

Categories