Case Sensitivity and Indices in MYSQL - mysql

I am creating a system where is use e-mail address as unique identifier. There are times I need to look for a user by the e-mail address. If the user enters the e-mail address in all lower case, but the database has it stored as mixed case, is it a full scan, or will the database still use the index?
This really is a problem because I attempt to validate that the e-mail address is valid when adding the user to the system.
I am using grails with MYSQL on the back end for the database.
I am currently doing this to find the user
def c = User.createCriteria()
def currentUser = c.get() { ilike('emailAddress',message.sender.address) }
I know I can force the case at the UI, but I would also like to force it at the model level
Thanks, and sorry for the long question

MySQL specifies collation for every character column, which may be case-sensitive or case-insensitive.
Index is built using whatever collation is specified on the column, so:
Alter your table to specify case-insensitive collation on email column (like ascii-general-ci, for example).
Rebuild your index.
Enjoy.
Keep in mind that all queries against email will now be case-insensitive.

Unfortunately MySQL does not support function based indexes like Postgres and Oracle. (Source)
A possible workaround in MySQL is to add another column for lower case e-mail addresses, and a trigger that populates it with lower case e-mails on all updates and inserts. Then simply index that column, and use that for your lookups.
With a function based index, you would have been able to do the following:
CREATE INDEX
ix_users
ON
table_users
USING
lower(email_address);

With Grails you have a few options to validate the model:
You can write a setter for the emailAddress that converts it to a consistent case:
public void setEmailAddress(email){
emailAddress = email
}
A more involved but correct answer would be to create a custom editor (PropertySupportEditor) that will handle the normalization for you automatically.
You will also would want to write a custom validator to ensure that Grails' validation fails if the emailAddress is not correctly normalized. If you wanted to make it really elegant you could make the validator into a reusable constrtaint using the constraints plugin which could result in something like this:
static constraints = {
emailAddress(normalizedEmail:true)
}

Related

Is it possible to create DDL table where specific attribute has to end with digit?

I'm new to MySQL.
I'm trying to create table "Customer" with attribute "Password".
I'd like to know is it possible in DDL to make a constraint,that password has to contain 5 chars, while the last one is digit(one of this: 0-9)
I have tried to search for the answer, but could not find one.
I'm pretty sure that I cant satisfy this condition, but I will be glad to hear an oponion of someone who understands better then me.
Thank you!
Your requirement should never be an actual consideration, because you should not be storing clear text passwords in your MySQL database in the first place. Instead, you should be checking password creation in your PHP server code (as well as possibly on the front end). If valid, you should be hashing your passwords irreversibly, and then storing the hash in the user table. Your exact specified requirements can be gotten using the following regex pattern:
^.{4,}\d$
This would match 5 or more characters of any kind, the last of which is a digit. For some more ideas on a better password strength, and how to write a regex for that, consider reading the canonical SO question
Regex to validate password strength.
Edit:
Given that it appears you are using SQL Server, if you really needed a clear text password column with your requirements, you could use a check constraint:
CREATE TABLE users (
id INT NOT NULL,
password VARCHAR(100) NOT NULL,
CONSTRAINT check_password
CHECK (LEN(password) >= 5 AND RIGHT(password, 1) LIKE '[0-9]')
);
Why not make a PHP page for the entries and place all restrictions on that page?
As in MySql, you can't have so many restrictions.
You can also sue MySql procedure for inserting values and place restrictions from there.

Reverse hash lookup query

i have an web service and one of the parameter our clients needs to use is a custom key. this key is a hash of sha1
eg:
bce700635afccfd8690836f37e4b4e9cf46d9c08
then when the client call our web service i have to check few things:
is client active
is client can submit via webservice and service
now my problem is this:
i have a query:
$sql = "SELECT permission, is_active FROM clients WHERE sha1(concat(id,key)) = '" . mysql_real_escape_string($key) . "'";
Am i doing the right thing? or there's a better way?
thanks
This approach is expensive, since, every time you run this query, MySQL will have to examine every single record in clients and compute the SHA-1 hash of its id and key. (I'm assuming here that clients has more than a few rows, or at least, that you'd like to use an approach that supports the case where clients has more than a few rows.)
Why don't you add a new field called (say) id_key_sha1? You can use a trigger to keep the field populated, and add an index on it. This approach should perform much better.
Edited to add: You mention that the client, in addition to passing in this SHA-1 hash, also has to submit a username and password? I don't know what your table structure looks like, but I'm guessing that it would make more sense to find the client record based on the username first, and then comparing the SHA-1 hash for that specific record, rather than trying to find the record by the SHA-1 hash.
You should not applying function into your LHS column where doing filtering in mysql,
this make not possible for mysql to make use of index for comparison.
An example will allow make use on index :-
where key = SHA1(CONCAT(id, :key))
// where the :key = user submitted api key
// and in this case mysql able to fetch the matched rows via index

