Artikelen › Bekijken

Toevoegen | Categorie:


Unieke data in je database

Unieke data in je database zetten

Op het forum worden veel vragen gesteld over het uniek maken van bepaalde velden. Zo wil je bijvoorbeeld maar 1 dezelfde gebruikersnaam hebben, of maar 1 email adres. Er zijn nog meer redenen, maar daar ga ik nu even niet op in.

Veel gebruikte, slechte manier

Een veel gehoord antwoord/oplossing op deze vraag is:

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
2
3
4
5
6
Draai een select query op de database
Kijk naar aantal resultaten
    Als resultaat 
1
        Fout
    Als resultaat 
0
        Voeg data in




Een twee eenvoudige query's, die op het eerste oog niks fout doen.

Waarom is dit fout dan?

Je kan nooit zeker weten dat op deze manier je data uniek is. Stel twee gebruikers maken een account aan, op het moment dat zij de select-query draaien is de naam nog uniek.
Gebruiker 1 voegt vervolgens zijn username in en gebruiker 2 doet dit ook. Nu is de data niet meer uniek en is je database in principe waardeloos geworden.

Een optie zou zijn om dit in transactions te doen of om de tabel te locken. Maar je houd nog steeds 1 nutteloze query over.

Maar het kan nog eenvoudiger

In je database kun je key's instellen en aan deze key's kun je eisen stellen. Bijvoorbeeld primaire key maar ook een unique key. Laten we dit ook gaan doen.
We maken bijvoorbeeld een user tabel met heel eenvoudig:

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
2
3
4
5
6
7
8
CREATE TABLE `tuts`.`unique_users` (
`
user_idINT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`
usernameVARCHAR50 NOT NULL ,
`
passwordVARCHAR32 NOT NULL ,
UNIQUE (
`
username`
)
ENGINE InnoDB;




We hebben nu een veld wat uniek moet zijn (eigenlijk 2, een primary key moet ook uniek zijn).

Vervolgens voeren we de volgende query uit:

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
2
3
4
5
6
7
8
INSERT INTO `tuts`.`unique_users` (
`
user_id` ,
`
username` ,
`
password`
)
VALUES (
NULL 'foo'MD5'bar' )
);




We hebben nu een user met de naam foo. Als we onze query nog een keertje draaien krijgen we het volgende resultaat:
Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
2
mysql_errno();    #1062 
mysql_error();    #Duplicate entry 'foo' for key 'username'




En nu verder?

Jeee, we hebben nu een foutmelding. Het zou wel erg handig zijn als we de user op een normale manier kunnen vertellen dat zijn geliefde gebruikersnaam al in gebruik is.

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$result mysql_query("
INSERT INTO `tuts`.`unique_users` (
`user_id` ,
`username` ,
`password`
)
VALUES (
NULL , 'foo', MD5( 'bar' )
);
"
);

if( !
$result && mysql_errno() == 1062 )
{
    echo 
'Deze gebruikersnaam bestaat al';
}
elseif( 
$result )
{
    echo 
'Je bent nu lid';
}
else
{
    echo 
'Er trad een andere fout op';
}




Het lijkt meer werk dan dat het is. Maar uiteindelijk heb je constistente data en bespaar je weer een query

Mocht je meerdere unieke velden hebben, zoals een emailadres. Vis dan gewoonweg het veld uit de error-string en geef daarbij een mooie foutmelding.

Unieke combinatie

Ook een heel mooi voordeel van deze techniek is dat je eenvoudig een combinatie van velden uniek kan maken (en houden). Je hebt bijvoorbeeld een nieuwsite waarbij een bericht wordt gekenmerkt door de slug en de datum.

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
2
3
4
5
6
7
CREATE TABLE `tuts`.`unique_news` (
`
postdateDATE NOT NULL ,
`
slugVARCHAR255 NOT NULL
ENGINE InnoDB;

-- 
En nog een mooie index:
ALTER TABLE `tuts`.`unique_newsADD UNIQUE `uniek_bericht` ( `postdate` , `slug` ) -- zou eigenlijk PRIMARY moeten zijnMaar is ter indicatie




Nu nog wat testdata
Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
2
3
4
5
6
7
8
9
INSERT INTO `tuts`.`unique_news` (
`
postdate` ,
`
slug`
)
VALUES (
'2010-10-06''foto-van-de-dag'
), (
'2010-10-07''foto-van-de-dag'
);




Tot nu toe gaat alles goed, de combinatie datum en slug is uniek. Maar als we op 7/10/2010 nog een foto van de dag toevoegen krijgen we weer een fout
Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
Duplicate entry '2010-10-06-foto-van-de-dag' for key 'uniek_bericht'



Dit klopt ook, want er was op die dag al een bericht geplaatst met die slug.

Ik hoop dat je door deze tutorial weer wat opgeschoten bent. Mocht je nog vragen hebben stel ze in het forum of in de reacties. (Mail, PM of msn beantwoord ik niet, dit is een forum en mensen kunnen van elkaar leren)

Tim

ps. Mocht het op deze manier wat onoverzichtelijk zijn dan plaats ik het wel in pagina's. Maar het leek me niet zo veel.

7 reacties | reageren


Rating

Stemmen: 4Je moet ingelogd zijn om te stemmen!