My suggestion makes use of a second table, called pending
.
It's basically an 'extension' of the users table, or a copy of the main data, depending on your structure.
This table, in it's purest form, would look like this:
UID (int), ActCode (Varchar[x]), ValidUntil (int)
UID and ActCode are both unique, meaning that only one ActCode may be issued per UID at a time, and each ActCode can only be associated once. ValidUntil contains the return value of UNIX_TIMESTAMP() + x seconds
...whatever you want your validity period to be.
This structure suggests, that the actual user table has id, userdata, activated
as columns.
If the link isn't used for x seconds, the link becomes invalid (UNIX_TIMESTAMP() > ValidUntil
) and a new activation link may be generated, while the old one gets deleted.
Alternatively, you can fetch (with each activation related request) the overdue activations and remove the userdata associated with it.
If the link is clicked within the interval, you would remove the activation code and update your user flag.
Another option would be the extended user table:
ActCode, ValidUntil, Userdata
This way, your UserTable is kept out of the selects entirely, you would insert UserData
only if the ActCode is used while it's still valid.
This protects your AutoIncrement from non-activated accounts and you don't need a Activated
field in your user table either...because as soon as it's in your user table, it's activated.