學海無涯!

一直以來,要放Unicode文字就得開NVARCHAR欄位的觀念深植我心。直到今天聽一位同事說: 如果Oracle資料庫的字元集設成Unicode,開VARCHAR就好了,不必為Unicode特意開NVARCHAR。

這顛覆了我的認知,但也不確定我根深蒂固的觀念是否隨軟體版本演進早已有所誤差。在噗浪上發問後,陸續收到一些回應: Access, MySQL, PostgreSQL都是如此(謝謝Bill, 鳥毅),噗友王圓外更是直接證實這點,於是也我寫了個小程式,找了台NLS_CHARACTERSET=AL32UTF8的Oracle驗證:

using (OracleConnection cn = new OracleConnection(cnStr))
{
    cn.Open();
    OracleCommand cmd = new OracleCommand();
    cmd.Connection = cn;
    cmd.CommandText = 
        "SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER = 'NLS_CHARACTERSET'";
    OracleDataReader dr = cmd.ExecuteReader();
    dr.Read();
    Response.Write("<li>NLS_CHARACTERSET=" + dr[1].ToString());
    cmd.CommandText = "CREATE TABLE JEFFTEST (T1 VARCHAR2(16), T2 NVARCHAR2(16))";
    cmd.ExecuteNonQuery();
    cmd.CommandText = "INSERT INTO JEFFTEST VALUES (:p1, :p2)";
    cmd.Parameters.Add("p1", OracleType.VarChar).Value = "犇";
    cmd.Parameters.Add("p2", OracleType.NVarChar).Value = "犇";
    cmd.ExecuteNonQuery();
    cmd.CommandText = "SELECT * FROM JEFFTEST";
    cmd.Parameters.Clear();
    dr = cmd.ExecuteReader();
    dr.Read();
    Response.Write("<li>T1=" + dr[0].ToString());
    Response.Write("<li>T2=" + dr[1].ToString());
    cmd.CommandText = "DROP TABLE JEFFTEST";
    cmd.ExecuteNonQuery();
}

執行結果如下,證明當Oracle NLS_CHARACTERSET=AL32UTF8時,VARCHAR2也能存Unicdoe。

  • NLS_CHARACTERSET=AL32UTF8
  • T1=犇
  • T2=犇
  • 不過,如果涉及多台DB,我不確定有的用VARCHAR,有的用NVARCHAR是否會有問題? 在工作環境涉及的Oracle在未全面採行Unicode前,我想我還是會採用NVARCHAR較保險(反正沒有損失)。


    Comments

    # by bcse

    (舉手) 可是 Access, MySQL, PostgreSQL 根本沒有 NVARCHAR 呀…

    Post a comment