วันพฤหัสบดีที่ 19 กรกฎาคม พ.ศ. 2555

ทดสอบ thai language (oracle) กับ Browser


เมื่อกลับไปอ่านบทความเดิม ที่เคยทดสอบมานานแสนนาน ก็เจอว่าเคยใช้เวลาบางช่วงกับการทดสอบ thai language ด้วย browser กับ Oracle Database
SQL> select * from database_properties where PROPERTY_NAME like 'NLS_CHAR%';
PROPERTY_NAME                  PROPERTY_VALUE       DESCRIPTION
------------------------------ -------------------- ------------------------------
NLS_CHARACTERSET               TH8TISASCII          Character set
สิ่งหนึ่งที่น่าคิดทำไมใช้ TH8TISASCII ละครับ ง่ายมาก... เพราะผมเก็บภาษาไทยใน VARCHAR2 (1 ตัวอักษรเท่ากับ 1 byte)
ถ้าใช้ AL32UTF8 ละ ถ้าเก็บภาษาไทยใน VARCHAR2 (อาจเจอ 1 ตัวอักษร = 3 bytes) จริงไม่จริงก็ต้องลองทดสอบกันดู ในกรณีที่ใช้ AL32UTF8 แล้วอยากเก็บภาษาไทย แต่ไม่ให้ (1 ตัวอักษร = 3 byte) คงยาก ลองไปใช้ NVARVAR2 ดูสิอาจช่วยได้
อย่างไรก็ดี นั่นคือเรื่องเล่า แต่สิ่งที่น่าสนใจ ต้องถามว่า  nls_length_semantics มีค่าเป็น
SQL> show parameter nls_length_semantics
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
nls_length_semantics                 string      BYTE
นั่นแหละ คือสิ่งที่ต้องรู้ เอาแบบเร็วๆ (NLS_LENGTH_SEMANTICS enables you to create CHAR and VARCHAR2 columns using either byte or character length semantics.)
ก็ตามภาษาอังกฤษนั่นแหละ ดังนั้นลอง เปลี่ยน column VARCHAR2 เป็น character length semantic ดูแล้วทดสอบ ว่าเป็นอย่างไร

กลับมากับการทดสอบ Browser เล่นๆ กัน ด้วย PHP ต้องขอบอกก่อนที่ PHP นั้นผมได้เซต NLS_LANG=.TH8TISASCII  อยู่แล้วนะครับ

นี่คือข้อมูลที่มี หลังจาก INSERT ด้วย Browser บ้าง Client Program บ้าง
SQL> select * from tab_char;
A
--------------------------------------------------
à¸à¸”ี1
ดี2
ต่อจากนนั้นผมก็เขี่ยน PHP ง่าย Query มันออกมา จากนั้นเปลี่ยน Encoding บนBrowser ดู

<?php
$conn = oci_pconnect("test_char", "test_char", "DB");
$stmt = oci_parse($conn, "select * from tab_char");
    oci_execute($stmt, OCI_DEFAULT);
    while (oci_fetch($stmt)) {
        echo "    " . oci_result($stmt, "A") . "<br>\n";
    }

?>

(IE) Web result: 
- Thai (windows)
เธ”เธต1
ดี2

- Unicode (UTF8)
ดี1
ดี2

(Firefox) Web result: 
- windows (iso-8859-1)
ดี1
ดี2

-Unicode (UTF8)
ดี1
ดี2

- TIS 620
เธ”เธต1
ดี2

จากนั้นลอง INSERT จาก Browser ด้วย Encoding ที่ต่างๆ ออกไป
<?php
$x=$_POST['DATA'];
$conn = oci_pconnect("test_char", "test_char", "DB");
$stmt = oci_parse($conn, "insert into tab_char values ('$x')");
oci_execute($stmt, OCI_DEFAULT);
oci_commit($conn);

$stmt = oci_parse($conn, "select * from tab_char");
    oci_execute($stmt, OCI_DEFAULT);
    while (oci_fetch($stmt)) {
        echo "    " . oci_result($stmt, "A") . "<br>\n";
    }

?>

5 กรณี 
- ISO-8859-1  
DATA = ดี201

- UTF-8 
DATA = ดี202

- Windows-1252
DATA = ดี203

- TIS-620
DATA = ดี204

- Windows-874
DATA = ดี205

จากนั้นลองใช้ SQL*Plus ดึงข้อมูลออกมาดู
A
--------------------------------------------------
ดี201
ดี203 

à¸à¸”ี202
��204
��205
สรุปได้ว่า!
- Character-Encoding บน Browser มีผลกับขอ้มูลที่ insert ลง table
- ถ้าเรียกใช้ Character-Encoding ใดในการ Insert ข้อมูล... ควรต้องใช้ Character-Encoding นั้นในการโชว์ข้อมูล
- PL/SQL developer (NLS_LANG=AMERICAN_AMERICA.TH8TISASCII) สามารถโชว์ข้อมูล ที่เกิดจาก Character-Encoding (TIS-620,Windows-874) ได้ดี

*** นี่เป็นการทดสอบขำๆ แต่หวังว่าจะมีประโยชน์ กับคนอ่าน ***