2016-06-06 22 views
0

ich in Cold Fusion arbeite 11 * und ich erhalte den folgenden Fehler:Abfrage - String Literal Too Long ORA Fehler

ORA-01704: string literal too long. 

First off, erhielt ich diesen Fehler und korrigiert sie, nachdem über mehrere Standorte suchen nach Ändern mein Code aus:

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

An:

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

Das funktionierte perfekt beheben. Jetzt bekomme ich den gleichen Fehler, aber anstatt cfquery zu verwenden, baue ich die SQL-Abfrage in eine Zeichenfolge, bevor ich damit arbeite. Das ist also, wie der Code aussieht:

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

--- Ende Funktion

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

Die Ursache des Fehlers ist old_paragraph_text und new_paragraph_text. Ich habe mich gefragt, ob es möglich ist, eine Lösung vom Typ cfqueryparam in dieses Problem einzubinden, wie in dem vorherigen Problem/der Lösung, die ich einschloss. Ich habe versucht, es genau wie das erste zu integrieren, aber ich bekomme Kompilierungsfehler im Code. Irgendwelche Gedanken oder Tipps wären hilfreich, danke.

+0

* versucht, es gerade wie die erste, aber ich bekomme Kompilierungsfehler * Können Sie einen Ausschnitt des Codes, den Sie ausprobiert? Es sollte gut funktionieren, solange Sie [Query' und 'addParam()'] verwenden (http://help.adobe.com/de_DE/ColdFusion/9.0/CFMLRef/WSe9cbe5cf462523a0693d5dae123bcd28f6d-7ffb.html) ODER den Code konvertiert haben zu cfml/cfquery. – Leigh

+0

Dies ist, was ich versucht habe, sobald ich das Programm erneut ausführen kann, werde ich den Fehler, der aufgetreten ist, posten, könnte ich die Anweisung falsch formatieren. Ich werde versuchen, das wieder hinzuzufügen. @Leigh sql = sql & & "','"; – Chris

+1

Sie können cfqueryparam nicht als Teil einer solchen Variablen verwenden. Wenn Sie Abfrageparameter verwenden, müssen Sie auch Ihre einfachen Anführungszeichen nicht verdoppeln. –

Antwort

1

(Zu lang für Kommentare)

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

Ehrlich gesagt, es speichert nicht viel, da der Code im Wesentlichen eine if/else so oder so zu tun. Außer jetzt wird die Arbeit auf der db-Seite erledigt, anstatt auf dem App-Server, wo es hingehört.

mit vielen Legacy-Anwendungen gearbeitet hat, ich erkennen, dass sie oft übernehmen, was man euphemistisch „fragwürdig“ Code ;-) Allerdings nennen könnte, sollten Sie nie rohe Clientvariablen in SQL verwenden. Wenn Sie keinen guten Grund haben, etwas anderes zu tun, verwenden Sie immer cfqueryparam.

Intern verwendet cfqueryparambind variables. Zwei der wichtigsten Vorteile sind:

  1. Bind Variablen schützen helfen gegen sql injection, indem Sie die Literalwerte verhindert als SQL-Befehle ausgeführt werden. Dies schützt die Datenbank vor Werten, die in böser Absicht erstellte SQL enthalten.

  2. Bei mehrfach ausgeführten Abfragen erhöhen Bindungsvariablen die Leistung, indem sie die Datenbank zur erneuten Verwendung von Ausführungsplänen auffordern. Andernfalls kann die Datenbank einen neuen Ausführungsplan erstellen, wenn sich die Abfrageparameter ändern, was teuer ist.

CFQueryparam hat auch einige andere nette Features, wie zum Beispiel die "Null" Attribut. Es kann verwendet werden, um einen null Wert zu übermitteln, wenn bestimmte Bedingungen erfüllt sind.

Schließlich, in Bezug auf Best Practices, ist es auch eine gute Idee, alle Variablen vollständig zu erfassen. Wenn also beispielsweise die Variablen im FORM-Gültigkeitsbereich übergeben werden, sieht die letzte Abfrage möglicherweise so aus: etwas. (Ändern die cfsqltypes nach Bedarf.)

<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: Sofern eine Spalte einen anderen Standardwert zugewiesen hat, wird NULL automatisch eingefügt werden, wenn diese aus der Säule INSERT Liste weggelassen wird.

+0

Danke für das Detail und die Erklärung – Chris

1

Ich schlage vor, Ihre Logik neu zu ordnen, um field null Variablen zu bestimmen, die dann im Null-Attribut von cfqueryparam verwendet werden. Etwas wie dieses:

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

Danke für den Vorschlag, ich habe einen ähnlichen Weg genommen, aber ich wollte den Code so begrenzen, anstatt den Null-Wert außerhalb der Abfrage zu bestimmen, fügte ich die Case-Anweisungen hinzu. – Chris

0

Danke für die Vorschläge. Anstatt die existierende Funktion, die in verschiedenen Bereichen der Anwendung verwendet wird, zu modifizieren, fügte ich eine neue insert-Anweisung an der Stelle hinzu, an der die Funktion aufgerufen wurde, um mit den Clobs umzugehen. Um mit den Nullfeldern umzugehen habe ich eine case Anweisung verwendet.

<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> 
+0

Auch ich habe versucht, die vorhandene Funktion zu ändern, aber ich lief weiter in fehlende Kommas Oracle Fehler. (Ich habe die gleiche Aussage wie in der Antwort verwendet, aber ich denke, dass die Variablen möglicherweise auf eine andere Art und Weise referenziert werden mussten.) – Chris