Запрос - строковый литерал слишком длинный ORA Ошибка

Я работаю в Cold Fusion 11* и получаю следующую ошибку:

ORA-01704: string literal too long.

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

<cfquery datasource="#dsn#">
    update paragraphs
    set paragraph_text = #input#
    where  paragraph_id=#rs_d.paragraph_id#
</cfquery>

Для того, чтобы:

<cfquery datasource="#dsn#">
    update paragraphs
    set paragraph_text = <cfqueryparam cfsqltype="CF_SQL_CLOB" value=#input#> 
    where paragraph_id=#rs_d.paragraph_id#
</cfquery>

Это исправление сработало отлично. Теперь я получаю ту же ошибку, но вместо использования cfquery я строю SQL-запрос в строку перед началом работы с ним. Вот как выглядит код:

sql = "insert into log (LOG_ENTRY_ID, program_id, paragraph_id, action, userid,";
sql = sql & " paragraph_text_old, paragraph_text_new, comment_id, current_program_status, new_program_status)";
sql = sql & " values (1 ," & program_id & ",";
if (paragraph_id neq ""){
    sql = sql & paragraph_id & ",";
}
else{
    sql = sql & " null,";
}
sql = sql & "'" & action & "',";
sql = sql & userid & ", '";
sql = sql & DoubleSingleQuotes(paragraph_text_old) & "','";
sql = sql & DoubleSingleQuotes(paragraph_text_new) & "',";
if (comment_id neq ""){
    sql = sql & comment_id & ",";
}
else{
    sql = sql & " null,";
}
if (current_program_status neq ""){
    sql = sql & "'" & current_program_status & "',";
}
else{
    sql = sql & " null,";
}
if (new_program_status neq ""){
    sql = sql & "'" & new_program_status & "'";
}
else{
    sql = sql & " null";
}       
sql = sql & ")";
   cfstmt(sql);

--- Конечная функция

<cffunction name="cfstmt">
    <cfargument name="sql">
    <cfquery name="rs" datasource="#dsn#">
        #PreserveSingleQuotes(sql)#
    </cfquery>
</cffunction>

Причиной ошибки являются old_paragraph_text и new_paragraph_text. Мне было интересно, возможно ли включить решение типа cfqueryparam для этой проблемы, как в предыдущей проблеме / решении, которое я включил. Я попытался включить его прямо как первый, но я получаю ошибки компиляции в коде. Любые мысли или советы будут полезны, спасибо.

3 ответа

Решение

(Слишком долго для комментариев)

хотел ограничить код, поэтому вместо определения нулевого значения вне запроса я добавил операторы case

Честно говоря, это не сильно экономит, так как код в основном выполняет if/else в любом случае. За исключением того, что сейчас работа выполняется на стороне базы данных, а не на сервере приложений, к которому она относится.

Поработав со многими устаревшими приложениями, я понимаю, что они часто включают в себя то, что вы можете эвфемистически назвать "сомнительным" кодом;-) Однако вы никогда не должны использовать необработанные переменные клиента в SQL. Если у вас нет очень веских причин поступать иначе, всегда используйте cfqueryparam,

Внутренне cfqueryparam использует переменные связывания. Два из наиболее важных преимуществ:

  1. Переменные связывания помогают защитить от внедрения SQL, предотвращая выполнение литеральных значений в виде команд SQL. Это защищает базу данных от значений, содержащих вредоносный SQL.

  2. Для запросов, выполняемых несколько раз, переменные связывания также повышают производительность, побуждая базу данных повторно использовать планы выполнения. В противном случае база данных может выбрать создание нового плана выполнения при изменении параметров запроса, что является дорогостоящим.

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

Наконец, с точки зрения передового опыта, это также хорошая идея, чтобы полностью охватить все переменные. Так, например, если переменные передаются в области FORM, окончательный запрос может выглядеть примерно так. (Измените cfsqltypes по мере необходимости.)

<cfquery datasource="#variables.dsn#">
  INSERT INTO into log (
    program_id
    , paragraph_id
    , userid
    , action
    , paragraph_text_old
    , paragraph_text_new
)
VALUES 
(
    <cfqueryparam value="#FORM.program_id#" cfsqltype="CF_SQL_INTEGER">
    , <cfqueryparam value="#FORM.paragraph_id#" cfsqltype="CF_SQL_INTEGER" null="#NOT IsNumeric(FORM.paragraph_id)#">
    , <cfqueryparam value="#Session.userid#" cfsqltype="CF_SQL_INTEGER">
    , 'Paragraph Updated' 
    , <cfqueryparam cfsqltype="CF_SQL_CLOB" value="#rs_d.paragraph_text#">
    , <cfqueryparam cfsqltype="CF_SQL_CLOB" value="#FORM.input#"> 
)
</cfquery>  

NB. Если столбцу не назначено другое значение по умолчанию, NULL будет вставлен автоматически, если этот столбец пропущен из INSERT список.

Я предлагаю перестроить вашу логику, чтобы определить field null переменные, которые затем используются в нулевом атрибуте cfqueryparam. Что-то вроде этого:

<cfscript>
fieldOneNull = conditionForNull ? true : false;
fieldTwoNull = conditionForNull ? true : false;
etc
</cfscript>

<cfquery>
insert into table
(field1, field2, etc)
values
(
<cfqueryparam cfsqltype="cf_sql_whatever" value="something" null="#fieldOneNull#">
, <cfqueryparam cfsqltype="cf_sql_whatever" value="something" null="#fieldTwoNull#">
, etc
)

Спасибо за предложения. Вместо того, чтобы модифицировать существующую функцию, которая используется в различных областях приложения, я добавил новый оператор вставки в позицию, где функция вызывается для обработки сгустков. Чтобы иметь дело с пустыми полями, я использовал case заявление.

<cfquery datasource="#dsn#">
    insert into log (
        LOG_ENTRY_ID, program_id, paragraph_id, userid, action, paragraph_text_old
       , paragraph_text_new, comment_id, current_program_status, new_program_status
    )
    values (
        null ,#program_id#,(case when #paragraph_id# = '' then null else #paragraph_id# end)
       , #Session.userid# , 'Paragraph Updated'
       , <cfqueryparam cfsqltype="CF_SQL_CLOB" value=#rs_d.paragraph_text#>
       , <cfqueryparam cfsqltype="CF_SQL_CLOB" value=#input#> 
       , null, null , null
    )
</cfquery>  
Другие вопросы по тегам