Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.89/9: Рейтинг темы: голосов - 9, средняя оценка - 4.89
7 / 7 / 2
Регистрация: 23.09.2012
Сообщений: 427
1

Вызов хранимой процедуры в Oracle с параметрами QList<double>, QList<QDateTime>, QList<quint64>

31.08.2018, 09:45. Просмотров 1734. Ответов 19
Метки нет (Все метки)


Добрый день, уважаемые форумчане.
Необходимо в хранимую процедуру в Oracle передать параметры, являющиеся списками: QList<double>, QList<QDateTime>, QList<quint64>. В объект QSqlQuery добавляю параметры, используя bindValue. Но в этот метод из списков можно передать (судя по документации) только QVariantList или QStringList. Хорошо, с этим можно смириться. Все списки перевожу в QStringList. Затем в Оракле в ХП все эти строки перевожу в числа и даты. НО. Всё равно ошибка:
ORA-06553: PLS-306: ошибочно число или типы аргументов при обращении к 'ADD_VALUES'
Невозможно выполнить выражение


Хранимая процедура расположена в пакете в таком виде:
Oracle 11 SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
TYPE STRING_ARR IS TABLE OF NVARCHAR2(255) INDEX BY BINARY_INTEGER;
PROCEDURE ADD_VALUES(Id_arr IN STRING_ARR, dateTime_arr IN STRING_ARR, value_arr IN STRING_ARR) IS
  Id_ NUMBER;
  dateTime_ DATE;
  value_ NUMBER(10,3);
BEGIN
FOR inx IN 1 .. value_arr.COUNT LOOP
    BEGIN
      Id_ := TO_NUMBER(Id_arr(inx));
        dateTime_ := TO_DATE(dateTime_arr(inx), 'dd.mm.yyyy HH24:MI:SS');
      value_ := TO_NUMBER(value_arr(inx));
      INSERT INTO VALUES(ID, LIST_ID, DATE_TIME, VALUE)
        VALUES(VALUES_SEQ.NEXTVAL, Id_, dateTime_, value_);
    EXCEPTION 
        WHEN OTHERS THEN 
          CONTINUE;
    END;
  END LOOP; 
END;
Что не так? Что с этим делать? Уже просто отчаяние, но передавать массив ОЧЕНЬ надо. Неужели нет никакого выхода? Очень надеюсь на вашу помощь.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
31.08.2018, 09:45
Ответы с готовыми решениями:

QList<QList<QRgb>> ошибка с вложенными списками
Пишу класс, который будет производить операции над изображением (пока только обрезка пустых полей)....

список списков QList<QList<int>>
QList&lt;QList&lt;int&gt;&gt; results = FactorsComb(n); QList&lt;QList&lt;int&gt;&gt;::iterator Iter1; ...

ASSERT failure in QList<T>::operator[]: "index out of range", file C:\Qt\5.7\mingw53_32\include/QtCore/qlist.h, line 545
Добрый день. В программе где-то есть утечка памяти, но что-то никак не могу её найти и исправить....

QList<QList<Type> >
Можно ли делать так? #include &lt;QCoreApplication&gt; #include &lt;QDebug&gt; class test { public: ...

19
217 / 171 / 96
Регистрация: 15.04.2018
Сообщений: 680
01.09.2018, 12:25 2
Лучший ответ Сообщение было отмечено NoviiMir как решение

Решение

Сталкивался с такой проблемой, но при использовании postgresql, думаю, вам тоже подойдет.

Подставьте непосредственно в запрос строку с данными вида
Код
{ <переменная>, <переменная>,...,<переменная> }
Тогда не нашел способа вынести это в .cpp , так что всё осталось в .h файле (и вам того же советую)

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*!
 * \brief paramFromStdVector статический метод, который возвращает отформатированную строку, созданную из vector<T>
 * \param v указатель на вектор переменных
 * \return указатель на строку и метка об ошибке
 * \throw eUnknown - неизвестная ошибка
 */
