Using Unique Indices versus Querying the Database - mysql

I am working on a login / registration system in node.js.
I usually query the database, to check whether the given username already exists, and if it doesn't, I create the new user.
I got the idea recently, of using the Unique Index in the MySQL database for the username. I have some questions though.
What would be the most efficient way to check for duplicates? Search the database for the given username, or use the Unique Index and catch an error from MySQL if it already exists?
I feel unsafe with MySQL spitting out errors when duplicates are made, but maybe I'm just crazy.
If I were to use the Unique Index, would it still be efficient to use it for every unique value? Such as having a Unique index for the username, email etc.?

What would be the most efficient way to check for duplicates? Search the database for the given username, or use the Unique Index and catch an error from MySQL if it already exists?
In first case you will be finding the user with username and then check whether it is found or not. So in this case your DB checks for this username and you also put one check.
Now consider second case where unique index is present. So you give mysql the data and it will try to check first and either throws the error or put the data into DB. This way you don't have to check double if the usrname is already in the DB or not. This will also save you from race conditions
If you are worrying about the mysql throwing errors then don't worry. mysql will throw an integrity error which you can catch and send appropriate response like username exists already

It's better to use Unique Indexes (with the validation occurring in the database engine), because this avoids thread races and ensures database integrity. Validating through select is unsafe and not a recommended way of doing it.
With that said, I recommend checking with a select before inserting to notify the user of the "username taken" before the tentative to insert.
Another good reason to use Unique Indexes is the performance. Depending on the size of the table, it can be way faster.

Related

sequelize you are using sql safe update error

I am getting this error randomly . I am deleting from activeusers table on the basis of username it gives me error sometime and works smoothly sometime.
here is my code for deleting
let say
data={nickname:'asad',id:1}
activeusers.destroy({where:{username:data.nickname} }).then(res=>{
});
I have turn off the sql safe update from sql workbench but problem still exists
how can i permanently get rid from this error
This is a common problem with updates in MySQL. Here is your query:
DELETE FROM ActiveUsers WHERE username = 'mazhar.hayat#ibexglobal.com'
The error stems from that you are not using a primary key column in the WHERE clause. You would also see this error if you had no WHERE clause at all. MySQL has a mode which views a DML query like this as unsafe, because it is broad and runs the risk of corrupting your data.
There is a hack solution to this which might work. You could modify the query to mention the primary key column as follows:
DELETE
FROM ActiveUser
WHERE username = 'mazhar.hayat#ibexglobal.com' AND id=id
This might spoof MySQL into thinking the query is safe, because it mentions the primary key column id in the WHERE clause.
But what I would recommend to you is turning off safe updates mode directly in MySQL. Edit your startup script and make sure that --safe-updates and --i-am-a-dummy are not mentioned in the script.
Edit:
If you wanted to handle this from destroy, then the query option is the only option:
Post.findAll(
{ where: ["username = ? AND id = id", data.nickname] }
).success()

Saving new records filtered by "unique" in mysql

I have a query that runs everytime a user logins. Since this query regards information the user might have third-party updated recently I thought it would be a good idea to turn the user_id + information combo in the table unique. As so, everytime a user tried to save new information it would only save the one information I already didn't have. So, the first query being
INSERT INTO table VALUES ("1","cake"),("1","pie"),("1","bedsheets")
And as the user logins a second time and it being
INSERT INTO table VALUES ("1","cake"),("1","pie"),("1","bedsheets"),("1","chocolate")
It would only save ("1","chocolate") because (id,info) being an unique pair all other would not be inserted. I came upon the realization they all fail if only one fails. So my question is: is there any way to override this operation? Or do I have to query the db first to filter the information I already have? tyvm...
When you use the IGNORE Keyword, so every errors, in the execution are ignored. Example: if you have a duplicate or PRIMARY key error while executing a INSERT Statement, so it will ignored and the execution is not aborted
Use this:
I NSERT IGNORE INTO table VALUES ("1","cake"),("1","pie"),("1","bedsheets"),("1","chocolate");

Is there any disadvantages of unique column in MYSQL

