查询 - 字符串文字太长 ORA 错误

Query - String Literal Too Long ORA Error

我在 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。我想知道是否可以像我之前包含的 problem/solution 那样包含一个 cfqueryparam 类型的解决方案来解决这个问题。我尝试像第一个一样直接包含它,但我在代码中遇到编译错误。任何想法或提示都会有所帮助,谢谢。

我建议重新安排您的逻辑以确定 field null 变量,然后在 cfqueryparam 的 null 属性中使用这些变量。像这样:

<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
)

感谢您的建议。我没有修改应用程序不同区域中使用的现有函数,而是在调用该函数以处理 clob 的位置添加了一个新的插入语句。为了处理空字段,我使用了 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>  

(评论太长)

wanted to limit the code so instead of determining the null value outside the query, I added the case statements

老实说,它并没有节省多少,因为代码本质上是在做 if/else 两种方式。除了现在工作是在数据库端完成的,而不是它所属的应用服务器。

我使用过许多遗留应用程序,我意识到它们通常包含您可能委婉地称为 "questionable" 代码的内容;-) 但是,您应该 永远不要在 SQL。除非您有充分的理由不这样做,否则请始终使用 cfqueryparam

在内部,cfqueryparam 使用 bind variables。两个最重要的好处是:

  1. 绑定变量通过防止将文字值作为 SQL 命令执行来帮助防止 sql injection。这可以保护数据库免受包含恶意制作的 SQL 的值的影响。

  2. 对于多次执行的查询,绑定变量还通过鼓励数据库重用执行计划来提高性能。否则,数据库可能会在查询参数发生变化时选择生成新的执行计划,代价高昂。

CFQueryparam 还有一些其他不错的功能,例如 "null" 属性。它可用于在满足特定条件时提交 null 值。

最后,就最佳实践而言,完全确定所有变量的范围也是一个好主意。因此,例如,如果变量在 FORM 范围内提交,最终查询可能看起来像这样 something。 (根据需要修改 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>  

注意: 除非为列分配了不同的默认值,否则当 INSERT 列表中省略该列时,将自动插入 NULL