[.NET] Oracle Client Exception - ORA-01722

摘要:[.NET] Oracle Client Exception - ORA-01722

最近的專案使用Oracle DB。在.NET裡可以使用Oracle Client,來對Oracle DB下SQL指令。寫了下面的程式碼,用來取得User資料表裡的User資料。



using (OracleConnection connection = new OracleConnection(connectionString))
{
    connection.Open();
    using (OracleCommand command = new OracleCommand())
    {
        command.Connection = connection;
        command.Parameters.Add(":lastName", "Chou");
        command.Parameters.Add(":firstName", "Clark");
        command.CommandText = @"SELECT * FROM USER_DATA WHERE FIRST_NAME=:firstName AND LAST_NAME=:lastName";

        using (OracleDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                // XXXXXXX
            }
            connection.Close();
        }
    }
}

快速打完、按下執行。卻產生了讓人摸不清頭緒的錯誤例外「ORA-01722:無效的數字」。



搞了半天才發現使用OracleCommand.Parameters來加參數是有順序性的。在OracleCommand.CommandText裡參數出現的順序,必須要和OracleCommand.Parameters是一致的。也就是下列的程式碼才能正常執行:



using (OracleConnection connection = new OracleConnection(connectionString))
{
    connection.Open();
    using (OracleCommand command = new OracleCommand())
    {
        command.Connection = connection;
        command.Parameters.Add(":firstName", "Clark");
        command.Parameters.Add(":lastName", "Chou");        
        command.CommandText = @"SELECT * FROM USER_DATA WHERE FIRST_NAME=:firstName AND LAST_NAME=:lastName";

        using (OracleDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                // XXXXXXX
            }
            connection.Close();
        }
    }
}

在網路上與朋友討論這個問題與解法。經由Demo的提點,才知道原來只要將OracleCommand.BindByName設定為True就可以解決這個問題。範例程式如下:



using (OracleConnection connection = new OracleConnection(connectionString))
{
    connection.Open();
    using (OracleCommand command = new OracleCommand())
    {
        command.BindByName = true;
        command.Connection = connection;
        command.Parameters.Add(":lastName", "Chou");
        command.Parameters.Add(":firstName", "Clark");
        command.CommandText = @"SELECT * FROM USER_DATA WHERE FIRST_NAME=:firstName AND LAST_NAME=:lastName";

        using (OracleDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                // XXXXXXX
            }
            connection.Close();
        }
    }
}

趁還有印象快速紀錄一篇下來,為自己做個紀錄,也希望能幫助到有需要的開發人員。 當然也要再次感謝Demo大大。:D


期許自己
能以更簡潔的文字與程式碼,傳達出程式設計背後的精神。
真正做到「以形寫神」的境界。