Autor Zpráva
maycza
Profil
Ahojte,

rovnou uvedu příklad, mám tabulku
CREATE TABLE dbo.dodavatele (
  id int NOT NULL,
  nazev nvarchar(80) NULL,
  PRIMARY KEY (id)
);

Tabulka má nastavenou collation na Czech_100_CI_AI. Potřebuji do tabulky vkládat kromě českých znaků i azbuku. Česky to všechno funguje, ale..

1) pokud vložím do tabulky nový záznam přes MSSQL Server manager pomocí editování řádků napsaný azbukou, všechno v pořádku, záznam se uloží tak jak jsem ho zadal
2) pokud vložím do tabulky nový záznam v MSSQL SM pomocí dotazu INSERT INTO dbo.dodavatele (nazev)VALUES(N'Москва') - vše ok (i když nepoužiju "N" před vkládanými daty
3) když vkládám záznam pomocí php, nastává problém. V souboru vloz.php uloženém v kódování windows-1250 mám úplně stejný dotaz jako v bodu 2), je jedno jestli použiju N pro unikód nebo ne, do databáze se uloží "??????". Co se stane když změním kódování na utf-8 asi psát nemusím...

Když nechám uložená data vypsat na stránce vypis.php, kódování windows-1250, vylezou z toho vždycky otazníky.

Nevíte někdo, kde dělám chybu?
Alphard
Profil
maycza:
Když nechám uložená data vypsat na stránce vypis.php, kódování windows-1250, vylezou z toho vždycky otazníky.
To ale v každém případě, ať tam ty data vložíte jakkoliv, ne?
cp1250 neobsahuje znaky azbuky, viz např. cs.wikipedia.org/wiki/Windows-1250#K.C3.B3dov.C3.A1_tabulka. Použijte jiné kódování, nebo převod na entity.
maycza
Profil
Ano s tím výpisem je to stejné pro všechny.

Nevíte jaké kódování se dá použít, aby to sežvýkala databáze i stránka?

Myslím, že použití entit mi také nepomůže pokud budu používat na stránce cp1250.. Když použiju utf8 tak se mi to zase blbě uloží v databázi..
juriad
Profil
maycza:
Máš nějaký důvod nepoužít úplně všude (tedy na stránce, ve skriptech i v databázi) UTF-8?
maycza
Profil
No právě jenom jeden, nějak mi uniká, která collation v MSSQL je ekvivalentem k UTF-8.. používám MSSQL server 2012
juriad
Profil
maycza:
Collation říká jen jakým způsobem se porovnávají znaky *, nikoli jak jsou uložené. Stačí ti, když máš sloupce typu NVARCHAR.

* například, zda jsou znaky shodné, po nějaké normalizaci (velikost písmen, diakritika, různé zápisy stejného znaku).
Joker
Profil
maycza:
Pokud vím, MS SQL Server nemá unicode na úrovni porovánání, ale použije se jiný datový typ. CHAR, VARCHAR a TEXT jsou ne-unicode, NCHAR, NVARCHAR a NTEXT jsou unicode.
maycza
Profil
Jj, to je pravda. Když se mrknete na ten úplně první příspěvek, tak vidíte, že jsem si vytvořil sloupec název, který je typu nvarchar o délce 50 znaků, tzn. unicode. Proč se mi tedy do databáze uloží nesmyly, když mám stránku uloženou v UTF-8 a nastaveno <meta charset="utf-8" />. Když nechám vypsat obsah tabulky, tak se mi ty nesmysly i zobrazí.
_es
Profil
maycza:
Proč se mi tedy do databáze uloží nesmyly, když mám stránku uloženou v UTF-8 a nastaveno <meta charset="utf-8" />
Veď ale sám píšeš, že problém nastáva pri neprávom nastavení kódovania na windows-1250 cez PHP.
maycza
Profil
_es:
to se omlouvám, zapomněl jsem dodat, že jsem to všechno změnil pro UTF-8.. a stejně to nepomáhá.
_es
Profil
maycza:
No dobre „vkladáš v PHP“ ale ako konkrétne? To popíš, aby ti mohol poradiť niekto, kto vie správne skombinovať PHP s MSSQL a UTF-8.
maycza
Profil
_es:
dotaz je úplně na začátku, v php to vypadá tedy takto:
$dotaz="INSERT INTO dbo.dodavatele (nazev)VALUES(N'Москва')";
$proved=odbc_exec($dbcon,$dotaz);



