Mysql
 sql >> Datenbank >  >> RDS >> Mysql

ColdFusion Parametrisieren einer Abfrage

Ignorieren des richtigen Ansatzes Für einen Moment liegt der Grund dafür darin, dass Sie den falschen cfsqltype verwenden für die Parameter. Sie senden also tatsächlich andere Werte an die Datenbank (und führen folglich einen anderen Vergleich durch), als Sie denken. Daher findet die Abfrage keine übereinstimmenden Datensätze. Aus diesem Grund ist Ihr Diagramm leer.

Durch die Verwendung von cf_sql_timestamp Sie konvertieren den "Wert" in ein vollständiges Datums-/Zeitobjekt. Jedoch YEAR() gibt nur eine vierstellige Zahl zurück. Sie vergleichen also Äpfel und Birnen. Konzeptionell macht Ihre Abfrage tatsächlich Folgendes:

  WHERE  2014 = {ts '2009-02-13 23:31:30'}

Der Grund, warum es keinen Fehler auslöst, ist, dass Datums-/Uhrzeitwerte intern als Zahlen gespeichert werden. Sie vergleichen also tatsächlich eine kleine Zahl (zB Jahr) mit einer wirklich großen Zahl (zB Datum/Uhrzeit). Offensichtlich wird der Datumswert viel größer sein, so dass er fast nie mit der Jahreszahl übereinstimmen wird. Wieder konzeptionell Ihre Abfrage tut dies:

 WHERE 2014 = 1234567890

Da cfsqltype optional ist, denken viele Leute, dass es nicht sehr wichtig ist - aber das ist es.

  • Validierung: Zusätzlich zu seinen anderen Vorteilen validiert cfqueryparam den bereitgestellten „Wert“ basierend auf dem cfsqltype (Datum, Datum und Uhrzeit, Nummer usw.). Dies geschieht vorher das sql wird immer an die datenbank gesendet. Wenn die Eingabe also ungültig ist, verschwenden Sie keinen Datenbankaufruf. Wenn Sie den cfsqltype weglassen oder einfach die Standardzeichenfolge verwenden, verlieren Sie diese zusätzliche Validierung.

  • Genauigkeit Die Auswahl des richtigen cfsqltype stellt sicher, dass Sie den richtigen Wert an die Datenbank senden. Wie oben gezeigt, kann die Verwendung des falschen Typs dazu führen, dass CF den falschen Wert an die Datenbank sendet.

    Der cfsqltype stellt auch sicher, dass Werte in einem eindeutigen Format an die Datenbank übermittelt werden, die die Datenbank so interpretiert, wie Sie es erwarten. Technisch könnte man alles als String an die Datenbank schicken. Das zwingt die Datenbank jedoch, eine implizite Konvertierung (normalerweise unerwünscht).

    Bei der impliziten Konvertierung wird die Interpretation der Zeichenfolgen vollständig der Datenbank überlassen - und sie liefert möglicherweise nicht immer die erwartete Antwort. Das Senden von Datumsangaben als Zeichenfolgen und nicht als Datumsobjekte ist ein Paradebeispiel dafür. Wie interpretiert die aktuelle Datenbank eine Datumszeichenfolge wie "05.04.2014"? Als 5. April oder 4. Mai? Es hängt davon ab, ob. Ändern Sie die Datenbank oder die Datenbankeinstellungen und das Ergebnis kann völlig anders sein.

Die einzige Möglichkeit, konsistente Ergebnisse zu gewährleisten, besteht darin, den entsprechenden cfsqltype anzugeben. Er sollte mit dem Datentyp der Vergleichsspalte/-funktion oder zumindest einem äquivalenten Typ übereinstimmen. Im Fall von YEAR() , gibt es eine vierstellige Zahl zurück. Sie sollten also cf_sql_integer verwenden , da Adrian die Kommentare erwähnt hat . Dasselbe gilt für Ihren MONTH() Vergleich.

 WHERE Year(ColumnName) = <cfqueryparam value="2014" cfsqltye="CF_SQL_INTEGER">
 AND   Month(ColumnName) = <cfqueryparam value="11" cfsqltye="CF_SQL_INTEGER"> 

Nachdem das alles gesagt ist, Dans Vorschlag ist der bessere Weg, Datumsvergleiche durchzuführen. Dieses Paradigma ist indexfreundlicher und funktioniert unabhängig davon, ob Ihre Zielspalte (nur) ein Datum oder ein Datum und eine Uhrzeit enthält. Beachten Sie die Verwendung von cf_sql_date in seinem Beispiel.

  • cf_sql_timestamp - sendet Datum und Uhrzeit
  • cf_sql_date - sendet nur ein Datum. der Zeitwert wird abgeschnitten