Почему я получаю 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();

это работает нормально, но внезапно это перестало работать, и я получаю ошибку Oracle ORA-01722 (недопустимое число). Я проверил параметры, и все числа, несомненно, являются действительными числами. Я даже подставил фиктивные значения для любых нулей, и я все равно получаю ошибку. Я пробовал тот же запрос в direct sql (используя OraDeveloper Studio), и он работает, даже с одинаковые параметры.

Как я могу отследить это?

EDIT: на запрос в комментариях, вот инструкция create table:

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;

3 ответов


Я уже дал ответ кредит, но я думаю, что стоит упомянуть здесь именно то, что корень моих проблем был, в случае, если кто-то еще найдет этот пункт, ища ответ на свою собственную проблему.

проблема в том, что реализация c# параметризованных запросов для Oracle содержит серьезную и потенциально опасную ошибку - настоящую "яму в общественном достоянии":

неважно, что вы называете свои параметры, они должны быть добавлены в порядок, в котором они отображаются в запросе.

Посмотреть подробнее здесь.


когда вы говорите, вы проверили параметры вы имеете в виду Parameters коллекция в классе SqlCommand? Вы можете попасть в фол эта заметка на странице SqlParameter:

будьте осторожны при использовании этой перегрузки конструктора SqlParameter для указания значений целочисленных параметров. Поскольку эта перегрузка принимает значение типа Object, необходимо преобразовать интегральное значение в тип объекта, когда значение равно нулю, как показано в следующем примере C# демонстрирует. Копия

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

Если вы не выполняете это преобразование, компилятор предполагает, что вы пытаетесь вызвать перегрузку конструктора sqlparameter (string, SqlDbType).

Я предлагаю вам использовать что-то вроде

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

вместо этого явно установить тип.


command.BindByName = true;

смотрите explination.