查询 - 字符串文字太长 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。两个最重要的好处是:
绑定变量通过防止将文字值作为 SQL 命令执行来帮助防止 sql injection。这可以保护数据库免受包含恶意制作的 SQL 的值的影响。
对于多次执行的查询,绑定变量还通过鼓励数据库重用执行计划来提高性能。否则,数据库可能会在查询参数发生变化时选择生成新的执行计划,代价高昂。
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
。
我在 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。两个最重要的好处是:
绑定变量通过防止将文字值作为 SQL 命令执行来帮助防止 sql injection。这可以保护数据库免受包含恶意制作的 SQL 的值的影响。
对于多次执行的查询,绑定变量还通过鼓励数据库重用执行计划来提高性能。否则,数据库可能会在查询参数发生变化时选择生成新的执行计划,代价高昂。
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
。