Probleme cu codificarea în versiunea mysql 4

Dacă se emite o întrebare din baza de date, atunci după conectarea la server, efectuați o interogare magică:

setați numele

Parametrul "codare" trebuie să se potrivească cu codificarea în care paginile sunt afișate pe site. De exemplu:

Dacă acest lucru nu a ajutat-o, și totuși să se pună întrebări sau să se afișeze în mod normal, dar sortarea este lame, atunci codarea tabelelor este strâmbă. În acest caz, vedeți "Corectarea unei baze de date cu codare incorectă".

Notă: în locul interogării SET NAMES, ar trebui să utilizați, dacă este posibil, funcția mysql_set_charset ().

Explicații detaliate

Înainte de versiunea 4.1, codarea datelor din MySQL putea fi setată numai la una. Teoretic, nu era nimic de păstrat datele în unicode într-o singură masă, iar în KOI-8 în altul. Deci toți au acționat și: în cele din urmă, pentru un DB orice date sunt doar un set de cifre. Ce se pune în ea, atunci ea se va întoarce la tine. Dar căutarea corectă și sortarea au funcționat numai pentru date care erau în aceeași codare ca și setările MySQL.

Începând cu versiunea 4.1, puteți stoca datele în orice codificare și puteți seta ordinea de sortare pentru cel puțin un câmp din tabel. Dar pentru aceasta a fost necesară introducerea unor reguli.
  1. Pentru fiecare câmp din tabel, au fost introduse doi parametri: setul de caractere (CHARACTER SET) și regula de comparație (COLLATION). Codificare - spuneți bazei de date, ce codificare sunt datele noastre. Normele de comparare specifică ordinea de sortare și comparare a datelor în căutare. COLLATION este atașat rigid la setul de caractere CHARACTER-u și poate fi setat numai din cele acceptate de codificare. Pur și simplu puneți, începutul numelui COLLATION trebuie să se potrivească setului CHARACTER. De exemplu, pentru a codifica utf8, puteți specifica regulile de comparare utf8_bin, dar cp1251_bin nu poate fi utilizat.