ještě ať to máte úplné:
$dbcon = odbc_pconnect('Driver=TDS;Server=nazev_serveru;', 'username', 'password'); 
_es
Profil
[#12] maycza:
Myslím, že problém je jednoducho v tom, že časť dotazu v ruštine Москва sa do databázy odosiela zle. Termín Unicode neznamená to isté ako UTF-8.
maycza
Profil
_es:
nemůže být ještě něco špatně třeba s tím ODBC driverem..? Ono to není totiž úplně dokonalé ani s tou češtinou. Když mám například sloupec "poznamky" typu nvarchar(255), uložím do něj řetězec obsahující diakritiku, tak to do databáze uloží např. místo ě písmeno í (s obráceonu čárkou) atd.

Při výpisu na stránku se znaky zobrazují tak jak mají.
_es
Profil
maycza:
tak to do databáze uloží např. místo ě písmeno í (s obráceonu čárkou) atd.
No veď to tvrdím, že sa textové reťazce neposielajú správne. Tak skús si to naštudovať v nejakej dokumentácii k MSSQL ako to má byť. Takto „naslepo“ to skúšať nie je asi dobrý nápad. Asi tu veľa diskutujúcich nepoužíva takú kombináciu databázového servera, PHP, znakovej sady a kódovania. MS tuším pod „Unicode“ rozumie často nejaké 16bitové kódovanie Unicode. Aj ODBC ovládač má nejaké svoje vlastné nastavenia - skús pozrieť aj tam. Musí byť vzájomne zosúladené: ukladanie znakov v databáze, to aby databázový server so znakmi pracoval správne, výstup z databázy aj vstup do nej.
tomix
Profil
_es:
Unicode je v rámci MS SQL spoločný názov pre formáty ako je UTF-8, UTF-16, UTF-32, UCS-2. Zial, UTF-8 má mizernú podporu a preferuje sa konveria do UTF-16 respektive co som teraz pozrel na UCS-2

Co sa týka nastavení pre ODBC, tak nejaké extra zvláštne nastavenia nepomôžu, pretože úloha ODBC je iba zabezpečiť konektivitu medzi medzi klientom a servrom (pokiaľ si to aplikácia vyžaduje).

maycza:
Pre radenie znakov v azbuke doporučujem pre tabulku alebo tabuľky koláciu Cyrillic_General_CI_AS , pre server nechaj Czech_100_CI_AI alebo zmen to na SQL_Czech_CP1250_CI_AS.
maycza
Profil
tomix:
ono o to řazení ani tak moc nejde i když je to taky potřeba.. mě jde hlavně o to zapsat data do db ve správném tvaru a pak je i ve správném tvaru vypsat. Ale to co píšete vyzkoušet můžu, nic lepšího zatím nemám
maycza
Profil
Pokud by to někoho ještě zajímalo, tak v MSSQL jsem nastavil kódování SQL_Latin1_General_CP1_CI_AS (default), php skripty jsem uložit v utf-8 a výsledek je následující:

- přes <form> zadáno "Москва" (uloženo pomocí odbc_exec($dbcon,"INSERT INTO dbo.dodavatele (nazev)VALUES(N'Москва')")) -> v db uloženo "Москва" -> při výpisu dat na stránku se zobrazí "Москва" (takže to co jsem zadal)
- přes SSMS zadáno INSERT INTO dbo.dodavatele (nazev)VALUES(N'Москва') -> v db uloženo "Москва" -> při výpisu na stránku zobrazeno "??????"

Možná bude nakonec nejjednodušší ukládat ruské názvy do zvláštní tabulky s nastavením collation na Cyrillic_General_CI_AS a svázat to přes id_dodavatele...
Joker
Profil
maycza:
v db uloženo "Москва" -> při výpisu na stránku zobrazeno "??????"

To už bude problém kódování na výstupu, řekl bych.
_es
Profil
maycza:
Jednoducho si stále neprišiel na to, ako správe skombinovať PHP a databázový server aby správne pracovali so znakovou sadou Unicode. Z ďalších možností: môžeš spraviť stránku aj v iných kódovaniach podporujúcich Unicode než UTF-8, napríklad spomínané UTF-16 či UCS-2.
maycza
Profil
Ještě se zkusím zeptat jinak. Používal nebo používá někdo z Vás tuto kombinaci? PHP na Linuxu + MSSQL na windows? Nemůže být právě toto kámen úrazu? Nestačilo by rozjet php na IIS?
Alphard
Profil
Vrátím se ještě k [#18] maycza. Ten první případ bohužel vůbec neznamená, že už to funguje. Vy jste databázi poslal nějakou sekvenci bajtů a ona vám ji beze změny vrací. Když je daná sekvence bajtů interpretována na té stránce, kde byla zadána, zobrazí se vše v pořádku, ale nějaký admin pracující s jiným kódováním to pochopitelně zobrazí špatně.
Druhý případ to jen dokazuje.

Na stránce stackoverflow.com/a/9259763 doporučují
ini_set('mssql.charset', 'UTF-8')
Zkoušel jste? Já to vyzkoušet nemohu, ale zdá, že je to v souladu s msdn.microsoft.com/en-us/library/cc626307(v=sql.105).aspx (sice je to psané pro SQL server, ale mohlo by to jít). Tvrdí, že konverze na (nepodporované) utf-8 bude automatická.
maycza
Profil
Alphard:
k tomu příspěvku [18] - já jsem netvrdil, že to funguje, jen jsem chtěl ukázat, že se alespoň vložený text zobrazí tak jak má. Samozřejmě je to k ničemu...

Jinak ini_set('mssql.charset', 'UTF-8') jsem už také zkoušel, ale nic se nezměnilo, jen si nejsem jistý jaké kódování při tom používat v html kódu tak jsem pro jistotu zkusil jak windows-1250 tak utf-8 (i když to by mělo být podle mě nastaveno na windows-1250). Zkoušel jsem i tohle:
$dbcon = odbc_pconnect('Driver=TDS;Server=nazev_serveru;Client_CSet=UTF-8', 'username', 'password');
což také nepomohlo... už opravdu nevím.
Alphard
Profil
maycza:
i když to by mělo být podle mě nastaveno na windows-1250
Co vás k tomu vede k myšlence deklarovat cp1250, když na serveru používáte utf8? Určitě ne, jak jsem uváděl v [#2] Alphard, cp1250 neobsahuje znaky azbuky (tyto rodiny znakových sad (u nás iso-8859-2 a cp1250) jsou kódovány 8bitově s velmi omezeným rozsahem znaků, proto je pro každý region určena jiná sada). V souladu s [#20] _es lze použít utf-8, utf-16, UCS-2 (což je myslím interní kódování v MSSQL),...

Myslím, že použití entit mi také nepomůže pokud budu používat na stránce cp1250.. Když použiju utf8 tak se mi to zase blbě uloží v databázi..
To si opět myslíte špatně. Entity pomohou, díky nim lze třeba na tuto diskuse psát Москва, i když je stránka kódována v iso-8859-2 (které znaky azbuky taktéž neobsahuje).

Myslím, že by to mělo jít nastavit a že třeba někde děláte jen drobnou chybu, ale přes diskusi nedokáži poradit víc.
maycza
Profil
Alphard:
no, říkal jsem si když mám všude nastaveno utf-8, proč používat převod na utf-8... ale protože jsem si tím právě nebyl jistý tak jsem zkusil obě varianty.

S těmi entitami jsem to psal proto, protože mi příkaz htmlentities() ani htmlspecialchars() nepřevede azbuku na číselné entity a převodní tabulka ve windows1250 je pitomost právě z důvodu, který uvádíte v příspěvku [#2].

Všude teď používám kódování utf-8, v db používám Latin1_General_CP1_CI_AS, azbuku převádím na číselné entity a ukládám do databáze. Jen jsem musel rozšířit rozsah sloupce "nazev".
_es
Profil
maycza:
Používať UTF-8 a súčasne entity značne stráca zmysel, keďže v UTF-8 sa tie znaky dajú zapísať „priamo“. Zdá sa mi, že nemáš dostatočný prehľad o tom, čo je znaková sada a čo kódovanie znakovej sady. Preto len naslepo skúšaš rôzne kombinácie, či to náhodou nezačne správne fungovať. Ako písal Alphard, nejako by to asi nastaviť malo ísť. Ak sa to nepodarí rozbehnúť v UTF-8, môžeš použiť aj UCS-2, v čom by to malo ísť, ak to je vraj interné kódovanie databázy.
maycza
Profil
Tak problém vyřešen.
Rozjel jsem php na IIS7, nainstaloval ovladač ODBC Driver 11 for SQL Server, do php extensions jsem přidal sqlsrv (v php.ini přidal řádek extension=php_sqlsrv_56_nts.dll).
Připojení:
$connectionInfo = array('UID'=>'username', 'PWD'=>'pwd', 'Database'=>'jmeno_databaze', 'CharacterSet' => 'UTF-8'); 
$conn = sqlsrv_connect('server', $connectionInfo); 
if ($conn === false) die( print_r( sqlsrv_errors() ) );
Skripty mám uložené v kódování UTF-8, v html <meta charset="utf-8" />.

V db používám collation Latin1_General_CI_AI.

Vše se ukládá a zobrazuje tak jak má.

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0