3

For preventing duplicate user names from being entered into the database and notifying the user, is it more standard/preferred to use exception catching when inserting or select query before inserting?

  1. Exception catching: if I try to insert the user input and the user name already exists then the SQL database will throw a primary key constraint violation exception. I can catch it if that happens and do whatever.

  2. Select Query: if it returns any tuples matching the user name then I won't bother with the insert. Then I can display the error message.

I suppose the main pro of using Exceptions here is there is less queries and lines (better speed?). However, I don't think this is an exceptional case since duplicates probably occur fairly often.

roverred
  • 1,841
  • 5
  • 29
  • 46
  • Doing a `SELECT` involves few lines and I personally find it much easier. Besides, IMO you shouldn't get an exception (something unexpected went wrong) out of it, it's something that requires logic handling, not errors handling, hence the SELECT. – Francisco Presencia Jul 01 '13 at 20:01
  • @dianuj, you added the `mysql` tag -- did the OP identify that as the RDBMS in use? – Bill Karwin Jul 01 '13 at 20:16
  • @BillKarwin I have removed the mysql tag and only added the `database` and `duplicates` tag `php` and `sql` were previously added – M Khalid Junaid Jul 01 '13 at 20:20
  • @roverred, it would be helpful if you tag this question with the brand of RDBMS you are using. `sql` refers to the language, not a specific implementation. If you use Microsoft SQL Server for example, please add the tag `sql-server`. – Bill Karwin Jul 01 '13 at 20:24
  • @BillKarwin Ok changed to mysql. My bad, I thought this case would be general enough. – roverred Jul 01 '13 at 20:43
  • 1
    @roverred, thanks for that. Yeah, auto-increment features are really not standardized between different brands of RDBMS. Every brand does it differently! Even MySQL has optional differences in behavior, see http://dev.mysql.com/doc/refman/5.5/en/innodb-auto-increment-handling.html – Bill Karwin Jul 01 '13 at 20:47

5 Answers5

4

In the very least, you should use option 1 - handle primary key constraint violation - when possible since the database is the last point of entry. Duplication is still possible if you check for duplicates in code (albeit highly unlikely) since there is a delay between when the initial SELECT is returned and the INSERT statement is sent back, and another user could have performed the same insert in that time window.

However, it is likely more efficient to run a select first to see if the record exists, rather than blindly letting the insert run every single time.

So I would recommend both.

Seth
  • 1,353
  • 1
  • 8
  • 17
2

If you use Exception catching method i.e. try to insert then keep in mind one thing when ever the Exception occurs your counter for auto_increment column will increase lets take an example you have inserted one record successfully and its id is 1 then you try to insert the same information you got the Exception then you try to insert another data with different data it will be inserted but the id no. for this time will be 3 not 2 as 1 was incremented when Exception occurred so keep in mind if you play with Exception case you will loose these id no.s when when Exception occurs .If id counter is not your concerned then go ahead with this option.

But i prefer to select first then insert

Hope it makes sense

M Khalid Junaid
  • 63,861
  • 10
  • 90
  • 118
  • +1 this is a good consideration for MySQL, but may not apply for other brands of RDBMS. – Bill Karwin Jul 01 '13 at 20:10
  • @BillKarwin thanks but i have posted this answer that we cannot predict the data limit of table so i just tries to save my unique no.s :) and Mysql and Sql are commonly used so my ming goes there first :) – M Khalid Junaid Jul 01 '13 at 20:17
  • Right, I have had the same experience on MySQL. I consulted for a site that lost 1000-1500 id values for each successful INSERT because of this. I'm just saying that the OP did not identify MySQL as the RDBMS he/she is using, so the advice may not be applicable for another RDBMS that handles auto-increment differently. Oracle, SQLite, PostgreSQL are also popular. :) – Bill Karwin Jul 01 '13 at 20:21
0

Unless, your database querying layer provides multiple Exception classes (for each SQL states - in case of relational databases) you should not use Exception catching; in that case you need to rely on the exceptions' messages - it could change over time.

pozs
  • 34,608
  • 5
  • 57
  • 63
0

I don't think there actually is a "standard" of doing this like this. Either you query, then insert, or you go for the INSERT / exception.

Both works fine if applied correctly.

I usually prefer to let the database do this task. Alter your table so the field you want to be unique is actually a unique index. When you want to insert the data, and it is a duplicate, you'll receive an error which can be used to decide what to do next. Or you might use an ON DUPLICATE KEY (if available on the RDBMS of your choice) if you want to do another table operation instead, if needed.

This avoids having problems on the database side, if not only your application writes into those tables. Even if you query first, you should do this in order to have a solid table.

Bjoern
  • 15,934
  • 4
  • 43
  • 48
  • `INSERT ... ON DUPLICATE KEY UPDATE` is a MySQL-specific solution. Se my answer to http://stackoverflow.com/questions/548541/insert-ignore-vs-insert-on-duplicate-key-update/548570#548570 for details on how it works. – Bill Karwin Jul 01 '13 at 20:14
0

How about the IGNORE clause:

CREATE TABLE `users` (
`username` VARCHAR(16),
PRIMARY_KEY (`username`)
);

INSERT IGNORE INTO `users`
(`username`)
VALUES ('Foo Dude');

This will generate a warning but won't terminate.

Apparently you can use the following to capture that warning in PHP 5.1.0 and beyond:

function exception_error_handler($severity, $message, $errfile, $errline)
{
    if (error_reporting()) { // skip errors that were muffled
        throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
    }

    // Or handle in some other way, like filtering for the WARNING
    // that is generated by the INSERT IGNORE.
}

set_error_handler("exception_error_handler");

But, I haven't tried this. Check out the PHP manual for "ErrorException" [http://php.net/errorexception] and especially the comments -- consider implementing your own "ErrorException" class where you filter for the WARNING generated by duplicate key inserts when using INSERT IGNORE.

OR

Apparently error_get_last() will also get warnings.

AND

If you don't want these warnings to show up in the log, then either use error_reporting() to suppress them, or try putting an '@' in front of the query function [use with extreme caution 'cuz this will suppress ALL errors/warnings!]:

@mysqli_query($query);
ReverseEMF
  • 506
  • 7
  • 10