Sida 2 av 3
Postat: 7 september 2007, 16:31:38
av sodjan
Ah, OK, jo jag ser att "som vanligt" kan syfta lite fel där...

Tanken var att koden ska se ut "som vanligt"...
> Men då behöver jag alltså inte blanda in index i koden för att söka i tabellen?
Det gör man *aldrig* med SQL. SQL syntaxen är helt oberoende av
den *fysiska* implementeringen av databasen. D.v.s hurvida det
finns index eller inte, om tabellen är partitionerad eller inte (om det stöds)
o.s.v.
Den enda gången du behöver bry dig om index är vid CREATE INDEX,
DROP INDEX o.s.v. Resten sköts av databasen.
Query-optimizern tar hand om att använda index *om* de finns.
Även att välja *mellan* index, om det finns flera.
Eller att välja att *inte* använda indexen, om det verkar effektivare.
Även att bestämma *hur* indexen ska användas, man kan läsa index
via "lookup" (net vanliga, binärträdssökningen) eller via index-scan (t.ex
om man söker på ett fält som är nr två av de indexerade fälten) T.ex :
CREATE INDEX idx1 ON tab1 (fld1, fld2)
En sökning med "WHERE fld1='abc') gör en table-lookup.
En sökning med "WHERE fld2='abc') kan göra en table-scan, *om*
MySQL stöder table-scans, det vet jag inte...
Postat: 7 september 2007, 21:06:01
av speakman
Har läst någon gång att man inte bör indexera fritextfält, iaf inte med MySQL.
Dessutom blir en INT-index betydligt mer slimmad än fritext.
Och för det tredje så är det alltid bra att köra ett "id" på de flesta tabeller, i förebyggande syfte ifall de senare ska nyttjas i relationer.
Och för det fjärde så slipper du skyffla en massa onödig text i HTML-formuläret, utan bara skicka med user-id.

(ska bara du använda formuläret och det är skyddat, så går det bra så. Ska flera ha tillgång i olika säkerhetsnivåer *måste* PHP+databassidan byggas annorlunda.)
Postat: 7 september 2007, 23:46:49
av sodjan
> Har läst någon gång att man inte bör indexera fritextfält, iaf inte med MySQL.
> Dessutom blir en INT-index betydligt mer slimmad än fritext.
Det är klart att ett INT index i sig blir effektivare än ett CHAR, men om
man vill ha username sökbart (snabbt) så har man ju inget val, eller hur ?
> Och för det tredje så är det alltid bra att köra ett "id" på de flesta tabeller,
> i förebyggande syfte ifall de senare ska nyttjas i relationer.
Det kan vara bra (platsbesparing). Men annars finns det tekniskt inget som
hindrar att "username" kan användas för RI. Vid de (små) tabellstorlekar som
det handlar om här, så spelar inte den större storlekan på "username"
någon större roll. Det blir även lite enklare att "läsa" de andra tabellerna
eftersom username står där i klartext och inte bara ett "id"...
> Och för det fjärde så slipper du skyffla en massa onödig text i
> HTML-formuläret, utan bara skicka med user-id.
Jag tror att man alltid vill kunna se username i alla fall. Dert blir lite
rörigt om man vid administration ska jobba med "id" och alltid annars
med "username".
Postat: 8 september 2007, 00:45:11
av speakman
Orkar inte citera, men:
Söker username gör man *en* gång, sedan använder man bara id't. Här är det givetvis bra att ha index även för username.
Det är inte bara platsbesparing, utan optimering. Inte stor skillnad i Jimmys applikation, men man bör ha det som tumregel då det i större projekt ger mer vinst, och därför finns ingen anledning att inte ha det så i mindre projekt (ungefär som att köra någon mongonotation i mindre projekt, och utan notation i större projekt... bara för att!).
Bara för att man gör SQL-operationer mot id't så utesluter väl inte det att man inte ser username på HTML-sidan? Det är ju bara att skicka vidare i formuläret.
Men att nyttja det för att köra operationer på den kan göra andra saker vanskligt. Tänk bl.a. blandingarna bland de olika character encodings som finns.
Väljer man då att köra UTF-8 rakt igenom (site + databas), och man sedan ansluter in via en läsare som inte stödjer det, så tänk vilka effekter det skulle kunna få om man ska frakta ett användarnamn med tecken > 127 mellan webbläsare och PHP-kod. Idioti!
Du gillar att "hacka" på mig va?

