/ Forside / Teknologi / Udvikling / SQL / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
SQL
#NavnPoint
pmbruun 1704
niller 962
fehaar 730
Interkril.. 701
ellebye 510
pawel 510
rpje 405
pete 350
gibson 320
10  smorch 260
Søge i database...
Fra : MooreHojer


Dato : 30-12-04 14:01

Hej NG

I forbindelse med noget login jeg har lavet vil jeg gerne have at hvert
brugernavn er unikt. Så er der en måde man kan søge i sin database på og
se om navnet allerede eksistere i database. Hvis det ikke gør skal den
så oprette brugeren, og hvis ikke skal den komme med en fejlmeddelelse.
Det skal være i SQL, og skal virke til både mySQL og MSAccess.

På Forhånd Tak!

-Simon



 
 
Troels Arvin (30-12-2004)
Kommentar
Fra : Troels Arvin


Dato : 30-12-04 14:19

On Thu, 30 Dec 2004 14:01:11 +0100, MooreHojer wrote:

> Hej NG
>
> I forbindelse med noget login jeg har lavet vil jeg gerne have at hvert
> brugernavn er unikt.

Så angiv i din tabel-konstruktion, at kolonnen for brugernavn skal have
en "unique"-constraint eller simpelthen primærnøgle:

CREATE TABLE user (
login varchar(20) PRIMARY KEY,
passhash CHAR(32),
...
);

Vi ved ikke meget om din applikation. Men du bør allerede nu overveje
følgende situation: En bruger "xyz" nedlægges. Senere kommer en anden
bruger og opretter sig som "xyz"; er der nu risiko for, at den nye bruger
på en eller anden måde kan komme til at se informationer tiltænkt den
tidligere "xyz"-bruger? - Den slags er fx. set med postsystemer: Et
bruger-login er blevet nedlagt, men posten ikke slettet; senere oprettes
en anden bruger med samme login som den tidligere, og den nye bruger kan
pludselig se den tidligere brugers private informationer (mails). Der er
forskellige måder at forebygge den slags situationer på (lettest: Hvis
en bruger nedlægges, fjernes alle hans data også).

> Så er der en måde man kan søge i sin database på og
> se om navnet allerede eksistere i database. Hvis det ikke gør skal den
> så oprette brugeren, og hvis ikke skal den komme med en fejlmeddelelse.

Du kan indsætte rækken, og hvis databasen giver fejl, bede folk om at
vælge at andet brugernavn:

INSERT INTO user (login,passhash,...) VALUES (...,...,...);

Hvordan du detekterer SQL-fejl (såsom: "rækken findes allerede") er
umuligt at udtale sig om, da vi ikke ved noget om, hvordan du programmerer
din frontend.

--
Greetings from Troels Arvin, Copenhagen, Denmark


Jesper Sommer (30-12-2004)
Kommentar
Fra : Jesper Sommer


Dato : 30-12-04 16:00

Netop derfor skal brugernavn IKKE være primær nøgle Jeg vil altid
anbefale at anvende et nyt unikt ID til records af denne type, og lade
alle referencer gå til denne nøgle.

Constraint på brugernavn ville dog ikke være min anbefaling. HVis der er
tale om et websystem kan du håndtere den slags checks i kode. Check af
eksisterende brugernavn må betragtes som "forretningslogik" for dit
websted, og det bør du under alle omstændigheder konsolidere ét sted
(f.eks. dine scripting filer eller nogle komponent-filer du har
kompileret) frem for at have det spredt.

Desuden vil en overtrædelse af et constraint alligevel medføre, at der
skal programmeres fejlhåndtering når databasen brokker sig. Så er det
akkuerat lige så nemt at søge efter brugernavnet først, og konstatere om
der returneres 1<record eller ej ...



- Jesper