template<typename T> 
static clReturnValue<std::shared_ptr<QString>, ErrMark> paramFromStdVector(const std::shared_ptr<std::vector<T>> v)
{
    clReturnValue<std::shared_ptr<QString>, ErrMark> res(eAllOK);
    res.value = std::make_shared<QString>("{"); //изначально задаем ему префикс для пустого вектора
    try
    {
        for(const T &value : *(v.get())) //проходимся по массиву
        {
            if(typeid(value) == typeid(int)) //если тип массива инт, то преобразовываем в строку след. образом:
                res.value->append(QString::number(value)  + ","); //дополняем строку значениями
            //TODO доделай свой тип, если нужно :)
        }
        if(res.value->size() > 1) //"волшебное" число взято из "{", если мы туда что-то добавили, то убираем запятую
            *(res.value.get()) = res.value->remove(res.value->size() - 1, 1); //убираем запятую
        *(res.value.get()) += "}"; //добавляем закрывающую скобку
    }
    catch(...)
    {
        qDebug() << "Неизвестная ошибка в методе TDataBase::paramFromStdVector";
        res.error = eUnknown;
        res.value = nullptr;
        return res;
    }
    return res;
}
1
7 / 7 / 2
Регистрация: 23.09.2012
Сообщений: 427
03.09.2018, 08:20  [ТС] 3
Огромное спасибо, что не прошли мимо!
Не могли бы вы показать, как в результате должен выглядеть запрос? Пока не совсем понимаю.

Добавлено через 1 час 5 минут
что-то типа этого?
SQL
1
CALL PACK_DATA.ADD_VALUES({1, 2, 3, 4, 5}, {<дата1>, <дата2>, <дата3>, <дата4>, <дата5>}, {0.1, 1.5, 3.3, 4.4, 5.5})
0
217 / 171 / 96
Регистрация: 15.04.2018
Сообщений: 680
03.09.2018, 12:38 4
NoviiMir, upd: да, в бинд к каждому массиву кидаешь {}, а не все вместе. У тебя должно быть три для каждого типа

Отдельно должен биндить {даблы}
ещё один бинд с {список временных отметок}
и ещё один с {интами}
1
7 / 7 / 2
Регистрация: 23.09.2012
Сообщений: 427
04.09.2018, 09:59  [ТС] 5
У меня наметился прогресс, который тут же привёл меня в тупик. Всё-таки добилась того, что отправляю в ХП массивы QVariantList, но теперь Оракл ругается:
ORA-01484: массивы могут быть привязаны только к PL/SQL командам
Невозможно выполнить пакетное выражение
В общем, всё тлен и безысходность...
0
217 / 171 / 96
Регистрация: 15.04.2018
Сообщений: 680
04.09.2018, 10:44 6
Выберите язык не sql, а <чего-то там>plsql. Тогда, скорее всего, будет приниматься.
0
7 / 7 / 2
Регистрация: 23.09.2012
Сообщений: 427
04.09.2018, 11:41  [ТС] 7
Это где такое можно выбрать?
0
217 / 171 / 96
Регистрация: 15.04.2018
Сообщений: 680
04.09.2018, 16:24 8
NoviiMir, прошу прощения за ответ, вводящий в заблуждение.

Цитата Сообщение от mvngr Посмотреть сообщение
Выберите язык не sql, а <чего-то там>plsql. Тогда, скорее всего, будет приниматься.

Попробуйте сначала сделать процедуру на сервере с целыми числами, потом с плавающей точкой, потом с датой. Скажитие, с каким типом данных именно ошибка. Или же ошибка в самом вызове и даже целые числа не могут корректно обработаться на стороне бд
0
7 / 7 / 2
Регистрация: 23.09.2012
Сообщений: 427
05.09.2018, 11:10  [ТС] 9
Поняла вас, сегодня попробую, отпишусь потом
0
7 / 7 / 2
Регистрация: 23.09.2012
Сообщений: 427
07.09.2018, 08:10  [ТС] 10
Попробовала передавать лишь один массив целых чисел, ошибка "массивы могут быть привязаны только к PL/SQL командам" сохранилась.

