FAQ |
Kalender |
2008-12-12, 16:47 | #21 | ||
|
|||
Klarade millennium-buggen
|
Det som hänt här är att kodningen blivit skruvad ett steg för långt. När tecknet för å i utf8 matades in i tabellen första gången, via anslutningen latin1 (set names latin1), blev det tvåbytes som bildar å tolkade som två separata tecken, vart och ett representerat av två bytes När man kallar fram det med samma anslutning altin1, så returnerar mysql två bytes som tillsammans "råkar" bilda bokstaven å.
Ändrar man sedan anslutningen till utf8 (set names utf8) så levererar mysql helt korrekt två bytes som behövs för att rendera de två tecken som tidigare bildade bokstaven å. Vi får alltså ut fyra bytes där vi istället bara skulle haft två, dessa kombinationer bildar inga vettiga tecken och där för ser vi vad Lindahl ser : Citat:
för den som vill pula lite i mysql kan roa sig med följade terminalövning: Citat:
|
||
Svara med citat |
2008-12-12, 21:55 | #22 | |||
|
||||
Mycket flitig postare
|
Citat:
Okej. Som förtydligande och bevis på att det fungerar gjorde jag lite knappande och kommenterade det hela: Kod:
CREATE TABLE t (f TEXT CHARSET latin1); SET NAMES 'latin1'; INSERT INTO t VALUES ("åsa"); SET NAMES 'utf8'; SELECT * FROM t; -- Ger Ã¥sa visat som utf-8, ger Ã¥sa visat som iso-8859-1 -- Den "dubbla" konverteringen sker med SET NAMES och ligger inte i databasen DROP TABLE t; CREATE TABLE t (f TEXT CHARSET latin1); SET NAMES 'latin1'; INSERT INTO t VALUES ("åsa"); ALTER TABLE t MODIFY f BLOB; ALTER TABLE t MODIFY f TEXT CHARACTER SET utf8; SET NAMES 'utf8'; SELECT * FROM t; -- åtger korrekt åsa visat som utf-8, ger Ã¥sa visat som iso-8859-1 -- (dvs är korrekt om filen tolkas som utf-8) -- Samma sak med fältet som BLOB och konverteringen inte inlagd i databasen, bra för testning innan DROP TABLE t; CREATE TABLE t (f TEXT CHARSET latin1); SET NAMES 'latin1'; INSERT INTO t VALUES ("åsa"); ALTER TABLE t MODIFY f BLOB; SET NAMES 'utf8'; SELECT CONVERT(f USING utf8) FROM t; -- Vad vi vill åstadkomma: DROP TABLE t; CREATE TABLE t (f TEXT CHARSET latin1); SET NAMES 'latin1'; INSERT INTO t VALUES ("åsa"); ALTER TABLE t MODIFY f BLOB; ALTER TABLE t MODIFY f TEXT CHARACTER SET utf8; -- Tabellen är ändrad som ovan allt borde fungera. -- Innan vi nu SELECT:ar så sätter NAMES till latin1 för vi vill ha ut data i iso-teckenkodning: SET NAMES 'latin1'; SELECT * FROM t; -- Ger Xsa (X ogiltigt unicodetecken) visat som utf-8, ger åsa visat som iso-8859-1 Aningen oöversiktiligt men i grunden rätt enkelt: 1. Har man en tabell som egentligen är i utf8 men är deklarerad som latin1 i tabellen (gammalt rävknep för att spara utf8-data i databaser som bara kan hantera iso) så beböver man konvertera fälten enligt följande enkla kommando för varje fält (MySQL tillåter för övrigt att ändra flera kolumner i en tabell med en ALTER-sats): Kod:
ALTER TABLE exempelfält MODIFY f BLOB; ALTER TABLE t MODIFY exempelfält TEXT CHARACTER SET utf8; 2. För att det sedan inte ska bli fel när man hämtar data så är det viktigt att man även sätter överföringsteckenkodningen (vilken är det teckensnitt man deklarerat på t.ex. hemsidan, i normalfallet utf-8) antingen i sin .ini-fil eller med sql: Kod:
SET NAMES 'utf8' Kod:
SET NAMES 'latin1'; |
|||
Svara med citat |
Svara |
|
|