ORA-01008: не все переменные связаны.Они связаны - PullRequest
27 голосов
/ 21 сентября 2011

Я столкнулся с проблемой Oracle, для которой до сих пор не смог найти причину. Приведенный ниже запрос работает в Oracle SQL Developer, но при запуске в .NET он выдает:

ORA-01008: не все переменные связаны

Я пробовал:

  • Изменение типа данных Oracle для lot_priority (Varchar2 или int32).
  • Изменение типа данных .NET для lot_priority (string или int).
  • Одно имя переменной связывания используется дважды в запросе. Это не проблема в моем другие запросы, которые используют одну и ту же связанную переменную в более чем одном местоположение, но просто чтобы убедиться, что я пытался сделать второй экземпляр его собственная переменная с другим именем и привязка к ней отдельно.
  • Несколько разных способов привязки переменных (см. Закомментированный код; и другие).
  • Перемещение вызова bindByName ().
  • Замена каждой связанной переменной литералом. У меня было две отдельные переменные, вызывающие проблему (: lot_pri и: lot_priprc). Были некоторые незначительные изменения, которые я не могу вспомнить между ними. Смена литералов заставила запрос работать, но они должны работать с привязкой.

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

SELECT rf.myrow floworder, rf.stage, rf.prss,
rf.pin instnum, rf.prid, r_history.rt, r_history.wt
FROM
(
    SELECT sub2.myrow, sub2.stage, sub2.prss, sub2.pin, sub2.prid
    FROM (
        SELECT sub.myrow, sub.stage, sub.prss, sub.pin,
            sub.prid, MAX(sub.target_rn) OVER (ORDER BY sub.myrow) target_row
            ,sub.hflag
        FROM (
            WITH floc AS 
            (
                SELECT flow.prss, flow.seq_num
                FROM rpf@mydblink flow
                WHERE flow.parent_p = :lapp
                AND flow.prss IN (
                    SELECT r_priprc.prss
                    FROM r_priprc@mydblink r_priprc
                    WHERE priprc = :lot_priprc
                )
                AND rownum = 1
            )
            SELECT row_number() OVER (ORDER BY pp.seq_num, rpf.seq_num) myrow,
                rpf.stage, rpf.prss, rpf.pin,
                rpf.itype, hflag,
            CASE WHEN rpf.itype = 'SpecialValue'
                THEN rpf.instruction
                ELSE rpf.parent_p
            END prid,
            CASE WHEN rpf.prss = floc.prss
                AND rpf.seq_num = floc.seq_num
                THEN row_number() OVER (ORDER BY pp.seq_num, rpf.seq_num)
            END target_rn
            FROM floc, rpf@mydblink rpf
            LEFT OUTER JOIN r_priprc@mydblink pp
                ON (pp.prss = rpf.prss)
            WHERE pp.priprc = :lot_priprc
            ORDER BY pp.seq_num, rpf.seq_num
        ) sub
    ) sub2
    WHERE sub2.myrow >= sub2.target_row
    AND sub2.hflag = 'true'
) rf
LEFT OUTER JOIN r_history@mydblink r_history
ON (r_history.lt = :lt
    AND r_history.pri = :lot_pri
    AND r_history.stage = rf.stage
    AND r_history.curp = rf.prid
)
ORDER BY myrow