Добавлено через 11 минут
У меня тут ещё мысль возникла, может, можно как-то в эту сторону подумать. В общем, до этого вставляла данные в БД с помощью простого запроса Insert, в который передавала параметры в виде QVariantList. Но меня не устраивает это потому, что если возникала ошибка вставки (нарушение уникальности), то не происходила вставка вообще всех данных. Прочитала документацию вдоль и поперёк, замучила гугл, но не получила никакой инфы о том, можно ли как-то обойти эту особенность QSqlQuery :: execBatch().
0
217 / 171 / 96
Регистрация: 15.04.2018
Сообщений: 680
07.09.2018, 20:28 11
Мне кажется, что данная ошибка возникает не из-за Qt модуля, а из-за хранимки. Попробуйте почитать документацию по поводу Oracle PL/SQL, надеюсь, что это вам поможет. Писали же в одной среде, но у меня, хоть и с другой бд, но код при вызове хранимой процедуры работает на ура. Следовательно, если мой код не подходит вам, то стоит призадуматься, правильно ли работает сторона бд.

offtop: уже как за свой код надеюсь, что у вас получится решить эту проблему
0
7 / 7 / 2
Регистрация: 23.09.2012
Сообщений: 427
10.09.2018, 07:48  [ТС] 12
Большое спасибо за участие в проблеме, как-то легче даже становится
По теме: видимо, я до конца всё-таки не поняла ваш метод формирования массивов. Уточню ещё раз. В параметр биндится строка вида {1, 2, 3, 4, 5} (для случая интов)?
0
217 / 171 / 96
Регистрация: 15.04.2018
Сообщений: 680
10.09.2018, 13:35 13
именно
0
7 / 7 / 2
Регистрация: 23.09.2012
Сообщений: 427
10.09.2018, 13:39  [ТС] 14
Неа, не работает так. "Ошибочно число или типы аргументов при обращении к 'ADD_VALUES'
Невозможно выполнить выражение"
0
217 / 171 / 96
Регистрация: 15.04.2018
Сообщений: 680
10.09.2018, 13:40 15
Очень странно, сегодня попробую через дебаг перепроверить, как буду свободен
0
7 / 7 / 2
Регистрация: 23.09.2012
Сообщений: 427
10.09.2018, 13:43  [ТС] 16
Да тут наверняка дело в БД, ошибки то не qt-шные ведь, а оракловые.
0
217 / 171 / 96
Регистрация: 15.04.2018
Сообщений: 680
10.09.2018, 13:44 17
NoviiMir, по поводу оракла ко мне обращаться не стоит, обратитесь в соотвествующую тему
0
7 / 7 / 2
Регистрация: 23.09.2012
Сообщений: 427
11.09.2018, 07:05  [ТС] 18
Спасибо всё равно вам, что не прошли мимо.
1
7 / 7 / 2
Регистрация: 23.09.2012
Сообщений: 427
14.09.2018, 06:48  [ТС] 19
Решение проблемы было найдено. Опишу его для тех, кто вдруг столкнётся с такой же проблемой однажды. Повторюсь, необходимо передать в хранимую процедуру Oracle массивы.
Для этого, вызывать хранимую процедуру нужно не с помощью CALL <ХП с параметрами>, а следующим образом:
BEGIN <ХП с параметрами>; END;
И затем
C++ (Qt)
1
query.execBatch(QSqlQuery::ValuesAsColumns);
0
217 / 171 / 96
Регистрация: 15.04.2018
Сообщений: 680
14.09.2018, 10:37 20
Мои поздравления
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.09.2018, 10:37

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

'QList<QListWidgetItem*>' в 'QList<QPair<QString, QString> >*'
Перевести 'QList&lt;QListWidgetItem*&gt;' в 'QList&lt;QPair&lt;QString, QString&gt; &gt;*' ?????

Построить график по точкам из QList<double>
Допустим, имеется функция: double func (double &amp;x) { return sin(x); } Загоняю её значения...

QList
Может дуратский вопрос, но все же. Когда добавляешь объект в QList он туда копируется или там...

QList в QList в QList
Здравствуйте, как вы наверное уже поняли из названия, меня интересует как сделать трехмерную...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.