I'm going to have to disagree with Descalzo about the activation key being unique in the current design. Notionally, the activation key is unique to an account, since it's sufficient to identify an unactivated account; it's a
candidate key. If the activation key and some other piece of identifying information (e.g. e-mail, username) were required, the activation key wouldn't be a candidate key. Moreover, the DB should enforce uniqueness. Declaring the column in a unique index is thus appropriate.
Removing the UNIQUE attribute from the activation key index isn't necessary to resolve the issue. Storing some other unique data (such as Descalzo suggests) would work, but someone could potentially re-activate their account using the new data (not that this would be problematic, though it is odd). Allowing the column to store NULL values would also work, since
NULL doesn't equal itself using the standard comparison operators in MySQL. Nulling the activation key for activated accounts also lets you change the column type to a constant width CHAR type (since it's a fair assumption that activation keys are all of a length), which offers some performance advantages.
A third (and better) approach is to separate out the activation data. One reason it's better is that storing the activation key in the user table is wasteful.
One particular approach is to keep a table of pending user accounts. When an account is activated, move the entry from the `pending` table to the `users` table.
Code:
INSERT INTO users SELECT username, password, email, status FROM pending WHERE activationkey = ?;
-- if the above succeeds
DELETE FROM pending WHERE activationkey = ?;
Alternatively, the pending table could store the activation key and the ID of the user to be activated, with the rest of the user data in the `users` table. One downside to this is that corruption of the pending table will essentially authorize pending users.
Depending on how the authentication and authorization system is designed, each option will have other benefits and detriments. With the first option, the default behavior is that unactivated users aren't given access; with the latter, unactivated users can log in without special consideration.