Tuesday, June 7, 2005

OCIStmtExecute problem

Есть набор записей (0, 1, 2, 3, 4, 5) с некоторым количеством полей.
Есть primary key в таблице.
Есть insert into... sql statement.

Ситуация 1.
Пусть запись 2  со значением поля, соответствующему PK, значение, которое уже есть в базе, в остальных - отличается.
Если прибиндить весь массив и попытаться сделать OCIStmtExecute , то вставятся записи 0 и 1.
Всё отлично. Так и должно быть - после commit записи видны в других сессиях.

Ситуация 2.
Пусть в записях 1 и 2 значения полей, соответствующиз PK совпадают между собой, но отсутствуют в базе. Остальные - тоже отсутствуют.
Делается такой же OCIStmtExecute. В ответ я ожидаю, что по крайней мере запись 0 добавится в базу. Но этого не происходит.
(nb: во втором случае, естесственно также делается commit)

Вопрос - куда копать. Вдруг кто знает.

8 comments:

  1. "папа, а ты сейчас с кем разговаривал?"

    ReplyDelete
  2. Похоже, что изменения фиксируются только тогда, когда не нарушается целостность импортируемых данных.
    В первом случае сами 6 записей целостны, дублирования ключа нет. В этом случае вставка идет до нарушения целостности в самой базе данных, все удачные вставки фиксируются.
    Во втором случае нарушена целостность в самих 6 записях. Видимо, OCIStmtExecute сначала проверяет целостность импортируемых данных. Если она нарушена, то импорт не происходит вообще, поэтому commit и не фиксирует вставку записи с номером 0 (в указанном выше примере).
    Механизм работы OCIStmtExecute мне неизвестен, но можно предположить, что существуют ошибки после которых работа OCIStmtExecute аварийно завершается. Судя по всему, нарушения целостности внутри самих импортируемых данных входят в этот список.

    P.S. Кстати, я в зимнюю сессию вам экзамен по винде сдавал. Мир тесен ;)

    ReplyDelete
  3. что либо целостность проверяется иначе, либо есть какая-то "внутренняя" транзакция, в которой говорится rollback в случае определённого противоречия.

    Тут собственно иных вариантов-то нет, осталось найти доку, в которой это постулируется, первоисточник так сказать. Вопрос в том, почему такое разительное отличие в механзме проверки!

    ReplyDelete
  4. Насчет первоисточника ничем помочь не могу...
    А почему различие? В обоих случаях проверка идет по одному алгоритму: 1) проверяется целостность вставляемых данных (между собой, если так можно выразиться), а потом 2) если сами вставляемые данные корректны, то производиться последовательная вставка в таблицу до первого нарушения целостности.
    В рассмотренном выше примере в Случае 1 мы доходим до шага 2), т.е. вставка происходит до 1-й ошибки ;в Случае 2 останавливаемся на шаге 1), т.е. вставка в таблицу не происходит вообще из-за того, что функция посчитала импортируемые данные некорректными
    Все это ИМХО, основанное на приведенном примере. Точно утверждать не могу

    ReplyDelete
  5. На самом деле это легко проверить, BTW. Надо попробовать на каком-нибудь другом языке ( не с++ ) попробовать сделать batch insert. Всего делов-то!

    ReplyDelete
  6. Мда, я, кажется, не помогу.
    Слова все знакомые :) Но смысл ускользает.

    ReplyDelete
  7. Ой, прочитала дискуссию:))) Оказывается, что PK - это праймэри кэй я не доперла :)

    ReplyDelete
  8. ...копать в сторону OCI_BATCH_ERRORS

    и т.д. ...

    Видимо всё же то, что Oracle добавляет записи в первом случае последовательно - некая случайность (хотя с другой стороны, именно в случае batch insert можно было бы ожидать и то, что такое поведение нормально). А вот во втором случае уже всё не так хорошо, а OCI_BATCH_ERRORS позволяет получить коллекцию(?) ошибок, с помощью которых (которой) уже можно отследить сбойную (сбойные) записи, что есть good.

    ReplyDelete