De obicei, fiecare codificare are cel puțin două seturi de reguli de comparație - numele codului_bin și numele lui_general_ci. Prima se compară cu fruntea cu codurile de simbol, iar cea de-a doua este insensibilă pentru litere mici, luând în considerare simbolurile coincide. imyakodirovki_general_cs colaționare compară sensibile la caz, spre deosebire de _bin care permite simboluri de potrivire ( „e“ și „e“ în limba rusă), precum și sortarea, punerea în aplicare a acelor caractere care sunt codificate în nici o ordine anume (de exemplu, „e "în 1251).

Dacă COLLATION nu este specificată pentru câmp, atunci este luată implicit. De exemplu, pentru utf8 - utf8_general_ci. În cele mai multe cazuri, COLLATION aranjează în mod implicit utilizatorul, ceea ce înseamnă că nu este necesar să îl specificați. Adică este suficient să specificați numai codificarea.

Codificarea poate fi specificată pentru un câmp, o tabelă, o bază de date și pentru întregul server. Setările au o natură prestabilită și pot fi modificate la orice nivel. Codificarea (și sortarea) pot fi specificate pentru fiecare câmp individual. Dacă nu sunt specificate, atunci când se creează tabelul, ele sunt luate din codificarea specificată pentru acest tabel. Dacă codificarea nu este specificată la crearea tabelului, aceasta este preluată din parametrii bazei de date. În mod similar, atunci când se creează o bază de date - fie setată în mod explicit, fie preluată din parametrii serverului.
  • A fost nevoie să se spună bazei de date ce codificare înregistrăm sau doriți să obțineți datele noastre. Asta a fost, de exemplu, un cod de client. Aici se află răspunsul la întrebarea Semnele de întrebare „“ în cazul în care sunt „Ele apar în cazul în care codificarea de masă nu este același lucru ca și c codificare client în consecință, în MySQL, două noi comenzi:? .. ​​Set character_set_client și setați character_set_results întâi specifică datele ajunge în orice codificare în bază și celălalt -. care este problema lor Deoarece cele mai multe dintre aceste coduri se potrivesc, atunci puteți scrie pe scurt - o singură interogare „sET DENUMIRI care codifică“, care stabilește ambii parametri.
  • Din explicațiile de mai sus ar trebui să fie clar că pentru o muncă fără probleme trebuie să facem doar două lucruri:
    1. Specificați codificarea corectă a clientului. Acest lucru se poate face fie în setările serverului din my.ini, fie prin solicitarea SET NAMES.
    2. Când creați tabele, nu uitați să specificați codificarea corectă pentru ele. Acest lucru se poate face în mai multe moduri. Cel mai simplu lucru este să specificați regulile de codificare și de comparare direct în codul CREATE TABLE. exemplu:

    CREATE TABLE `chartest` # 40;
    "nume" varchar # 40; 10 # 41; implicit NULL
    # 41; ENGINE = MyISAM CHARACTER SET = utf8

    Dar dacă avem o grosime de sute de mese realizate într-o versiune anterioară a MySQL? Pentru a adăuga manual la fiecare tabel? Probabil ar trebui, de asemenea, să fie făcut. Dar mai întâi trebuie să încercați să setați parametrii impliciți.

    După cum ne amintim, atunci când se creează tabele, dacă acestea nu sunt specificate cu colaționarea și setul de caractere, acești parametri sunt luați din setările bazei de date. Prin urmare, ar trebui să încercați să modificați aceste setări. Mai intai privim, ce sunt acum: intram in consola si scriem:

    utilizați `mydb`
    arată variabile precum "character _ set _ database";

    Această interogare va imprima codarea implicită mydb. Dacă nu ne convine, încercăm să înlocuim noi înșine:

    modificați setul de caractere `mydb` utf8;

    Dacă cererea a avut succes, verificăm din nou, și dacă totul este bine, atunci începem să creăm tabele sau să dăm greșelile. În acest caz nu posibile (drepturi nu sunt suficiente), singurele două opțiuni: fie contactați furnizorul pentru a se pentru a schimba setările, sau se bazeze pe colaționarea și SET CARACTERE tuturor pentru a crea manual tabele.

    recodare

    După cum rezultă din explicațiile anterioare, codificarea clientului ar trebui să corespundă codificării reale a datelor primite. În acest caz, chiar dacă datele se află în cealaltă, atunci nu există probleme - MySQL va re-codifica automat înainte și înapoi.

    Vom realiza experimentul. Pentru el, avem nevoie de MySQL instalat sub Windows. Pentru cei care au un sistem de operare diferit, cred că nu va fi o problemă schimbarea codificărilor în terminal.

    Pentru a demonstra posibilitățile de conversie folosim faptul că, prin ferestre implicit consola este setat la codificarea vechi DOS - 866. Asta este, mai întâi vom crea un tabel în această codificare și scrie date pe aceasta, și apoi încercați să comunice cu baza de date într-o codificare diferită.

    Mai întâi, executați interpretul de comandă cmd.exe și instalați fontul Consolei Lucida în proprietățile ferestrei. Apoi numim consola mysql:

    Test C: \ MySQL \ bin \ mysql.exe -uroot

    În consola am scris:

    setați nume cp866;
    CREATE TABLE ct # 40; "nume" varchar # 40; 10 # 41; implicit NULL # 41; CARACTER SET = cp866;
    inserați în valorile ct # 40; 'Vova' # 41; ;
    selectați * din ct;

    Dacă am făcut totul bine, rezultatul va fi:

    Apoi scrieți ieșirea, ieșiți din consola și scrieți comanda "chcp 1251", care va schimba codificarea ferestrei consolei ferestrelor la 1251. Apoi reporniți consola mysql și scrieți:

    setați nume cp1251;
    selectați * din ct;
    inserați în valorile ct # 40; 'Vova' # 41; ;
    selectați * din ct;

    Același lucru se poate repeta pentru codarea utf8 (chcp 65001).

    Ca rezultat, vedem că chiar și atunci când datele nu apar în codificarea în care sunt stocate în baza de date, lucrul cu ele este complet corect. În același timp, ei continuă să se afle în baza de date în aceeași codificare, în care erau de la bun început - 866.

    Posibilitățile de transcodare sunt, desigur, limitate la aceeași limbă. Asta este, din 1251, este posibil să se transcodeze în 866, în koi8r, în UTF8. În latin1 din 1251 nu puteți transcoda - vor exista întrebări.

    Corectarea bazei de date, în tabelele cărora codarea este incorectă

    Ce se întâmplă dacă literele sunt normale și munca de căutare și sortare este ciudată?

    Deci, avem probleme care nu sunt rezolvate de cererea SET NAMES. Aceasta înseamnă că tabelele conțin date în aceeași codificare, iar tabelul pentru aceste tabele este diferit. În principiu, o soluție rapidă la această problemă poate fi dedusă din explicațiile anterioare: efectuați o interogare SET NAMES cu codificarea specificată în tabel. Puteți vedea acest lucru prin interogarea arătării tabelului de creație `table`.

    Dacă există o DEFAULT CHARSET = latin1 în ultima linie, atunci executăm SET NAMES latin1. Tabelul nu va funcționa în mod corespunzător de sortare și căutare, dar cel puțin datele în sine vor fi date și înregistrate în mod normal (dacă codarea paginii html corespunde codificării actuale situate în baza de date). Dar aceasta, desigur, este o situație anormală, mai ales că nu este dificil să o rezolvi.

    Există două modalități de a rezolva acest lucru, vom folosi această opțiune:
    • Învățăm codificarea tabelelor (arătăm crea tabelul `table`).
    • Facem o descărcare de baze de date utilizând mysqldump
    Să presupunem că am aflat că tabelele au fost create implicit în codarea latin1, dar conțin, de fapt, date în utf8. În acest caz, folosiți comanda:

    mysqldump -uUSERNAME -pPASSWORD NUME_BD --allow-cuvinte cheie --create-opțiuni --complete-insert --default-caractere-set = Latin1 --add drop-table> dump.sql

    O eroare obișnuită în astfel de cazuri, atunci când - setul de seturi predefinite este indicat de codificarea efectivă a datelor, în acest caz - utf8. În halda vor fi gunoi. Trebuie să specificați cel setat în tabele. Ca rezultat, MySQL nu va încerca să re-codifice datele și le va da înapoi așa cum este.

    Scanăm fișierul cu un depozit pentru a ne asigura că fișierul conține date normale în codificare utf8, nu gunoi. O amprentă completă și verificată este copiată lateral. Departe în lateral.

    În fișierul cu memorie, corectăm instrucțiunile CREATE DATABASE și / sau CREATE TABLE pentru a crea tabelele în codarea corectă. Sau schimbați setările bazei de date, așa cum a fost descris mai sus. Umpleți spatele depozitului:

    mysql -UUSERNAME -PASSWORD DB_NAME - set de caractere predefinite = utf8

    În codul site-ului, după funcțiile mysql_connect și mysql_select_db adăugați linia:

    mysql_query # 40; "SET NAMES utf8" # 41; ;

    Totul, puteți lucra!

    Dacă tot nu se întâmplă nimic
    Un număr mare de întrebări referitoare la codificări care nu sunt legate de baza de date mi-au determinat să compilez un mic manual consolidat. Astfel, codarea site-ului nostru este compusă din 4 elemente:
    1. Codificarea bazei de date. Setați când creați tabele. Poate fi oricare. Trebuie să reflecte codificarea reală a datelor din tabel. De exemplu, dacă datele pe care le avem vor fi în codificarea Windows-1251, apoi crearea unui tabel, vom scrie:

    CREATE TABLE chartest # 40; text șir # 41; CARACTERISTICI DEFAULT = cp1251;

    Verificați codificarea curentă a tabelului cu o interogare

    SHOW CREATE TABLE numele tabelului

  • Codificarea clientului bazei de date (clientul este, în acest caz, un script care funcționează cu baza de date). Setați imediat după conectarea la baza de date, interogare

    SET NAMES codificare

    Trebuie să se potrivească cu codificarea paginii HTML de ieșire. De exemplu, dacă pagina este în utf-8, atunci în PHP scriem

    mysql_query # 40; "SET NAMES utf8" # 41; ;

    Puteți verifica la cerere

    afișează variabile precum '% char%'; # 40; variabilele character_set_client. caracter_set_set_connection și set_set_setults trebuie să aibă valoarea stabilită de noi # 41;

  • Codificarea site-ului. Specifică un antet HTTP pentru tipul de conținut. Trebuie să corespundă codificării datelor din pagină. De exemplu, dacă pagina este în utf-8, atunci în PHP vom scrie:

    antet # 40; "Tip de conținut: text / html; charset = UTF-8" # 41; ;

    notițe
    • Este ciudat, dar interogarea SET NAMES nu schimbă codificarea folosită de funcția mysql_real_escape_string. Și numai pentru codificarea acestei funcții a fost inventată! Pentru ca mysql_real_escape_string să funcționeze conform destinației și trebuie să schimbați codificarea cu mysql_set_charset (), nu cu interogarea SET NAMES. Cu toate acestea, pentru noi acest lucru nu este atât de important, deoarece pentru ut8 și toate codificările cu un singur octet, nu vor exista consecințe negative din codificarea incorectă. Să nu mai vorbim de faptul că este timpul să renunțăm la trasarea în general și să folosim expresii native pregătite.
    • Dacă nu doriți să setați codificarea în fiecare script, puteți seta codarea pentru întregul server în mod implicit. Pentru a face acest lucru, în my.ini în secțiunea [mysqld], scrieți:

    init-connect = 'SET NAMES utf8'

    Astfel, codificarea implicită va fi modificată de la latin1 la specificat. Desigur, în scripturi poate fi schimbat în orice altul.