Qt PL / SQL - Оператор присваивания - Слишком маленький буфер строки символов - PullRequest
1 голос
/ 28 января 2020

Я какое-то время ковырял свой мозг, пытаясь понять это.

Проблема, с которой я столкнулся, заключается в том, что функция, которую я использую в Oracle, возвращает BLOB. Это список элементов, которые объединяются с использованием ||.

Из проведенного мною исследования

  1. В документах QSQLQuery говорится "Хранимые процедуры, использующие оператор return для возврата значений или возврат нескольких результатов". наборы, поддерживаются не полностью. Подробности c см. SQL Драйверы базы данных. " - что наводит меня на мысль, что мне может понадобиться переключиться на другую кодовую базу, если Qt пока не может справиться с этим.
  2. В документации для драйвера QOCI упоминается, что этот "двоичные большие объекты (BLOB) можно читать и записывать, но помните, что для этого процесса может потребоваться много памяти. Вам следует использовать запрос перенаправления только для выбора полей больших объектов (см. QSqlQuery :: setForwardOnly ()). "

Я установил
query.setForwardOnly(true);
До того, как подготовил или выполнил оператор.

Тем не менее, я все еще получаю эту ошибку
QSqlError("6502", "Unable to execute statement", "ORA-06502: PL/SQL: numeric or value error: character string buffer too small\nORA-06512: at line 55\n")

Мне пришлось немного почистить код, я надеюсь, что это все еще полезно, чтобы дать контекст тому, что я пытаюсь contribli sh

              temp_clob       clob;
              name varchar2(183) := ?;
              start varchar2(16)  := ?;
              end   varchar2(16)  := ?;
              count  integer       := ?;
              return_val    named_redacted_table_object; -- Sorry had to remove this, it's a table with more Date, Varchar, etc
           begin
              dbms_lob.createtemporary(temp_clob, true);
              return_val := package_name.function_name (
                 set_name     => name,  
                 start_time   => to_date(start, 'yyyy-mm-dd hh24:mi'),                 
                 end_time     => to_date(end, 'yyyy-mm-dd hh24:mi'),
                 max_count    => count); 

        -- In here was a loop that would break apart the removed table object and make it into strings along the following lines
        -- '' || return_val(i).name || return_val(i).value || etc
        -- and would store these into the CLOB / temp_clob
              ? := temp_clob;
           end; 

Я не мог заставить что-то столь простое работать

begin
  ? := 'test123';
end; 

С предположением, что я мог бы по крайней мере прочитать эту строку в Qt.

Вот мой код для Qt

QString name = "test";
QSqlQuery query(db);
query.setForwardOnly(true);
query.prepare(sql);
QString test_sql_text = ui->comboBox_test_text->currentText();
qDebug() << name;
query.bindValue(0, name);
query.bindValue(1, "2003-03-14 00:00");
query.bindValue(2, "2005-03-14 23:00");
query.bindValue(3, 2);
query.bindValue(4, QString(""), QSql::Out);
bool query_executed_ok = query.exec();
qDebug() << "did it execute?" << query_executed_ok;

// qDebug() << query.executedQuery();
qDebug() << query.boundValues();
qDebug() << query.lastError();
QSqlRecord rec = query.record();
qDebug() << rec;
int record_count = rec.count();
qDebug() << "Records: " << record_count;
while (query.next()) {
    for(int i=0;i<record_count;i++) {
       qDebug() << query.isValid() << " - " << rec.fieldName(i) << " " << query.value(i).toString();
    }
}

Ответы [ 3 ]

1 голос
/ 28 января 2020
begin
  ? := 'test123';
end; 

Переменные связывания используются для присвоения значений переменным. Вы определяете свою переменную в своем коде pl / sql и присваиваете ей значение во время выполнения, используя переменную связывания. В этом случае код pl / sql будет скомпилирован правильно. В вашем коде переменная связывания используется для замены переменной pl / sql, а не значения, которое завершится ошибкой. Ваш блок pl / sql не может быть скомпилирован, потому что он не может разрешить «?». Допустимое использование переменных связывания будет

BEGIN
  l_xyz := ?;
END;

, где вы присваиваете значение test123 во время выполнения.

1 голос
/ 28 января 2020

Потребовалось немного возиться, и я понимаю, что дал довольно зашифрованный c код. Так что спасибо страховщику и Коену за то, что выстрелили в мой беспорядок.

Что я смог определить и получить работу для всех, кто сталкивался с этим:

Позвольте мне начать с того, что я не уверен, является ли это ошибкой, или я делаю что-то, что не было задумано разработчиками QSqlQuery (класс для обработки вызовов SQL).

Вызов будет работать в SQL разработчику, и я увижу предполагаемый CLOB со всеми символами. Мне не удалось заставить работать DBMS_Output, однако я видел этот пост, в котором говорилось, что нужно зарезервировать место в строке перед привязкой его к запросу.

Это решает мою проблему и показывает результат в окне отладки. Однако это представляет новую проблему. Что если строка станет больше, чем мое жестко закодированное резервное значение?

Вот обновленный код для этого

query.prepare(sql);
        QString name= ui->comboBox_name->currentText();
        qDebug() << project;
        query.bindValue(":name", project);
        query.bindValue(":start_date", "2005-03-14 00:00");
        query.bindValue(":end_date", "2006-03-14 23:00");
        query.bindValue(":max_count", 3);
        QString testStr ="*****";
        //testStr.truncate(0); //Maybe this works too?
        testStr.reserve( 1000000 ); // This did it for sure
        qDebug() << testStr.capacity();
        query.bindValue(":result_clob", testStr, QSql::Out);
        bool query_executed_ok = query.exec();
        qDebug() << "did it execute?" << query_executed_ok;
        if (query_executed_ok) {
            testStr = query.boundValue(":result_clob").toString();
            qDebug() << testStr;
        } else {
            qDebug() << "string is empty";
        }

У меня появилась идея сделать это из ЭТОГО поста.

1 голос
/ 28 января 2020

Похоже, что опубликованная ошибка находится внутри кода Oracle; ORA .... Вы разделились настолько, что трудно увидеть, что на самом деле происходит, особенно там, где очевидно произошла ошибка. Но, возможно, с использованием Oracle предоставленного кода, который специально разработан для обработки CLOB. Вместо

    '' || return_val(i).name ... 
    Try
    dbms_lob.append(temp_clob, to_clob(return_val(i).name))
...