i'd like to ask a question regarding Unique columns in MySQL.
Would like to ask experts on which is a better way to approach this problem, advantages or disadvantages if there is any.
Set a varchar column as unique
Do a SQL INSERT IGNORE
If affected rows > 0 proceed with running the code
versus
Leave a varchar column as not-unique
Do a search query to look for identical value
If there is no rows returned in query, Do a SQL INSERT
proceed with running the code
Neither of the 2 approaches is good.
You don't do INSERT IGNORE nor do you search. The searching part is also unreliable, because it fails at concurrency and compromises the integrity. Imagine this scenario: you and I try to insert the same info into the database. We connect at the same time. Code in question determines that there's no such record in the database, for both of us. We both insert the same data. Now your column isn't unique, therefore we'll end up with 2 records that are the same - your integrity now fails.
What you do is set the column to unique, insert and catch the exception in the language of your choice.
MySQL will fail in case of duplicate record, and any proper db driver for MySQL will interpret this as an exception.
Since you haven't mentioned what the language is, it's difficult to move forward with examples.
Defining a column as an unique index has a few advantages, first of all when you define it as an "unique index" MySQL can optimize your index for unique values (same as a primary key) because mysql doesn't have to check if there are more rows with the same value so it can use an optimized algoritme for the lookups.
Also you are assured that there never will be a double entry in your database instead of handeling this in multiple places in your code.
When you don't define it as UNIQUE you first need to check if an records exists in your table, and then insert something wich requires 2 queries (and even a full table lock) instead of 1 wich decreases your performance and is more error prone
http://dev.mysql.com/doc/refman/5.0/en/constraint-primary-key.html
I'm leaving the fact that you would use the INSERT IGNORE wich IGNORES the exception when the entry allready exists in the database (Still you could use it for high performance operations maybe in some sort of special case). A normal INSERT will give you the feedback if an entry allready exists
Putting a constraint like UNIQUE is better when it comes to query performance and data reliability. But there is also a trade-off when it comes to writing. So It's up to you which do you prefer. But in your case, since you also do INSERT IF NOT EXIST query, so I guess, it's better to just use the Constraint.

MySQL perfomance: letting a UNIQUE field generate an error or manually checking it

Theoretical question about the impact on performance.
One of the fields in my table is unique. For instance, email_address in the Users table.
What has less of an impact on performance? Attempting to add an already existing email address and getting the error, or doing a search on the email field?
The UNIQUE field will probably be faster.
If you tell MySQL that a certain field is unique, it may perform some optimizations.
Additionally, if you want to insert the record if it isn't in the table already you might run into some concurrency issues. Assume there are two people trying to register with the same email address. Now, if you perform the uniqueness check yourself something like so:
bool exists = userAlreadyExists(email);
if (exists)
showWarning();
else
insertUser(email);
something like the following might happen:
User 1 executes userAlreadyExists("foo#example.com") // returns false
User 2 executes userAlreadyExists("foo#example.com") // returns false
User 1 executes insertUser("foo#example.com")
User 2 executes insertUser("foo#example.com") // which is now a duplicate
If you let MySQL perform the uniqueness check, the above won't happen.
If you check then update, you have to query the database twice. And its turn it will check the table index twice. You have both network overhead and database processing overhead.
My point of view is you have to be optimistic: update and handle gracefully the potential failure if there is some duplicate values.
The two-steps approach has one other drawback: don't forget there will be concurrent access to your database. Depending on you database setup (isolation level, database engine), there is a potential that DB was modified by an other connection between the SELECT and your UPDATE.

Show human error if inserting duplicate data in access database

I've prohibited duplicate records in access database so no one will insert same data again and again. it works fine, but the error message is not helpful to the users, i want to show that error in a more human way possible.
Microsoft JET Database Engine (0x80004005)
The changes you requested to the table were not successful because
they would create duplicate values in the index, primary key, or
relationship. Change the data in the field or fields that contain
duplicate data, remove the index, or redefine the index to permit
duplicate entries and try again.
Instead of this lengthy message i just want to show "Sorry - Record already exist."
Is this possible?
Two ways to do this:
Catch the error. I think classic ASP requires on error resume next and then you need to check the err message. You might even have to match the string since I think the error code will be the same for different errors.
Do a select from the database before the insert to check if the value already exists
Either way you can then display your own message. Might be even more user-friendly to customize the message further ("Sorry - species 'Gruffalo' already exists").