public void runMyQuery(string lot_priprc, string lapp, string lt, int lot_pri) {
Dictionary<int, foo> bar = new Dictionary<int, foo>();
using(var con = new OracleConnection(connStr)) {
    con.Open();

    using(var cmd = new OracleCommand(sql.rtd_get_flow_for_lot, con)) { // Query stored in sql.resx
        try {
            cmd.BindByName = true;
            cmd.Prepare();
            cmd.Parameters.Add(new OracleParameter("lapp", OracleDbType.Varchar2)).Value = lapp;
            cmd.Parameters.Add(new OracleParameter("lot_priprc", OracleDbType.Varchar2)).Value = lot_priprc;
            cmd.Parameters.Add(new OracleParameter("lt", OracleDbType.Varchar2)).Value = lt;
            // Also tried OracleDbType.Varchar2 below, and tried passing lot_pri as an integer
            cmd.Parameters.Add(new OracleParameter("lot_pri", OracleDbType.Int32)).Value = lot_pri.ToString();
            /*********** Also tried the following, more explicit code rather than the 4 lines above: **
            OracleParameter param_lapp
                = cmd.Parameters.Add(new OracleParameter("lapp", OracleDbType.Varchar2));
            OracleParameter param_priprc
                = cmd.Parameters.Add(new OracleParameter("lot_priprc", OracleDbType.Varchar2));
            OracleParameter param_lt
                = cmd.Parameters.Add(new OracleParameter("lt", OracleDbType.Varchar2));
            OracleParameter param_lot_pri
                = cmd.Parameters.Add(new OracleParameter("lot_pri", OracleDbType.Varchar2));
            param_lapp.Value = lastProcedureStackProcedureId;
            param_priprc.Value = lotPrimaryProcedure;
            param_lt.Value = lotType;
            param_lot_pri.Value = lotPriority.ToString();
            //***************************************************************/
            var reader = cmd.ExecuteReader();
            while(reader.Read()) {
                // Get values from table (Never reached)
            }
        }
        catch(OracleException e) {
            //     ORA-01008: not all variables bound
        }
    }
}

Почему Oracle утверждает, что не все переменные связаны?

Ответы [ 8 ]

16 голосов
/ 25 сентября 2011

Я нашел, как выполнить запрос без ошибок, но я не решаюсь назвать его «решением», не понимая причину.

Это больше похоже на начало моего фактического запроса:

-- Comment
-- More comment
SELECT rf.flowrow, rf.stage, rf.process,
rf.instr instnum, rf.procedure_id, rtd_history.runtime, rtd_history.waittime
FROM
(
    -- Comment at beginning of subquery
    -- These two comment lines are the problem
    SELECT sub2.flowrow, sub2.stage, sub2.process, sub2.instr, sub2.pid
    FROM ( ...

Второй набор комментариев выше, в начале подзапроса, был проблемой.После удаления запрос выполняется.Другие комментарии в порядке.Это не вопрос какого-то мошеннического или отсутствующего перевода строки, приводящего к комментариям для следующей строки, поскольку следующая строка является SELECT.Отсутствие выбора привело бы к ошибке, отличной от «не все переменные связаны».

Я много раз спрашивал и нашел одного сотрудника, который наткнулся на это - комментарии, вызывающие сбои запроса - несколько раз.Кто-нибудь знает, как это может быть причиной?Насколько я понимаю, самое первое, что СУБД будет делать с комментариями, это посмотреть, содержат ли они подсказки, а если нет, удалить их во время анализа.Как обычный комментарий, не содержащий необычных символов (только буквы и точка), может вызвать ошибку?Bizarre.

8 голосов
/ 22 июня 2015

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

По умолчанию Oracle ODP.net связывает переменные по позиции и рассматривает каждую позицию как новую переменную.

Рассматривать каждую копию как отдельную переменную и задавать ее значение несколько раз - это обходной путь и боль, как упомянул furman87, и может привести к ошибкам, если вы попытаетесь переписать запрос и переместить все в другое.

Правильный способ - установить для свойства BindByName OracleCommand значение true, как показано ниже:

var cmd = new OracleCommand(cmdtxt, conn);
cmd.BindByName = true;

Вы также можете создать новый класс для инкапсуляции OracleCommand, установив для BindByName значение true при создании экземпляра, чтобы вам не приходилось каждый раз устанавливать значение. Это обсуждается в этом посте

7 голосов
/ 21 сентября 2011

У вас есть две ссылки на переменную привязки: lot_priprc - хотя должно требовать, чтобы вы устанавливали значение переменной только один раз и связывали его в обоих местах, у меня были проблемы, когда этого не былоработать и должен был рассматривать каждую копию как отдельную переменную.Боль, но это сработало.

1 голос
/ 06 декабря 2018

Решение в моей ситуации было аналогичным ответом Чарльзу Бернсу;и проблема была связана с комментариями кода SQL.

Я строил (или, скорее, обновлял) уже функционирующий отчет SSRS с источником данных Oracle.Я добавил еще несколько параметров в отчет, протестировал его в Visual Studio, он отлично работает, поэтому я развернул его на сервере отчетов, а затем при выполнении отчета на сервере я получил сообщение об ошибке:

"ORA-01008: не все переменные связаны"

Я пробовал несколько разных вещей (файл TNSNames.ora установлен на сервере, удалены однострочные комментарии, проверка соответствия запроса набора данных).К чему это привело, я должен был удалить блок комментария сразу после WHERE keyword.Сообщение об ошибке было устранено после перемещения блока комментария после WHERE CLAUSE conditions.У меня есть другие комментарии в коде также.Это было только одно после ключевого слова WHERE, вызывающего ошибку.

SQL с ошибкой: «ORA-01008: не все переменные связаны» ...

WHERE
/*
    OHH.SHIP_DATE BETWEEN TO_DATE('10/1/2018', 'MM/DD/YYYY') AND TO_DATE('10/31/2018', 'MM/DD/YYYY')
    AND OHH.STATUS_CODE<>'DL'
    AND OHH.BILL_COMP_CODE=100
    AND OHH.MASTER_ORDER_NBR IS NULL
*/

    OHH.SHIP_DATE BETWEEN :paramStartDate AND :paramEndDate
    AND OHH.STATUS_CODE<>'DL'
    AND OHH.BILL_COMP_CODE IN (:paramCompany)
    AND LOAD.DEPART_FROM_WHSE_CODE IN (:paramWarehouse) 
    AND OHH.MASTER_ORDER_NBR IS NULL
    AND LOAD.CLASS_CODE IN (:paramClassCode) 
    AND CUST.CUST_CODE || '-' || CUST.CUST_SHIPTO_CODE IN (:paramShipto) 

SQL успешно выполняется на сервере отчетов ...

WHERE
    OHH.SHIP_DATE BETWEEN :paramStartDate AND :paramEndDate
    AND OHH.STATUS_CODE<>'DL'
    AND OHH.BILL_COMP_CODE IN (:paramCompany)
    AND LOAD.DEPART_FROM_WHSE_CODE IN (:paramWarehouse) 
    AND OHH.MASTER_ORDER_NBR IS NULL
    AND LOAD.CLASS_CODE IN (:paramClassCode) 
    AND CUST.CUST_CODE || '-' || CUST.CUST_SHIPTO_CODE IN (:paramShipto)   
/*
    OHH.SHIP_DATE BETWEEN TO_DATE('10/1/2018', 'MM/DD/YYYY') AND TO_DATE('10/31/2018', 'MM/DD/YYYY')
    AND OHH.STATUS_CODE<>'DL'
    AND OHH.BILL_COMP_CODE=100
    AND OHH.MASTER_ORDER_NBR IS NULL
*/

Вот как выглядит экран отображения параметров набора данных.

enter image description here

1 голос
/ 01 октября 2018

Пришел сюда в поисках помощи, поскольку получил ту же ошибку, выполнив инструкцию, указанную ниже, во время прохождения курса Удеми:

INSERT INTO departments (department_id, department_name)
                  values( &dpet_id, '&dname');  

Раньше я мог выполнять операторы с переменными подстановки. Комментарий Чарльза Бернса о возможности достижения сервером некоторого порога при воссоздании переменных побудил меня выйти из системы и перезапустить SQL Developer. Оператор работал нормально после повторного входа в систему.

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

1 голос
/ 16 июня 2017

Это ошибка в Managed ODP.net - 'Ошибка 21113901: УПРАВЛЯЕМЫЙ ODP.NET RAISE ORA-1008 С ИСПОЛЬЗОВАНИЕМ ЕДИНОГО ЦИТАТЫ CONST + BIND VAR IN SELECT' исправлено в патче 23530387, заменено патчем 24591642

1 голос
/ 04 января 2016

В отношении проблемы с комментариями Чарльза: чтобы сделать ситуацию еще хуже, пропустите

:p1 = 'TRIALDEV'

через параметр команды, затем выполните

select T.table_name as NAME, COALESCE(C.comments, '===') as DESCRIPTION
from all_all_tables T
Inner Join all_tab_comments C on T.owner = C.owner and T.table_name = C.table_name
where Upper(T.owner)=:p1
order by T.table_name

558 line(s) affected. Processing time: 00:00:00.6535711

и при изменении буквенной строки из ===до ---

select T.table_name as NAME, COALESCE(C.comments, '---') as DESCRIPTION
[...from...same-as-above...]

ORA-01008: not all variables bound

Оба оператора прекрасно выполняются в SQL Developer.Сокращенный код:

            Using con = New OracleConnection(cs)
                con.Open()
                Using cmd = con.CreateCommand()
                    cmd.CommandText = cmdText
                    cmd.Parameters.Add(pn, OracleDbType.NVarchar2, 250).Value = p
                    Dim tbl = New DataTable
                    Dim da = New OracleDataAdapter(cmd)
                    da.Fill(tbl)
                    Return tbl
                End Using
            End Using

с использованием Oracle.ManagedDataAccess.dll версии 4.121.2.0 с настройками по умолчанию в VS2015 на платформе .Net 4.61.

Итак, где-то в цепочке вызовов естьэто может быть синтаксический анализатор, который слишком агрессивно ищет однострочные комментарии, начатые в commandText.Но даже если это так, сообщение об ошибке «не все переменные связаны», по крайней мере, вводит в заблуждение.

0 голосов
/ 08 июня 2016

У меня была похожая проблема в унаследованном приложении, но de "-" был строковым параметром.

Пример.

Dim cmd As New OracleCommand("INSERT INTO USER (name, address, photo) VALUES ('User1', '--', :photo)", oracleConnection)
Dim fs As IO.FileStream = New IO.FileStream("c:\img.jpg", IO.FileMode.Open)
Dim br As New IO.BinaryReader(fs)
cmd.Parameters.Add(New OracleParameter("photo", OracleDbType.Blob)).Value = br.ReadBytes(fs.Length)
cmd.ExecuteNonQuery() 'here throws ORA-01008

Изменение значения параметра адреса '-'на «00» или другое, работает.

...