How to generate a SEF alias for a DB String Value

I have a DB table named games which lets just say for simplification contains the columns "id" and "gametitle" and has roughly 7,000 rows already populated.
What I would like to do is have a piece of SQL that would generate a SEF alias for the gametitle that I can use in the URL (I have URL Rewriting successfully running on the site).
The new field would be entered into a new column named "gamealias".
So for instance, if I had a gametitle of "Halo: Combat Evolved" it would drop any special characters and produce something similar to "halo-combat-evolved". All the aliases in the table would have to be unique as they are going to be used in the games url... e.g. http://thegamesdb.net/game/halo-combat-evolved/
Also, it would be nice if upon insertion of a new row, the alias could be generated automatically from SQL without having to handle it in PHP (maybe using the sql fields default value somehow), although I don't mind having to do this in PHP if it's not possible magically in SQL.
I think this could be done in MySQL using a trigger and a regex-replace UDF, but it would probably be a simpler route just using PHP. You could easily guarantee gamealias uniqueness if you integrated the title's primary key in with the string. For example, consider something that would output "halo-combat-evolved-321".

What's the best way to save trivial user states (e.g. dismissed welcome msg) in database?

Should I use (create) a column for every new state? Or one field with a bunch of comma separated states (alternatively a json obj)? Any suggestions welcome.
UPDATE
First let me day thanks for the answers. I just want to clear up, what options I see:
Put a column for every state in the user row (initial plan) / Can get messy with lots of states (in the future)
Put one column with json/xml data in the user row / Easy to maintain (no db change required), but doesn't feel right
Have a dedicated states table (thx lhiles)/ Sounds cool, how would this table look like?
I'm looking for pros/cons of the different implementations. Again: Thanks!
Create a column for each state. This is proper data normalization.
With a column for each state you can retrieve as few or as many states as needed for the current operation.
All of the states returned will be contained in a single row with each column named. This makes referencing each state value very easy.
It allows you to easily add constraints to each state as needed. (State X can only contain '1' or '2'.)
It allows you to easily query states across users. (How many users have set a state value to 'X'?)
My preferred method is to create a dedicated table for user settings. Each state/setting corresponds to a column within that table. As your project grows additional columns can be added without cluttering your apps core data.
Another route, if you feel that there will be too many settings to devote 1 setting per column, would be to store the settings as XML (or json as you mentioned) data within SQL. This would allow you to derive any type of state format you wanted, however, it puts more work on the programmer to parse, validate, and persist those settings.
You can save state using an ENUM if the states are mutually exclusive; e.g. person is male or female.
Or using a SET if states can co-exist; e.g. person is a member of (AA and CA and SOsA*)
A sample table using both:
CREATE TABLE test.table1(
test_enum ENUM('male', 'female') DEFAULT 'male',
test_set SET('AA', 'CA', 'SOsA') DEFAULT NULL
)
ENGINE = INNODB;
If you're using an ENUM I personally would recommend you set an explicit default value other than null, because most of the time a choice must be made.
Link: http://dev.mysql.com/doc/refman/5.1/en/constraint-enum.html
* (stackoverflow sufferers anonymous)
I really wouldn't do this with a column per setting, as most of the other people are suggesting. I'd do a setting per row because this doesn't require schema changes (including upgrade scripts) every time you add a setting.
Better yet, write some reflection code to run on app startup that'll look at the entries on an enum and automatically create a record in the database (with some default value that you specify in a custom attribute on each enum value).
I recently did something like I'm indicating above. Now to add a new setting, I add an entry to an enum and that's it. New settings take about 10 seconds.
I may put my code up on CodeProject, it has has made development easy.

How can I add regular expressions to MySQL datafields?

I have the following table:
Table Account{
[...]
email varchar(100),
[...]
}
and a corresponding regular expression:
/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i
How can I use the MySQL model, to link the regular expression to the the data-field "email", so that the regex is accessible to read out through php as well as a trigger or even better, in a kind of constraint?
I want to define this directly using MySQL workbench, so a separate table won't work for me.
In my opinion, input validation like this is not really the task of the database. Those validation rules may change. You may even make them configurable by the user some day. This becomes awfully difficult if the rules are buried in some trigger somewhere.
Also, you will need to handle a validation error on application level anyway - showing a message of some sort.
The best place to make them accessible to PHP inside mySQL may be a column comment, that you can fetch using SHOW COLUMNS in conjunction with the FULL keyword.