#oracle #delphi #sql
Доброго времени суток. Есть задача: синхронизировать данные с Active Directory через LDAP. Т.е. при нажатии на какую-то кнопку "Синхронизация" в программе, написанной на Delphi, обновлять все существующие и добавлять новые записи в БД Oracle. Как я понимаю, для этого в Oracle есть операция MERGE INTO [...]. Но чтобы не грузить БД и не заставлять ее парсить 1500 запросов каждый раз, хотелось бы сделать все это с использованием подготовленных (параметрических) запросов. С этой БД я работал мало, поэтому сразу возникли вопросы. Запрос у меня получился приблизительно таким (точный сказать не могу пока, но вроде такой он и есть): MERGE INTO testtable USING( SELECT :field1_s field1, :field2_s field2, :field3_s field3, :field4_s field4 FROM dual ) data ON (data.field4 = testtable.field4) WHEN MATCHED THEN UPDATE SET testtable.field1 = data.field1, testtable.field2 = data.field2, testtable.field3 = data.field3 WHEN NOT MATCHED THEN INSERT VALUES(NULL, data.field1, NULL, data.field2, data.field3, NULL, data.field4) На field4 в таблице testtable стоит уникальный индекс и по этому полю происходит проверка на существование данной записи в таблице. В Delphi я использую компоненты ADO (AdoConnection, AdoQuery) для работы как с базой Oracle, так и с Active Directory. Я закрепляю за данным запросом параметры field1_s, field2_s и т.д., а затем задаю последовательно значения для параметров через AdoQuery.Parameters.ParamByName('field1_s').Value. Когда я вызываю процедуру AdoQuery.ExecSQL, Oracle выдает мне свою ошибку, что не все параметры были заполнены, а конкретно: ORA-01008 not all variables bound Уже что только не делал. Все чего добился - это другая ошибка: ORA-01036: illegal variable name/number, что конечно же не лучше :) Теперь еще хотелось бы отметить, что такой же параметрический обычный INSERT отрабатывает нормально и все данные заносятся в таблицу: INSERT INTO testtable VALUES(NULL, :field1_s, NULL, :field2_s, :field3_s, NULL, :field4_s) А следовательно напрашивается вывод о том, что все дело в SQL-запросе. Но вот что с ним - ума не приложу! Может все дело в подзапросе SELECT, который я использую для MERGE? Например, может виновата строчка ... FROM dual, которую я добавил только из-за того что оракл ругался на отсутствие ключевого слова FROM? Если да, то как можно переписать данный запрос, так чтобы Oracle вставил данные не из существующей таблицы, а новые данные, которые передает моя программа? Версию Oracle на сервере точно не могу сказать, но вроде - 11. По крайней мере, клиент я использую версии 11. Подскажите, куда мне копать? Надеюсь, объяснил все понятно. Заранее спасибо. UPD: Версия Oracle на сервере все-таки 9.2. Параметры в делфи биндю вот так: q_temp.SQL.Clear; q_temp.Close; q_temp.SQL.Add('MERGE INTO testtable USING ' + '(SELECT :field1_s, :field2_s, :field3_s, :field4_s FROM dual) ' + .... ); q_temp.ParamCheck := true; q_temp.Prepared := true; for i := 0 to 10 do begin q_temp.Parameters.ParamByName('field1_s').Value := ldapQuery.FieldByName('field1').AsString; q_temp.Parameters.ParamByName('field2_s').Value := ldapQuery.FieldByName('field2').AsString; q_temp.Parameters.ParamByName('field3_s').Value := ldapQuery.FieldByName('field3').AsString; q_temp.Parameters.ParamByName('field4_s').Value := outbuf; ldapQuery.Next; end; Еще пробывал назначать параметрам типы ftString вручную, но это ничего не поменяло. Сейчас попробывал сделать идентичный непараметрический SQL-запрос - все работает. UPD2: Пока, чтобы не передавать весь запрос целиком много раз, сделал хранимую процедуру и вызываю теперь ее. Но это все равно - не решение проблемы. Хотел посмотреть логи сервера, чтоб реально увидеть, что к нему приходит, да что-то не получилось. Например, утилитка Toad ругается на отсутствие таблицы dbms (права у меня рутовские). Еще пробовал вот эту вещицу, но она что-то не отображает запросы и корректно не работает. Может кто-нибудь знает какой-нибудь хороший SQL профайлер для Oracle, так чтобы можно было логи посмотреть не на сервере (туда у меня доступа нет), а на клиенте? Например, для MSSQL это SQL Server Profiler.
Ответы
Ответ 1
ParamCheck включается до назначения SQL запроса. Попробуйте.
Комментариев нет:
Отправить комментарий