Предыстория: понадобилось мне получать данные с кассового аппарата (КА) и передавать их в Оракл для дальнейшей обработки. Данные в КА хранятся в виде таблицы товаров с указанием цены, количества, к-ва продаж/возвратов и т.д. Получать данные можно только по одной строке с таблицы (такие методы у КА). И вот, что бы не передавать по одной строке с Делфи в Оракл решено было узнать как можно передать сразу все строки. Изначально план был такой: заполняем многомерный массив и передаем его в Оракл, но, скажу сразу, что ни многомерный, ни массив массивов передать не удалось и судя по некоторым форумам, которые я облазил за эти 2 дня, это сделать невозможно. У меня постоянно возникала ошибка несоответствия типов. Если все-таки такая возможность есть - комментируйте.
В итоге я передавал в функцию, в качестве параметров одномерные массивы. Количество этих массивов соответствовало количеству необходимых мне для обработки колонок в таблице КА.
Начну, пожалуй, с того, что я создал в 2 глобальных типа в PL/SQL:
create or replace type T_ExportDataFromMINI as object
(
ed_NumDoc NUMBER, -- Номер дока
ed_NumRow NUMBER, -- Номер строки в доке
ed_Price NUMBER(12,2), --Цена
ed_QtySale NUMBER,
ed_SumSale NUMBER(12,2),
ed_QtyRet NUMBER,
ed_SumRet NUMBER(12,2)
)
и второй:
create or replace type t_exportdatafrommini_tree is table of t_exportdatafrommini
Потом, в пакете, я прописал 7 локальных типов:
type t_mini_numdoc is table of number index by binary_integer;
type t_mini_numrow is table of number index by binary_integer;
type t_mini_price is table of number(12,2) index by binary_integer;
type t_mini_qtysale is table of number index by binary_integer;
type t_mini_sumsale is table of number(12,2) index by binary_integer;
type t_mini_qtyret is table of number index by binary_integer;
type t_mini_sumret is table of number(12,2) index by binary_integer;
и написал функцию, которая принимает параметры. Каждый параметр - это коллекция с типом, который я прописал выше. Сама функция:
Далее переходим к Делфи. На форму был добавлен элемент TOracleQuery, прописаны параметры сессии, добавлен SQL текст:
begin
:res := PKG_TEST.PARSEEXPORTDATAFROMMINI2(:p_numdoc, :p_numrow, :p_price, :p_qtysale, :p_sumsale, :p_qtyret, :p_sumret);
end;
И определены переменные через Variables Editor:
Самое главное, что бы для переменных, с помощью которых мы хотим передавать массивы была установлена галка PL/SQL Table.
Далее оглашаем необходимое количество массивов и инициализируем их:
.....
arNumdoc, arNumrow, arPrice, arQtysale, arSumsale, arQtyret, arSumret: variant;
.....
arNumdoc := VarArrayCreate([0, 3999], varVariant);
arNumRow := VarArrayCreate([0, 3999], varVariant);
arPrice := VarArrayCreate([0, 3999], varVariant);
arQtysale := VarArrayCreate([0, 3999], varVariant);
arSumsale := VarArrayCreate([0, 3999], varVariant);
arQtyret := VarArrayCreate([0, 3999], varVariant);
arSumret := VarArrayCreate([0, 3999], varVariant);
Я указал размер массива равным 4000 элементов, так как в КА нет метода, что бы получить количество элементов в памяти. После заполнения массивов данными (метод VarArrayPut) я меняю верхнюю границу массивов с помощью метода VarArrayRedim.
Далее заполняем SQL переменные:
with oqExportData do
begin
SetVariable('p_numdoc', arNumdoc);
SetVariable('p_numrow', arNumrow);
SetVariable('p_price', arPrice);
SetVariable('p_qtysale', arQtysale);
SetVariable('p_sumsale', arSumsale);
SetVariable('p_qtyret', arQtyret);
SetVariable('p_sumret', arSumret);
Execute;
end
И после всего этого обнуляем переменные:
arNumdoc := Unassigned;
arNumrow := Unassigned;
arPrice := Unassigned;
arQtysale := Unassigned;
arSumsale := Unassigned;
arQtyret := Unassigned;
arSumret := Unassigned;
В итоге я передавал в функцию, в качестве параметров одномерные массивы. Количество этих массивов соответствовало количеству необходимых мне для обработки колонок в таблице КА.
Начну, пожалуй, с того, что я создал в 2 глобальных типа в PL/SQL:
create or replace type T_ExportDataFromMINI as object
(
ed_NumDoc NUMBER, -- Номер дока
ed_NumRow NUMBER, -- Номер строки в доке
ed_Price NUMBER(12,2), --Цена
ed_QtySale NUMBER,
ed_SumSale NUMBER(12,2),
ed_QtyRet NUMBER,
ed_SumRet NUMBER(12,2)
)
и второй:
create or replace type t_exportdatafrommini_tree is table of t_exportdatafrommini
Потом, в пакете, я прописал 7 локальных типов:
type t_mini_numdoc is table of number index by binary_integer;
type t_mini_numrow is table of number index by binary_integer;
type t_mini_price is table of number(12,2) index by binary_integer;
type t_mini_qtysale is table of number index by binary_integer;
type t_mini_sumsale is table of number(12,2) index by binary_integer;
type t_mini_qtyret is table of number index by binary_integer;
type t_mini_sumret is table of number(12,2) index by binary_integer;
и написал функцию, которая принимает параметры. Каждый параметр - это коллекция с типом, который я прописал выше. Сама функция:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function PARSEEXPORTDATAFROMMINI2(p_numdoc t_mini_numdoc, p_numrow t_mini_numrow, p_price t_mini_price, | |
p_qtysale t_mini_qtysal, p_sumsale t_mini_sumsale, p_qtyret t_mini_qtyret, | |
p_sumret t_mini_sumret) return integer is | |
i integer; | |
v_array t_exportdatafrommini_tree := t_exportdatafrommini_tree(); | |
begin | |
--наполняем коллекцию | |
for i in 1..p_numdoc.COUNT loop | |
v_array.Extend(); | |
v_array(v_array.count) := t_exportdatafrommini(p_numdoc(i), p_numrow(i), p_price(i), | |
p_qtysale(i), p_sumsale(i), p_qtyret(i), p_sumret(i)); | |
end loop; | |
--проверяем, что же пришло с РКА | |
for rec in (select * from Table(cast(v_array as t_exportdatafrommini_tree))) loop | |
insert into tbl_roma | |
(tr_id, tr_doc_num, tr_log_info, tr_date) | |
values | |
(888, 888, rec.ed_NumDoc || '/' || rec.ed_NumRow || '/' || rec.ed_price || '/' || | |
rec.ed_qtysale || '/' || rec.ed_sumsale || '/' || rec.ed_qtyret || '/' || rec.ed_sumret, sysdate); | |
end loop; | |
commit; | |
return 1; | |
end; |
begin
:res := PKG_TEST.PARSEEXPORTDATAFROMMINI2(:p_numdoc, :p_numrow, :p_price, :p_qtysale, :p_sumsale, :p_qtyret, :p_sumret);
end;
И определены переменные через Variables Editor:
Самое главное, что бы для переменных, с помощью которых мы хотим передавать массивы была установлена галка PL/SQL Table.
Далее оглашаем необходимое количество массивов и инициализируем их:
.....
arNumdoc, arNumrow, arPrice, arQtysale, arSumsale, arQtyret, arSumret: variant;
.....
arNumdoc := VarArrayCreate([0, 3999], varVariant);
arNumRow := VarArrayCreate([0, 3999], varVariant);
arPrice := VarArrayCreate([0, 3999], varVariant);
arQtysale := VarArrayCreate([0, 3999], varVariant);
arSumsale := VarArrayCreate([0, 3999], varVariant);
arQtyret := VarArrayCreate([0, 3999], varVariant);
arSumret := VarArrayCreate([0, 3999], varVariant);
Я указал размер массива равным 4000 элементов, так как в КА нет метода, что бы получить количество элементов в памяти. После заполнения массивов данными (метод VarArrayPut) я меняю верхнюю границу массивов с помощью метода VarArrayRedim.
Далее заполняем SQL переменные:
with oqExportData do
begin
SetVariable('p_numdoc', arNumdoc);
SetVariable('p_numrow', arNumrow);
SetVariable('p_price', arPrice);
SetVariable('p_qtysale', arQtysale);
SetVariable('p_sumsale', arSumsale);
SetVariable('p_qtyret', arQtyret);
SetVariable('p_sumret', arSumret);
Execute;
end
И после всего этого обнуляем переменные:
arNumdoc := Unassigned;
arNumrow := Unassigned;
arPrice := Unassigned;
arQtysale := Unassigned;
arSumsale := Unassigned;
arQtyret := Unassigned;
arSumret := Unassigned;