Postat: 8 september 2007, 13:14:38
av sodjan
> Du gillar att "hacka" på mig va?
Nej, det kan jag inte påstå...

Men *databaser* är väldigt intressant.
Första gången man kommer in i en applikation för admin av
användare är det väldigt osannolikt man vet ID. Det är än mindre
sannolikt att den användare som man ska hjälpa vet det. Alltså är
det username man vill söka på. Alltså behöver man ett index på username.
Detta utesluter inte att man *också* har ett "ID" för varje användare som
används för interna RI kopplingar i databasen, eller för joins o.s.v.
Och det går naturligtsvis bra att skicka det fram och tillbaka mellan
applikationen och browsern, om man vill.
I Jimmys fall, så verkar ett ID dock bara införa extra komplexitet utan att
ge någon större fördel.
Hm, det ser ju faktiskt ut som vi är överens, eller hur ?

Postat: 8 september 2007, 13:46:54
av speakman
Det var ju *precis* det tillvägagångssättet jag försökte förklara, så svaret är nog "ja".

Håller även med dig ang. Jimmys applikation, men jag menar att det kan vara bra att ha det som tumregel att ha id-fält.
Postat: 10 september 2007, 00:02:24
av JimmyAndersson
Ändringarna jag gör sparas inte...
Har debuggat och de aktuella variablerna stämmer.
Så jag funderar på om jag gjort något fel i själva update-koden. Såhär ser det ut:
Kod: Markera allt
$db = mysql_connect($mysql_host, $mysql_user, $mysql_pass); // Ansluter
if (! $db)
{
print ("Anslutningen misslyckades");
exit;
}
mysql_select_db($mysql_databas, $db); // Väljer databas
if ($editpassword != "")
{
mysql_query("UPDATE $mysql_tabell
SET Password = $editpassword WHERE user = $searchuser
LIMIT = 1");
echo "<br>Password";
}
$mysql_tabell innehåller nament på tabellen.
$editpassword innehåller det ändrade lösenordet från formuläret
$searchuser innehåller användarnamnet jag sökte på för att ändra.
"Password" skrivs ut när jag tryckt Submit-knappen och det finns något i $editpassword.
Har dubbelkollat alla variabler med echo-rader, så att det verkligen hamnar rätt innehåll där.
Det som händer när jag skriver i ett namn i sökfältet ($searchuser) och trycker "Sök" (Submit-knapp) är att användarens uppgifter syns i textinmatningsfält. Då t.ex tömmer jag alla fält och skriver ett annat lösenord och sedan trycker "Spara". Går sedan in i visningsläget av uppgifterna och ser då att inget har ändrats. Lösenordet kodas med MD5 så det är ju lite svårt att se skillnader, men jag har provat med alla andra fält också.
Jag har tittat på UPDATE-koden som någon postade i tråden och jag har även läst
här men jag kan inte komma på varför ändringarna inte sparas.
Någon som har en idé?

Postat: 10 september 2007, 09:47:52
av hh
Det brukar löna sig att skriva ut frågan på sidan när man söker fel, så ser man i alla fall om koden försöker göra det man vill. Efter det kan man prova att manuellt köra frågan mot databasen (med t ex phpmyadmin eller mysql query browser) och se vilka felmeddelanden som rapporteras.
Byt alltså ut mysql_query mot ett echo och se vad som händer. Det mesta brukar lösa sig på den vägen - på sätt ellere annat.
Postat: 10 september 2007, 11:40:01
av speakman
En sak jag ser är att du inte "snuffar" in fältvärdet i SQL-strängen, det bör se ut så här:
Kod: Markera allt
mysql_query("UPDATE $mysql_tabell
SET Password = \"$editpassword\" WHERE user = \"$searchuser\"
LIMIT = 1");
Alla fältvärden av strängtyp (o.dyl.) *skall* inneslutas.
Detta hade du även upptäckt om du gjort som hh skriver, att byta ut mysql_query mot echo. Mycket effektivt.
Slutligen ett litet tips för att få koden mer kompakt och lättläst:
Byt ut $db = mc(); if(!$db)...
till:
$db = mysql_connect(...) or die ("Anslutningen misslyckades.");
Postat: 10 september 2007, 13:41:30
av JimmyAndersson
Bytte ut mysql_query mot echo och det ser helt rätt ut.
Nu är det här bara ett test-case, så jag kan lika gärna visa hur det ser ut:
UPDATE ftpd SET Password = nisse WHERE user = nisse LIMIT = 1
Efter detta har jag inneslutit strängarna.
Bra idé med att lägga till "or die". Då blev koden fem rader kortare.
Men felet kvarstår förstås. Ska fortsätta gå igenom koden i dag med lite nya ögon.
Kommer ni på något så är det bara att skriva.

Postat: 10 september 2007, 13:50:32
av speakman
> Efter detta har jag inneslutit strängarna.
Hur menar du? Varför har du inte med den biten i ditt inklipp?
F.ö. ser det bra ut. Vad är det som inte fungerar?
Släng in "or die(...);" efter alla mysql-anrop så ser du om något felar där...
Postat: 10 september 2007, 14:04:36
av JimmyAndersson
> Efter detta har jag inneslutit strängarna.
Hur menar du? Varför har du inte med den biten i ditt inklipp?
På sätt och vis så har jag med den biten. Resultatet blev nämligen likadant.
Med inneslutningen så ser det ut såhär:
UPDATE ftpd SET Password = "nisssse" WHERE user = "nisse" LIMIT = 1
Ser ju rätt ut. Men lägger jag till "or die", dvs så att koden blir:
Kod: Markera allt
mysql_query ("UPDATE $mysql_tabell
SET Password = \"$editpassword\" WHERE user = \"$searchuser\"
LIMIT = 1") or die ("Uppdateringen misslyckades");
..så får jag "Uppdateringen misslyckades". Så något *är* ändå galet där.
Provade även att byta ut " mot ' vid strängarna, men det blir precis likadant ändå.
Vad är det som inte fungerar?
Det som inte fungerar är att ändringarna i databasen inte sparas. Det gamla värdet står kvar i tabellen. Som du ser av inklippet när jag bytte ut mysql_query mot echo så är alla strängar rätt.
edit: Testade även att lägga till LOW_PRIORITY i UPDATE-strängen, men det blev samma fel ändå.
Eftersom jag både kan lägga till och ta bort saker i tabellen så är rättigheterna rätt.
edit 2:
En lite längre kod:
Har inte lagt till inneslutningarna här än, men visst ska det fungera ändå?
Kod: Markera allt
$editpassword = $_POST['password'];
$db = mysql_connect($mysql_host, $mysql_user, $mysql_pass) or die ("Anslutningen misslyckades");
mysql_select_db($mysql_databas, $db) or die ("Hittade inte databasen");
if ($editpassword != "")
{
mysql_query ("UPDATE $mysql_tabell
SET Password = \'$editpassword\' WHERE user = \'$searchuser\'
LIMIT = 1") or die ("Uppdateringen misslyckades");
echo "<br>Password"; //Visar att koden "gått in" i if-rutinen.
}
Postat: 10 september 2007, 14:20:35
av hh
Det kan hända att jag är för trött för att de felet, men det kan också vara något annat. Kopiera strängen och lägg in den i något program där du kan köra SQL-satser direkt (t ex
MySQL Query browser) så borde du få ett fint felmeddelande. Annars tror jag man kunde lägga till .mysql_error() eller nåt sånt till or die()-strängen.
alltså or die("fel! ".mysql_error());
Postat: 10 september 2007, 15:03:16
av cykze
Ska det inte vara "LIMIT 1" istället för "LIMIT = 1"? Eller båda kanske fungerar?
Postat: 10 september 2007, 15:22:00
av speakman
cykze har fullständigt rätt. Det förbigick mig. LIMIT 1 är vad som gäller.