Troels Arvin wrote:
> On Thu, 30 Dec 2004 14:01:11 +0100, MooreHojer wrote:
>
>
>>Hej NG
>>
>>I forbindelse med noget login jeg har lavet vil jeg gerne have at hvert
>>brugernavn er unikt.
>
>
> Så angiv i din tabel-konstruktion, at kolonnen for brugernavn skal have
> en "unique"-constraint eller simpelthen primærnøgle:
>
> CREATE TABLE user (
> login varchar(20) PRIMARY KEY,
> passhash CHAR(32),
> ...
> );
>
> Vi ved ikke meget om din applikation. Men du bør allerede nu overveje
> følgende situation: En bruger "xyz" nedlægges. Senere kommer en anden
> bruger og opretter sig som "xyz"; er der nu risiko for, at den nye bruger
> på en eller anden måde kan komme til at se informationer tiltænkt den
> tidligere "xyz"-bruger? - Den slags er fx. set med postsystemer: Et
> bruger-login er blevet nedlagt, men posten ikke slettet; senere oprettes
> en anden bruger med samme login som den tidligere, og den nye bruger kan
> pludselig se den tidligere brugers private informationer (mails). Der er
> forskellige måder at forebygge den slags situationer på (lettest: Hvis
> en bruger nedlægges, fjernes alle hans data også).
>
>
>>Så er der en måde man kan søge i sin database på og
>>se om navnet allerede eksistere i database. Hvis det ikke gør skal den
>>så oprette brugeren, og hvis ikke skal den komme med en fejlmeddelelse.
>
>
> Du kan indsætte rækken, og hvis databasen giver fejl, bede folk om at
> vælge at andet brugernavn:
>
> INSERT INTO user (login,passhash,...) VALUES (...,...,...);
>
> Hvordan du detekterer SQL-fejl (såsom: "rækken findes allerede") er
> umuligt at udtale sig om, da vi ikke ved noget om, hvordan du programmerer
> din frontend.
>

Troels Arvin (30-12-2004)
Kommentar
Fra : Troels Arvin


Dato : 30-12-04 16:27

On Thu, 30 Dec 2004 16:00:29 +0100, Jesper Sommer wrote:

> Netop derfor skal brugernavn IKKE være primær nøgle

Hvad henviser du til her?

> Constraint på brugernavn ville dog ikke være min anbefaling. HVis der er
> tale om et websystem kan du håndtere den slags checks i kode.

Det er en smagssag. Men som jeg læser MooreHojer's indlæg, er det
indiskutabelt, at brugernavne skal være unikke. Indiskutable constraints
("invarianter") kan man lige så godt lægge i databasen, når det er
muligt, så man lettere fanger bugs i sin frontend-kode. Og i dette
tilfælde _er_ det muligt: Databasen har alle oplysninger, der skal bruges
til at hitte ud af, om brugernavne opfylder den specificerede constraint.

Bemærk, at jeg med "frontend" mener alt mellem database og bruger, altså
også inkl. n lag af middleware, hvis man bruger den slags begreber.

> Check af
> eksisterende brugernavn må betragtes som "forretningslogik" for dit
> websted, og det bør du under alle omstændigheder konsolidere ét sted
> (f.eks. dine scripting filer eller nogle komponent-filer du har
> kompileret) frem for at have det spredt.

Jeg vil hævde, at det er noget vrøvl, affødet af et tilfældigt
branche-lune, hvor man tror, at databaser er "farlige" at rode med og
databaseudviklere dyrere end frontend-kodere. (Med den uheldige
konsekvens, at der rundt omkring opbygges store, bloat'ede imperative
middleware-lag, der til sidst når en fedmegrad, der gør dem umulige at
overskue).

Men bør bruge rette værktøj til rette job. Og når det gælder
håndtering af "et brugernavn må kun optræde én gang", er databasen
absolut det letteste sted at placere constraint'en:
- DBMSet har direkte føling med data-tilstanden, og kan
derfor opretholde invarianten lettere+hurtigere.
- I SQL kan du implementere din invariant/constraint
_deklarativt_, frem for at blande contraint-opretholdelse sammen
med controller-kode i din frontend.
- Databaser har det med at overleve frontends: Hvis du har
de centrale invarianter defineret i din database, kan du med en vis
sindsro udskifte/ændre frontend'en, eller tilføje andre frontends.

