ЕСть вот такое определение ХП в БД Oracle:
in_name IN VARCHAR2,
in_desc IN VARCHAR2 DEFAULT NULL,
in_adress_id IN INTEGER DEFAULT NULL,
in_developer_id IN INTEGER,
in_owner_id IN INTEGER,
in_management_id IN INTEGER,
in_site_status_id IN INTEGER,
in_comments IN VARCHAR2 DEFAULT NULL,
in_id IN INTEGER DEFAULT NULL) RETURN INTEGER;
каким образом ее вызвать из скрипта TSCRM чтобы получить возвращаемое значение?
Нравится
SSV, можно создать SelectQuery на таблицу с одной записью (tbl_DatabaseInfo) где создать CustomSQL колонку и там вызвать Вашу функцию. В итоге должно получиться что-то типа такого:
SELECT f_add(:pin_site_type_id, ...) "Column1" FROM "tbl_DatabaseInfo"
Получить значение можно так:
... var sq = Services.GetNewItemByUSI("f_addQuery"); sq.Parameters.ItemsByName("in_site_type_id").Value = 1; ... var ds = sq.Open(); Log.Write(1, ds.ValAsInt("Column1")); ...
Писал по памяти, без проверки, так что если будут ошибки компиляции, думаю подправите :)
Спасибо, Александр, но после Вашего ответа я понял, что некорректно задал свой вопрос. Дело в том, что CRM работает с MS SQL сервером, а процедура должны вызываться из БД Oracle. Подозреваю, что в данном случае SelectQuery не сможет подключиться к серверу Oracle. Это нужно для синхронизации неких данных в двух БД.
Можно попробовать через ADOQuery или создать linked-server на Oracle и попробовать вызвать функцию.
Точно так же как я описал в первом посте. Только можно делать выборку не с tbl_DatabaseInfo, а из DUAL.
Вы не указали owner для функции и не заменили кавычки на квадратные скобки. Попробуйте так:
SELECT dbo.TestOut(1,0) AS [Column1] FROM [tbl_DatabaseInfo]
Только как это Вам поможет? У Вас же функция на Oracle :)
"SSV" написал:создал тестовую процедуру на MS SQL
Процедуру или функцию?
var SiteBalDataset = Services.GetNewItemByUSI('ADOC_Site'); SiteBalDataset.SQLText = 'select f_add("'+pNameSite+'"'+','+'"'+pAddressSite+'") as IDBalSys from DUAL'; SiteBalDataset.Open; var IDBalSys = SiteBalDataset.ValAsFloat('IDBalSys');
На последней строке выдает ошибку - "Объект не поддерживает это свойство или метод."
В чем может быть дело?
"SSV" написал:SiteBalDataset.Open;
А так?
var ds = SiteBalDataset.Open(); var IDBalSys = ds.ValAsFloat('IDBalSys');
"SSV" написал:SiteBalDataset.SQLText = 'select f_add("'+pNameSite+'"'+','+'"'+pAddressSite+'") as IDBalSys
Никогда так не делайте, с этим много проблем. Используйте параметры.
var SiteBalDataset = Services.GetNewItemByUSI('ADOC_Site'); SiteBalDataset.Parameters.ItemsByName('pNameSite').ValAsStr = pNameSite; SiteBalDataset.Parameters.ItemsByName('pAddressSite').ValAsStr = pAddressSite; var ds = SiteBalDataset.Open(); var IDBalSys = ds.ValAsFloat('IDBalSys'); //SiteBalDataset.ValAsFloat('IDBalSys');
Та же самая ошибка на строке - var ds = SiteBalDataset.Open();
SSV, а что такое ADOC_Site? ADODataSet? У него есть ADOCommand?
Если это ADODataSet, то тогда Ваш код подходит больше:
var SiteBalDataset = Services.GetNewItemByUSI('ADOC_Site'); SiteBalDataset.Parameters.ItemsByName('pNameSite').ValAsStr = pNameSite; SiteBalDataset.Parameters.ItemsByName('pAddressSite').ValAsStr = pAddressSite; SiteBalDataset.Open(); // Вызвать метод var IDBalSys = SiteBalDataset.ValAsFloat('IDBalSys');
SSV, а какой у Вас запрос сейчас? И какой провайдер Вы используете при подключении к Oracle?
"SSV" написал:
SELECT sites_pkg.f_add(:pNameSite,:pAddressSite) AS IDBalSys FROM DUAL
А Вы выполняли его в какой либо утилите по работе с Oracle? Он работает? Возвращает данные для Ваших параметров? Попробуйте еще указать имя колонки IDBalSys в кавычках - "IDBalSys"
"SSV" написал:Что интересно - средствами Oracle выполнить этот запрос не получается - ругается на команду Insert в теле функции, а из скрипта CRM выполняется, но пишет, что "Object 'DataField IDBalSys' is not assigned"...
Все правильно, набор данных ничего не вернул, поэтому и ругается...
Есть :) Исправить ошибку в функции sites_pkg.f_add.
Тут даже не в том проблема что ничего не вернул запрос, а в том, запрос некорректен.
А в дебаггере проверяли, DataFields у SiteBalDataset содержит элементы?
Попробуйте еще так:
... var IDBalSys = SiteBalDataset.DataFields.Items[0].Value; ...
Ну так у DataSet нет DataField. Вы их в дизайнере добавили?
"Осауленко Александр" написал:
Ну так у DataSet нет DataField. Вы их в дизайнере добавили?
:sad:
это что-то меня совсем переклинило. Теперь добавил, всё проходит без видимых ошибок, но такое впечатление, что ничего не происходит - функция запись не добавляет и возвращает 0...
Наверное у Вас функция все-таки не корректна... Или параметры не те приходят. Тут только отлаживать функцию необходимо на стороне Oracle.
FUNCTION f_add(in_site_type_id IN INTEGER DEFAULT NULL, in_name IN VARCHAR2, in_desc IN VARCHAR2 DEFAULT NULL, in_adress_id IN INTEGER DEFAULT NULL, in_developer_id IN INTEGER DEFAULT NULL, in_owner_id IN INTEGER DEFAULT NULL, in_management_id IN INTEGER DEFAULT NULL, in_site_status_id IN INTEGER DEFAULT NULL, in_comments IN VARCHAR2 DEFAULT NULL, in_id IN INTEGER DEFAULT NULL) RETURN INTEGER AS PRAGMA AUTONOMOUS_TRANSACTION; v_id INTEGER; v_error VARCHAR2(4000); BEGIN IF in_id IS NULL THEN SELECT MAX(id)+1 INTO v_id FROM sites; ELSE v_id:=in_id; END IF; INSERT INTO sites VALUES (v_id, in_site_type_id, in_name, in_desc, in_adress_id, in_developer_id, in_owner_id, in_management_id, in_site_status_id, in_comments); COMMIT; RETURN v_id; EXCEPTION WHEN OTHERS THEN v_error:=SQLERRM(SQLCODE); INSERT INTO test_s VALUES (SYSDATE,'ERROR:'||v_error); COMMIT; END;
"SSV" написал:SELECT MAX(id)+1
INTO v_id
FROM sites;
Это конечно Вы зря. А почему не последовательности?
Дело в том, что я не работаю с Oracle, функции пишет девочка. Меня тоже удивил этот кусочек кода. Я попросил упростить функцию - сократить количество параметров до двух самых необходимых - in_name и in_desc. В случае ошибки сейчас что-то пишется в таблицу test_s, что именно еще нужно выяснить у девочки.
FUNCTION add2(in_name IN VARCHAR2, in_desc IN VARCHAR2 DEFAULT NULL) RETURN INTEGER AS PRAGMA AUTONOMOUS_TRANSACTION; v_id INTEGER; v_error VARCHAR2(4000); BEGIN SELECT MAX(id)+1 INTO v_id FROM sites; INSERT INTO sites (id,name,description) VALUES (v_id, in_name, in_desc); COMMIT; RETURN v_id; EXCEPTION WHEN OTHERS THEN v_error:=SQLERRM(SQLCODE); INSERT INTO test_s VALUES (SYSDATE,'ERROR:'||v_error); COMMIT; END;
Теперь Statement Tracer for Oracle выдает такую ошибку:
Class: Error message
Time stamp: 16/08/2010 07:45:12
SQL statement: ORA-01722: неверное число
Только сейчас заметил, что изменилось имя функции...
var SiteBalDataset = Services.GetNewItemByUSI('ADOC_Site'); SiteBalDataset.Parameters.ItemsByName('pin_name').ValAsStr = pNameSite; SiteBalDataset.Parameters.ItemsByName('pin_desc').ValAsStr = pAddressSite; SiteBalDataset.Open(); var IDBalSys = SiteBalDataset.ValAsFloat('IDBalSys');
на строке SiteBalDataset.Open(); выдает ошибку:
"TSADOEngineLibrary.ADODataset: Не удается вновь задать положение в наборе строк"
Может в ADODataSet нужно что-то поменять в настройках курсора?
SSV,
1. Вам необходимо обязательно уйти от SELECT MAX - это не подход к клиент-серверным базам
2. Вернуть какое-то число в случае ошибки
Какая структура таблиц sites и test_s?
"SSV" написал:"TSADOEngineLibrary.ADODataset: Не удается вновь задать положение в наборе строк"
Ну так у Вас же функция еще не скомпилированная, как Вы можете делать выборку из нее?
У меня нет полного доступа к БД Oracle, но предполагаю, что структура sites идентична параметрам функции f_add. Каких либо реляционных связей с другими таблицами нет. Таблица test_s, опять же судя по коду в функции состоит из двух полей - дата и строка, она создавалась только для проверки данной функции.
Не совсем понял про не скомпилированную функцию. Почему, в таком случае, такая ошибка не всплывала с функцией f_add?
У Вас есть какая-то утилита для работы с Oracle? TOAD, PL/SQL Developer? Можете там выполнить запрос, который Вы запускаете из Terrasoft?
Скажите разработчику функции:
1. MAX это не подход и это надо обязательно переписать
2. Вернуть значение в случае ошибки. Сейчас Функция "глушит" все ошибки и ничего не возвращает.
Запрос, который выполняет CRM, работает в Oracle. Более того - при выполнении метода SiteBalDataset.Open(); данные добавляются в таблицу, но всё равно в CRM вываливается ошибка - "TSADOEngineLibrary.ADODataset: Не удается вновь задать положение в наборе строк" и соответственно строка - var IDBalSys = SiteBalDataset.ValAsFloat('IDBalSys'); не выполняется и никакого возвращаемого значения я не получаю.
А Вы как-то меняли ADODaatSet - настройки курсора и т.п.?
Если у Вас серверный курсор, попробуйте клиентский.
Если параметры не типизировать, то значение вроде бы присваивается -
SiteBalDataset.Parameters.ItemsByName('pin_site_type_id').Value = null;
но при этом, при попытке выполнить метод Open(), вылезает ошибка - "TSADOEngineLibrary.ADODataset: Неправильно определен объект Parameter. Предоставлены несовместимые или неполные сведения".
"SSV" написал:как присвоить полю SiteBalDataset.Parameters.ItemsByName('pin_site_type_id').ValAsInt значение NULL?
Посмотрите это свойство Value