【问题标题】:ORA-01400 can't insert null value... but I am NOT inserting null value!ORA-01400 无法插入空值...但我没有插入空值!
【发布时间】:2011-07-16 10:52:19
【问题描述】:

我正在尝试使用 C# 应用程序中的 ODP.NET 在 Oracle 表中插入数据,但我收到 ORA-01400 can't insert null value 错误我没有插入空值。

这是我尝试执行的参数化 SQL 命令的精简版本。它被包裹在OracleCommand 中,并通过ExecuteNonQuery 的调用执行:

declare c int; 
begin
   select count(*) into c from "Entradas" where "Id" = :Id and nvl("AppId", 0) = nvl(:AppId, 0);
   if c>0 then
       update "Entradas" set
         /*...a bunch of columns...*/,
         "VisitaLaboral" = :VisitaLaboral,
         /*...some more columns...*/
         where "Id" = :Id and nvl("AppId",0) = nvl(:AppId, 0); 
   else
       insert into "Entradas" (
         /*... a bunch of columns...*/,
         "VisitaLaboral",
         /*...some more columns...*/
         ) values (
         /*...a bunch of values...*/,
         :VisitaLaboral,
         /*...some more values...*/
       );
   end if;
end;

该行以前不存在,因此它是命令的insert 部分被执行。当然我已经验证了所有列名和列值参数都正确放置在 SQL 文本中。

问题出在VisitaLaboral 列中。它的类型为 NUMBER(1,0),它不接受 NULL,我正在尝试插入一个值 0。这是 Visual Studio 在命令执行前立即显示的关于关联的OracleParameter 的内容:

但是,如果我直接在 Application Express 中执行命令(直接在命令文本中提供值),它可以正常工作并插入行。

那么,这里发生了什么? ODP.NET 库中是否存在错误,或者我做错了什么?

附加信息:

  • 数据库是 Oracle 10g Express Release 10.2.0.1.0
  • Oracle.DataAccess.dll 版本为 4.112.1.2
  • 使用 Visual Studio 2010,面向 .NET framework 4.0

提前谢谢你!

更新:

如果我使用(已弃用)System.Data.OracleClient 类而不是 ODP.NET,一切正常。

WTF,甲骨文?不,真的,WTF?

【问题讨论】:

  • 我不知道,但 this question 可能会让你感兴趣。
  • 您是否尝试过 ODP 中的“command.bindbyname = True”(System.Data.OracleClient 默认按名称绑定,而 ODP 默认按位置绑定)。试试 bindbyname=true 看看会发生什么
  • @Harrison:是的,在另一个 SO 问题中看到并尝试过,但也没有用。
  • 7 年后仍然遇到类似的事情......我放了 if 语句以防止在我的数据上下文中插入空值,但仍然设法尝试插入空值......

标签: oracle odp.net oracle-xe ora-01400


【解决方案1】:

您的问题似乎是您不知道数据库中实际发生了什么。最快的解决方案是找出发生了什么并使用它。

  1. 连接数据库
  2. 使用 dbms_session.set_sql_trace(true) 启用 sql 跟踪
  3. 执行您的应用程序操作
  4. 从数据库断开
  5. 查找 - 或要求您的 dba - 将原始跟踪文件发送给您

在跟踪文件(纯文本文件)中找到您的代码并查看引发错误时会发生什么。

可能是触发器触发了......

【讨论】:

    【解决方案2】:

    我们遇到了同样的问题。我们解决了将列属性“IsNullable”设置为 true 的问题。

    【讨论】:

    • 但该列实际上不可为空。反正我试过了,还是不行。
    • @Konamiman:当您将列设置为可为空时,问题仍然存在......这意味着问题出在其他地方。可能是另一列...?
    【解决方案3】:

    好吧,我对 ODP.net 一无所知,但如果参数中有一个值,那么精度、比例和大小属性是否都应该为零(看起来是这样)?

    【讨论】:

    • 好主意,但将精度设置为 1(该列的精度为 1,比例为 0)不起作用。
    • 在您的示例中,您尝试传入零值,它是否适用于非零值?
    【解决方案4】:

    这是一个数据库级别的错误信息,你可以确定插入的值为空。是否可以注销ODP.NET生成的sql语句?

    【讨论】:

    • Is 是一个 OracleCommand.ExecuteNonQuery 调用,所以除非我遗漏了什么,否则 ODP.NET 不会生成任何 SQL 语句,因为我直接提供它。无论如何,我该如何配置这样的日志记录?
    【解决方案5】:

    您真的确定插入子句和值子句中的列顺序相同吗?检查您的“一堆列”...

    【讨论】:

    • 这是我仔细检查的第一件事。一切似乎都在正确的位置。
    • @konaniman,我同意@Stefan 的观点,我建议将命令对象上的 bindbyname 设置为 true [command.bindbyname = True],确保命令参数中的名称与匿名块匹配,那么您将无需担心订单。这些问题通常与参数顺序问题有关。
    猜你喜欢
    • 2016-06-21
    • 1970-01-01
    • 2018-11-08
    • 2016-03-30
    • 2011-08-23
    • 2017-09-01
    • 2011-10-09
    • 2013-02-21
    • 2016-08-21
    相关资源
    最近更新 更多