6

关于在 Sql 语句中使用 .Net DateTime 有几个问题,但没有一个能解决我的问题。

我正在使用以下代码查询 Oracle 数据库:

private DataTable QueryByIdAndDate(string id, DateTime fdate, DateTime tdate) {
    string query = "SELECT * FROM table WHERE ID = :id AND DATE_TIME BETWEEN :from AND :to"
    DbCommand cmd = db.CreateCommand();
    cmd.CommandType = CommandType.Text;
    cmd.CommandText = query;

    DbParameter fromDate = CreateDateParameter(cmd, fdate);
    fromDate.ParameterName = "from";
    DbParameter toDate = CreateDateParameter(cmd, tdate);
    toDate.ParameterName = "to"; 
    DbParameter idParam = CreateStringParameter(cmd, id);
    idParam.ParameterName = "id";

    cmd.Parameters.AddRange(new DbParameter[] { fromDate, toDate, idParam });
    return db.ExecuteQuery(cmd);
}

private DbParameter CreateDateParameter(DbCommand cmd, DateTime date) {
    DbParameter param = cmd.CreateParameter();
    param.DbType = DbType.DateTime;
    param.Direction = ParameterDirection.Input;
    param.Value = date;
    return param;
}

但它不能正常工作。像这样尝试代码时:

DataTable result = QueryByIdAndDate("12345", DateTime.Now, DateTime.Now.AddDays(1));

它给出了以下错误: ORA-01847: day of month must be between 1 and last day of month

我假设它与 DateTime 的格式化方式有关,但我不知道以可靠方式解决此问题的正确方法。

4

4 回答 4

11

(根据评论...)

看起来在这种情况下,参数的顺序很重要......尽管您已经给它们起了名字。我没想到会这样,这是驱动程序有些损坏的迹象,但是将您的代码更改为:

cmd.Parameters.AddRange(new DbParameter[] { idParam, fromDate, toDate });

应该修复它。(顺便说一下,这不一定是您构建参数的方式,但这在这里有些无关紧要。)

不要开始日期/时间值指定为字符串。引入比您需要的更多的字符串转换是一个非常糟糕的主意。

于 2012-04-24T20:18:18.427 回答
3

DateTime值转换为格式化的日期字符串:

private DbParameter CreateDateParameter(DbCommand cmd, DateTime date) 
{
     DbParameter param = cmd.CreateParameter();
     param.DbType = DbType.DateTime;
     param.Direction = ParameterDirection.Input;
     param.Value = date.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
     return param;
} 

即使您正在发送一个字符串值,DbType仍然设置为DateTime,因此该值应该被正确转换。

于 2012-04-24T20:11:18.883 回答
2

Oracle 期望日期格式为“DD-Mon-YYYY”,因此您需要基本上以这种方式格式化您的日期值并将其分配给参数值。

编辑:我注意到最近版本的 ODP 似乎可以更好地处理日期时间参数。例如,当 WHERE 子句对日期/时间列有约束时,这很好用:

DateTime dt = new DateTime(2012, 5, 21);
cmd.Parameters.Add("some_date_param", dt);

使用最新版本的 ODP 以这种方式运行查询可以正常工作。但是我有很多代码需要将日期/时间值作为格式化字符串传递,以便 Oracle 接受它们。

于 2012-04-24T20:15:02.810 回答
2

对于那些可能会错过它的人,请参阅@kprobst在@JonSkeet接受的答案下的评论

如果您尝试使用名称绑定而不BindByNameCommand.

(整个 Oracle 提供程序 API 是一堆垃圾恕我直言)。

于 2016-11-22T14:58:19.423 回答