> Desuden vil en overtrædelse af et constraint alligevel medføre, at der
> skal programmeres fejlhåndtering når databasen brokker sig. Så er det
> akkuerat lige så nemt at søge efter brugernavnet først, og konstatere om
> der returneres 1<record eller ej ...

Nej: Din løsning kræver en unødvendig søgning. Og fejlhåndtering fra
databasen skal du under alle omstændigheder have styr på. Et tip er her
at navngive unikheds-constraint'en på passende vis, så man i
fejlsituationen let kan se, at det er login-unikhed, der er brudt. Se i
denne forbindelse følgende ret udmærkede artikelserie (link'et går til
artikel to af tre): http://www.dbazine.com/celko26.shtml

--
Greetings from Troels Arvin, Copenhagen, Denmark


Jesper Sommer (30-12-2004)
Kommentar
Fra : Jesper Sommer


Dato : 30-12-04 16:58

>>Netop derfor skal brugernavn IKKE være primær nøgle
> Hvad henviser du til her?

Så angiv i din tabel-konstruktion, at kolonnen for brugernavn skal have
en "unique"-constraint eller simpelthen primærnøgle:

CREATE TABLE user (
login varchar(20) PRIMARY KEY,
passhash CHAR(32),

?

> Det er en smagssag. Men som jeg læser MooreHojer's indlæg, er det
> indiskutabelt, at brugernavne skal være unikke. Indiskutable constraints
> ("invarianter") kan man lige så godt lægge i databasen, når det er
> muligt, så man lettere fanger bugs i sin frontend-kode. Og i dette
> tilfælde _er_ det muligt: Databasen har alle oplysninger, der skal bruges
> til at hitte ud af, om brugernavne opfylder den specificerede constraint.

Du har helt ret, sådan kan det læses. Du identifcerer dog også selv en
helt rigtig problematik omkring nedlægningen af gamle brugerkonti. Eller
måske udløb af brugerkonti ? I sådanne tilfælde er det ikke sikkert man
ønsker at udføre en faktisk sletning af den gamle bruger, men kun at
sætte et "slette-flag" på den gamle konto, hvorefter brugernavnet kan
bruges af en ny konto fordi den gamle nu er "slettet" ?

> Bemærk, at jeg med "frontend" mener alt mellem database og bruger, altså
> også inkl. n lag af middleware, hvis man bruger den slags begreber.

Fair nok - jeg var heller ikke helt kommet til n-tier diskussionen endnu
*g* Men man kunne godt lave en 2½-tier model, hvor man "misbruger" sin
scripting platform til at samle ... af, vent, det kommer i næse sektion

>>Check af
>>eksisterende brugernavn må betragtes som "forretningslogik" for dit
>>websted, og det bør du under alle omstændigheder konsolidere ét sted
>>(f.eks. dine scripting filer eller nogle komponent-filer du har
>>kompileret) frem for at have det spredt.
>
> Jeg vil hævde, at det er noget vrøvl, affødet af et tilfældigt
> branche-lune, hvor man tror, at databaser er "farlige" at rode med og
> databaseudviklere dyrere end frontend-kodere. (Med den uheldige
> konsekvens, at der rundt omkring opbygges store, bloat'ede imperative
> middleware-lag, der til sidst når en fedmegrad, der gør dem umulige at
> overskue).

Nej, nej, database kode er skam ikke farligt. Og DB folk er sikkert ikke
dyrere end programmører (og i en del tilfælde er det de samme folk der
er tale om).

Men man kan godt "misbruge" sin scripting platform til at samle den
slags funktioner. Der er jo intet der hindrer en programmør i, at samle
f.eks. check af brugerkonti i en PHP/ASP/CGI/JSP/osv fil der ikke
genererer HTML output, men blot returnerer et bolsk udtryk eller en
parameter som man kan bruge en masse andre steder. Det er ikke
"midlle-tier" eller "3-tier", men det er samme tanke - sådan lidt groft
sagt.

Performance mæssigt er der heller ikke den store straf, for alle moderne
webservere cacher en kompileret udgave af scripting filerne nu til dags

> Men bør bruge rette værktøj til rette job. Og når det gælder
> håndtering af "et brugernavn må kun optræde én gang", er databasen
> absolut det letteste sted at placere constraint'en:
> - DBMSet har direkte føling med data-tilstanden, og kan
> derfor opretholde invarianten lettere+hurtigere.
> - I SQL kan du implementere din invariant/constraint
> _deklarativt_, frem for at blande contraint-opretholdelse sammen
> med controller-kode i din frontend.
> - Databaser har det med at overleve frontends: Hvis du har
> de centrale invarianter defineret i din database, kan du med en vis
> sindsro udskifte/ændre frontend'en, eller tilføje andre frontends.

Peter Hansen har brugernavn "hansen" og har en konto. En dag nedlægger
han sin konto, eller han stopper med at betale/bruge sitet, hvorefter
hans konto automatisk udløber efter 12 måneder.

Jens Hansen opretter nu en konto. Han ønsker brugernavnet "hansen" som i
øvrigt ikke bliver brugt af andre brugere pt.

Hvis der er lavet en constraint i basen på brugernavn, så kræver det en
fuld og fysisk sletning af Peter Hansens gamle konto. Hvis der blot er
kodet et check af om der er AKTIV konti med det ønskede brugernavn, så
kan Jens Hansen få sin konto med brugernavn "hansen", uden at vi mister
alle oplysningerne om Peter og tvinges til at slette hans bruger record.

>>Desuden vil en overtrædelse af et constraint alligevel medføre, at der
>>skal programmeres fejlhåndtering når databasen brokker sig. Så er det
>>akkuerat lige så nemt at søge efter brugernavnet først, og konstatere om
>>der returneres 1<record eller ej ...
>
> Nej: Din løsning kræver en unødvendig søgning. Og fejlhåndtering fra
> databasen skal du under alle omstændigheder have styr på. Et tip er her
> at navngive unikheds-constraint'en på passende vis, så man i
> fejlsituationen let kan se, at det er login-unikhed, der er brudt. Se i
> denne forbindelse følgende ret udmærkede artikelserie (link'et går til
> artikel to af tre): http://www.dbazine.com/celko26.shtml

Det er faktisk en rigtig god artikel, omend den har et lidt andet fokus.
Men tak for tippet

Jeg mener dog IKKE at der foretages en "unødvendig søgning". Jeg mener
den er ganske nødvendig. Og i øvrigt er det en misforståelse at en så
primitiv SELECT er det fjerneste problem for databasen. Det er en gammel
og dybt forældet mantra, at man skal begrænse antallet af søgninger.

Hvor mange ms. går der med at udføre en SELECT COUNT (*) WHERE username
= 'hansen' hvis der er et index på username ? Hvor mange cycles skal
basen bruge til det ? Ikke mange ! Det er akkurat lige så misforstet at
have skræk for søgninger af denne art, som at have skræk for at samle
sin forretningslogik i separate filer

Yes - så fik vi taget hul på de rellegiøse diskussioner *g*


- Jesper

Troels Arvin (30-12-2004)
Kommentar
Fra : Troels Arvin


Dato : 30-12-04 18:01

On Thu, 30 Dec 2004 16:58:23 +0100, Jesper Sommer wrote:

> Du har helt ret, sådan kan det læses. Du identifcerer dog også selv en
> helt rigtig problematik omkring nedlægningen af gamle brugerkonti. Eller
> måske udløb af brugerkonti ? I sådanne tilfælde er det ikke sikkert man
> ønsker at udføre en faktisk sletning af den gamle bruger, men kun at
> sætte et "slette-flag" på den gamle konto, hvorefter brugernavnet kan
> bruges af en ny konto fordi den gamle nu er "slettet" ?

Det var jo netop hvad jeg advarede imod, ja. Men i den konkrete situation
ved vi p.t. kun - men med sikkerhed - at databasen skal indeholde
maksimalt én instans af et brugernavn. Det er det, jeg tager udgangspunkt
i.

> Men man kan godt "misbruge" sin scripting platform til at samle den
> slags funktioner. Der er jo intet der hindrer en programmør i, at samle
> f.eks. check af brugerkonti i en PHP/ASP/CGI/JSP/osv fil der ikke
> genererer HTML output, men blot returnerer et bolsk udtryk eller en
> parameter som man kan bruge en masse andre steder.

Du påpeger, at det er generelt kan være smart at samle visse funktioner
til funktionsbiblioteker (eller "pakker" eller "klasser", eller hvad man
nu kan lide at kalde det). Det er der vist ingen, der gider betvivle
nytten af.

> Performance mæssigt er der heller ikke den store straf, for alle moderne
> webservere cacher en kompileret udgave af scripting filerne nu til dags

Min skepsis overfor store, voksende lag af middleware/frontend går ikke
så meget på performance-problemer, men på kode-uoverskuelighed, bugs,
osv. Og derfor er jeg så begejstret for at kunne udnytte det, hvis en
invariant kan implementeres med én, deklarativ "kode"-linje som del af et
database-schema.

[...]
> Hvis der er lavet en constraint i basen på brugernavn, så kræver det en
> fuld og fysisk sletning af Peter Hansens gamle konto.
[...]

Ja, og det er måske heller ikke nogen helt dårlig strategi (jeg tror,
at frygt for at slette informationer er skadelig); og det er nok også,
hvad mange brugere i grunden vil ønske sig af privacy-grunde.

- Eller de slettede brugere kan overføres til en slags arkiv-database/
warehouse, hvis nogen på et tidspunkt skulle have lyst til at foretage
nogle statistiske analyser. Eller man kan sige, at nedlagte brugere lever
videre på backup-bånd, indtil båndene er cirkuleret.

- Eller ... you name it.

> Hvis der blot er
> kodet et check af om der er AKTIV konti med det ønskede brugernavn, så
> kan Jens Hansen få sin konto med brugernavn "hansen", uden at vi mister
> alle oplysningerne om Peter og tvinges til at slette hans bruger record.

Ok, ja. Men også den constraint kan du lægge i databasen, omend det så
bliver mindre simpelt (som en naturlig konsekvens af, at invarianten er
mindre simpel, og fordi situationen desværre er den, at ingen SQL-DBMSer
understøtter "table assertions").

> Jeg mener dog IKKE at der foretages en "unødvendig søgning". Jeg mener
> den er ganske nødvendig. Og i øvrigt er det en misforståelse at en så
> primitiv SELECT er det fjerneste problem for databasen. Det er en gammel
> og dybt forældet mantra, at man skal begrænse antallet af søgninger.
>
> Hvor mange ms. går der med at udføre en SELECT COUNT (*) WHERE username
> = 'hansen' hvis der er et index på username ?

I visse DBMSer er SELECT COUNT(*) faktisk en potentielt ret dyr operation,
selv med indekser. (Noget med den måde, hvorpå transaktionshåndteringen
er skruet sammen på.) Men lad nu det ligge.

> Hvor mange cycles skal basen bruge til det ? Ikke mange !
Nej, ikke (ligegyldige) CPU-cycles, evt. ekstra ventetid, hvis der er
transaktioner, der bliver udsat pga. det unødvendige ekstra SELECT. Det
afhænger af den konkrete situation, DBMS-mærket, osv. Jeg er dog i og
for sig enig i, at et ekstra databasekald i de fleste sammenhænge er uden
praktisk performancemæssig betydning.

> Det er
> akkurat lige så misforstet at have skræk for søgninger af denne art,
> som at have skræk for at samle sin forretningslogik i separate filer

Som tidligere nævnt: Min skræk går primært på overvægtige
kaskader af frontend-lag.

--
Greetings from Troels Arvin, Copenhagen, Denmark


Jesper Sommer (04-01-2005)
Kommentar
Fra : Jesper Sommer


Dato : 04-01-05 20:12


> Som tidligere nævnt: Min skræk går primært på overvægtige
> kaskader af frontend-lag.

På dét punkt er jeg nu også temmelig enig med dig. Det er ufattligt hvor
meget arbejdstid og hvor mange millioner der bruges (læs: spildes) på
middle-tier løsninger, som kunne have været løst på en meget mere
lavpraktisk måde.

Netop i de situationer kan man få nogle af de fordele der er ved den
slags koncepter, og misbruge sin scipting platfom. Ja, lad os bare kalde
det et funktionsbibliotek - selv om der sikkert er non-DB-nørder der vil
blive lidt lange i ansigtet over at kalde en Apache/IIS for en container *g*

Men alt ialt er vi vist enige - og relligionen kan vi så lade de yngre
generationer tage sig af

- Jesper

Peter Brodersen (30-12-2004)
Kommentar
Fra : Peter Brodersen


Dato : 30-12-04 18:59

On Thu, 30 Dec 2004 16:27:27 +0100, Troels Arvin <troels@arvin.dk>
wrote:

>> Netop derfor skal brugernavn IKKE være primær nøgle
>Hvad henviser du til her?

Uden at tage stilling til den aktuelle tråd, så kan en generel
problemstilling være "gamle brugere". Utallige systemer er blevet
udviklet, hvor man ikke har tænkt nærmere over "unikheden" over
brugernavne. Som regel er ønsket i praksis, at man kun kan have et
"aktivt, unikt brugernavn ad gangen", og ikke bare ét unikt brugernavn
i hele datastrukturens levetid.

Brugernavne kan let risikere at blive genbrugt. En medarbejder
stopper, og en ny tiltræder et par år efter og får samme brugernavn.
En ny kunde vil gerne have det samme brugernavn som en tidligere
kunde, idet brugernavnet rent faktisk repræsenterer noget (fx en
e-mail-adresse eller lignende).

Her er det et problem, hvis brugernavnet i andre tabeller bruges som
fremmednøgle. Pludselig er der legacy-data fra en tidligere kunde
eller medarbejder, der bliver tilknyttet den nye medarbejder. En
løsning er selvfølgelig ganske enkelt at forhindre genbrug, men det er
ikke altid lige praktisk.


... men alt det her er selvfølgelig en variant af at hyppe
pseudonøgle-hesten :)

--
- Peter Brodersen

Vagn Kofoed (31-12-2004)
Kommentar
Fra : Vagn Kofoed


Dato : 31-12-04 06:36

"Troels Arvin" <troels@arvin.dk> skrev i en meddelelse
news:pan.2004.12.30.15.27.26.776518@arvin.dk...
> On Thu, 30 Dec 2004 16:00:29 +0100, Jesper Sommer wrote:
>
>
> Bemærk, at jeg med "frontend" mener alt mellem database og bruger, altså
> også inkl. n lag af middleware, hvis man bruger den slags begreber.
>

Og lidt fra puristen...
Det er i hvert fald ikke den korrekte/oprindelige betydning. Dengang man
brugte frontends var det en maskine (eller SW) der kunne forbehandle de
transaktioner der kom ind til systemet. En slags forbrænder der dels modtog
og fordelte varerne og dels lavede den første simple massage. Ideen i det,
var bedst i et mainframe system med terminaler.

Vagn Kofoed



Søg
Reklame
Statistik
Spørgsmål : 177459
Tips : 31964
Nyheder : 719565
Indlæg : 6408195
Brugere : 218881

Månedens bedste
Årets bedste
Sidste års bedste