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

发布于 2024-09-26 04:34:55 字数 1259 浏览 6 评论 0原文

我一直在使用参数化查询将值插入到 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();

这一直工作正常,但突然停止工作,并且我收到 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;

I've been using a parameterized query to insert values into an Oracle table, like so:

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();

This has been working fine, but suddenly this has stopped working, and I am getting Oracle error ORA-01722 (invalid number). I have checked the parameters, and all numbers are unquestionably valid numbers. I even substituted dummy values for any nulls, and I still get the error. I tried the same query in direct sql (using OraDeveloper Studio), and it works, even with the identical parameters.

How do I track this one down?

EDIT: per request in the comments, here's the create table statement:

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

忘东忘西忘不掉你 2024-10-03 04:34:55

我已经给出了答案,但我认为值得在这里提及我的问题的根源是什么,以防其他人在寻找自己问题的答案时发现这个项目。

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

:它们必须按照它们在查询中出现的顺序添加。

查看更多此处

I have given answer credit already, but I think it's worth mentioning here exactly what the root of my problems was, in case anyone else finds this item while looking for an answer to their own problem.

The problem is that the C# implementation of parameterized queries for Oracle contains a serious and potentially dangerous bug - a real "pit in the public domain":

It doesn't matter what you name your parameters; they have to be added in the order in which they appear in the query.

See more here.

溺渁∝ 2024-10-03 04:34:55

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

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

Parameter = new SqlParameter("@pname", Convert.ToInt32(0));

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

我建议您使用类似的东西

cmd.Parameters.Add(
   new SqlParameter("Field1", SqlDbType.Int32) { Value = field1Val });

来显式设置类型。

When you say you checked the parameters do you mean the Parameters collection on the SqlCommand class? You might be falling foul of this note on the SqlParameter page:

Use caution when you use this overload of the SqlParameter constructor to specify integer parameter values. Because this overload takes a value of type Object, you must convert the integral value to an Object type when the value is zero, as the following C# example demonstrates.
Copy

Parameter = new SqlParameter("@pname", Convert.ToInt32(0));

If you do not perform this conversion, the compiler assumes that you are trying to call the SqlParameter (string, SqlDbType) constructor overload.

I'd suggest you use something like

cmd.Parameters.Add(
   new SqlParameter("Field1", SqlDbType.Int32) { Value = field1Val });

instead to explicitly set the type.

青朷 2024-10-03 04:34:55
command.BindByName = true;

请参阅此解释。

command.BindByName = true;

Please see this explination.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文