为什么我收到ORA-01722(无效号码)?

Sha*_*ica 8 c# oracle ora-01722

我一直在使用参数化查询将值插入到Oracle表中,如下所示:

var q = "insert into MyTable(Field1, Field2...) values(:Field1, :Field2...)";
var cmd = new OracleCommand(q, conn); // conn is a pre-existing connection
cmd.Parameters.Add("Field1", field1Val); 
cmd.Parameters.Add("Field2", field2Val);
// etc...
cmd.ExecuteNonQuery();
Run Code Online (Sandbox Code Playgroud)

这一直工作正常,但突然这已停止工作,我收到Oracle错误ORA-01722(无效数字).我检查了参数,所有数字无疑都是有效的数字.我甚至为任何空值替换了虚拟值,我仍然得到错误.我在直接sql中尝试了相同的查询(使用OraDeveloper Studio),即使使用相同的参数也可以.

如何跟踪这个?

编辑:评论中的每个请求,这是创建表语句:

CREATE TABLE ALPHA.VISITFINDINGS (
  ID NUMBER(12),
  VISITID NUMBER(12) NOT NULL,
  DESCRIPTION VARCHAR2(100),
  CUSTOMIMAGE CLOB,
  VISUALFINDINGSSECTIONMAPID NUMBER(12),
  FINDINGSID NUMBER(12),
  CONSTRAINT FK_VISITFINDINGS_AREA FOREIGN KEY (VISUALFINDINGSSECTIONMAPID)
    REFERENCES ALPHA.VISUALFINDINGSSECTIONMAP(VISUALFINDINGSSECTIONMAPID),
  CONSTRAINT FK_VISITFINDINGS_FINDINGS FOREIGN KEY (FINDINGSID)
    REFERENCES ALPHA.FINDINGS(FINDINGSID),
  CONSTRAINT FK_VISITFINDINGS_VISIT FOREIGN KEY (VISITID)
    REFERENCES ALPHA.VISITS(VISITID),
  CONSTRAINT PK_VISITFINDINGS PRIMARY KEY (ID))
TABLESPACE USERS
STORAGE (
  INITIAL 64K
  MAXEXTENTS UNLIMITED
)
LOGGING;
Run Code Online (Sandbox Code Playgroud)

Sha*_*ica 38

我已经给出了答案信用,但我认为这里确实值得一提的是我的问题的根源是什么,以防其他人在寻找他们自己问题的答案时找到这个项目.

问题是Oracle的参数化查询的C#实现包含一个严重且有潜在危险的错误 - 一个真正的"公共领域":

你的参数命名无关紧要; 它们必须按照它们在查询中出现的顺序添加.

在这里查看更多.

  • 它在另一个主题中声称这不是一个错误,而是一个功能.当然,它是一个非常危险和无用的功能,因为它既是一个功能又是一个bug.但是,他们说如果你设置OracleCommand.BindByName = true,它将按预期工作. (3认同)
  • 由于这个更准确,你应该从我的答案中删除检查并标记这个! (2认同)
  • 这不是bug,你可以通过设置属性command.BindByName = true;来强制Oracle按名称匹配参数。 (2认同)

Rup*_*Rup 5

当你说你检查参数时,你的意思Parameters是SqlCommand类上的集合?您可能会在SqlParameter页面上违反此注释:

使用SqlParameter构造函数的此重载指定整数参数值时请小心.因为此重载采用Object类型的值,所以当值为零时,必须将整数值转换为Object类型,如下面的C#示例所示.复制

Parameter = new SqlParameter("@pname", Convert.ToInt32(0));
Run Code Online (Sandbox Code Playgroud)

如果不执行此转换,编译器会假定您尝试调用SqlParameter(string,SqlDbType)构造函数重载.

我建议你使用类似的东西

cmd.Parameters.Add(
   new SqlParameter("Field1", SqlDbType.Int32) { Value = field1Val });
Run Code Online (Sandbox Code Playgroud)

而是明确设置类型.

  • OP使用的是Oracle,而不是SQL Server,所以这将是OracleParameter ......但你的答案仍然存在.然而,它并没有解释为什么它曾经工作...... (3认同)