【问题标题】:ORA-01843: not a valid month - issue on second pcORA-01843: 无效的月份 - 第二台电脑上的问题
【发布时间】:2016-10-03 04:35:39
【问题描述】:

在我的电脑 (Win7) 上,该语句运行没有错误。如果我将 c# .exe 复制到程序最终应该运行的服务器(Win2012 服务器),那么我会收到错误

ORA-01843: 月份无效

我读取了一个 csv 文件并将其插入到带有语句的 oracle-db 中

command.CommandText = "INSERT INTO table (DATUM, ...) VALUES('" + dr[0].ToString() + "',..."')";

dr[0].ToString() 的值为 "01.06.2016"

DATUM 列是 oracle-db 中的 DATE 类型。

我用消息框调试了代码并得到了这个结果:

我看不出这两条语句有什么区别,当我执行int rowsupdated = command.ExecuteNonQuery();时,来自服务器的左边一条正在调用错误

我已经比较了区域设置,它们在两个系统上都是相同的(德语)。还有什么可能导致问题?谢谢

填写Datatable的部分(dr的来源):

StreamReader oStreamReader = new StreamReader(Zielverzeichnis + Dateiname, System.Text.Encoding.UTF8); //nach, für Umlaute

                    DataTable dtCSV_Import = null;
                    int RowCount = 0;
                    string[] ColumnNames = null;
                    string[] oStreamDataValues = null;
                    //using while loop read the stream data till end
                    while (!oStreamReader.EndOfStream)
                    {
                        String oStreamRowData = oStreamReader.ReadLine().Trim();
                        if (oStreamRowData.Length > 0)
                        {
                            oStreamDataValues = oStreamRowData.Split(';');
                            //Bcoz the first row contains column names, we will poluate 
                            //the column name by
                            //reading the first row and RowCount-0 will be true only once
                            if (RowCount == 0)
                            {
                                RowCount = 1;
                                ColumnNames = oStreamRowData.Split(';');
                                dtCSV_Import = new DataTable();

                                //using foreach looping through all the column names
                                foreach (string csvcolumn in ColumnNames)
                                {
                                    DataColumn oDataColumn = new DataColumn(csvcolumn.ToUpper(), typeof(string));

                                    //setting the default value of empty.string to newly created column
                                    oDataColumn.DefaultValue = string.Empty;

                                    //adding the newly created column to the table
                                    dtCSV_Import.Columns.Add(oDataColumn);
                                }
                            }
                            else
                            {
                                //creates a new DataRow with the same schema as of the oDataTable            
                                DataRow oDataRow = dtCSV_Import.NewRow();

                                //using foreach looping through all the column names
                                //Prüfen was kleiner ist, Spalten aus XML oder tatsächliche Spalten in der CSV -> sonst Fehler [i]
                                if (oStreamDataValues.Length < ColumnNames.Length)
                                {
                                    for (int i = 0; i < oStreamDataValues.Length; i++)
                                    {
                                        oDataRow[ColumnNames[i]] = oStreamDataValues[i] == null ? string.Empty : oStreamDataValues[i].ToString();
                                    }
                                }
                                else
                                {
                                    for (int i = 0; i < ColumnNames.Length; i++)
                                    {
                                        oDataRow[ColumnNames[i]] = oStreamDataValues[i] == null ? string.Empty : oStreamDataValues[i].ToString();
                                    }
                                }

                                //adding the newly created row with data to the oDataTable       
                                dtCSV_Import.Rows.Add(oDataRow);
                            }
                        }
                    }
                    //close the oStreamReader object
                    oStreamReader.Close();
                    //release all the resources used by the oStreamReader object
                    oStreamReader.Dispose();

【问题讨论】:

  • 永远不要依赖隐式转换。这取决于用于会话的 NLS 设置。而是始终明确提供格式:to_date(stringval,'dd-mm-yyyy')
  • dr 到底是什么?它是数据阅读器吗?而不是字符串连接,为什么不将其转换为 DateTime (我假设它是 object )并使用参数化查询添加它?为什么你用mysql标记?
  • 您确实也比较了两个系统上的表定义,不是吗?您介意在此处添加吗?
  • @katz 很好用。请考虑接受 MT0 的回答,除了 to_date 他还涵盖其他选项
  • 为什么要存储DATUM(日期)和ZEIT(时间)列?合并两者并将其全部存储在一个 DATE 列中 - 日期总是有一个时间部分。

标签: c# oracle date datetime


【解决方案1】:

如果您将值插入日期列并尝试插入字符串值,那么 Oracle 将使用 NLS_DATE_FORMAT 会话参数作为格式掩码隐式调用 TO_DATE()。如果此格式掩码不匹配,则会出现异常。

会话参数可以由各个用户在其会话中设置 - 因此,如果用户 Alice 具有预期的参数,这并不意味着用户 Bob 将具有相同的参数,并且您使用的相同查询将无法正常工作,因为您依赖隐式转换值。或者更糟糕的是,Bob 今天有预期的参数,然后明天决定他更喜欢他的日期格式为 DD-MON-YYYY 并更改他的 NLS_DATE_FORMAT 突然间,在不更改代码的情况下,一切都中断了,你会有一个非常糟糕的是时候调试错误了。

如果你想插入一个日期,那么:

  1. 将其作为绑定变量(最佳选择)传递,而不将其转换为字符串;或
  2. 使用日期文字(即DATE '2016-06-01');或
  3. 使用带有指定格式掩码的TO_DATE()(即TO_DATE( '" + dr[0].ToString() + "', 'DD.MM.YYYY' ))。

您可以阅读有关bind variables in the Oracle Documentationthis SO question 的信息。

【讨论】:

    猜你喜欢
    • 2014-08-03
    • 1970-01-01
    • 1970-01-01
    • 2015-07-04
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 2012-05-13
    相关资源
    最近更新 更多