Frage

Ich versuche, einen guten CF Web-Entwickler zu sein und <cfqueryparam> um alle FORM oder URL-Elemente zu verwenden, die es zu meinen SQL-Abfragen machen.

In diesem Fall Ich versuche, einen Benutzer zu ermöglichen, dynamisch die ORDER BY-Klausel zu steuern.

<cfquery datasource="MyDSN" name="qIncidents">
  SELECT IncidentID, AnimalID, IntakeDate, DxDate, OutcomeDate
  FROM Incidents
  WHERE ShelterID = <cfqueryparam cfsqltype="cf_sql_integer" value="#Arguments.ShelterID#">
  ORDER BY <cfqueryparam cfsqltype="cf_sql_varchar" value="#SortBy#">
</cfquery>

Wenn ich das tue, bekomme ich folgende Fehlermeldung:

  

Das SELECT-Element durch die ORDER BY-Nummer identifiziert 1 enthält eine Variable als Teil des Ausdrucks eine Spaltenposition identifiziert wird. Variablen sind nur zulässig, wenn durch einen Ausdruck der Bestellung eines Spaltennamen verweist.

Alle Vorschläge, wie dies sicher zu tun?

War es hilfreich?

Lösung

Leider kann man nicht cfqueryparam verwenden, um direkt in der ORDER BY-Klausel.

Wenn Sie den Auftrag durch dynamisch verwenden möchten, aber immer noch so sicher machen, können Sie eine cfswitch oder eine ähnliche Struktur einrichten, um Ihre SortBy Variable auf einer Bedingung abhängig zu ändern (zum Beispiel eine URL-Variable). Wie immer passieren keine Werte direkt vom Benutzer, nur Blick auf die Eingabe des Benutzers und wählen Sie aus einer vorgegebenen Liste von möglichen Werten auf der Grundlage dieser. Verwenden Sie dann nur die Standardsyntax:

ORDER BY #SortBy#

Andere Tipps

Ich werde erweitern nur auf Aaron Antwort. Eines der Dinge, die ich tue, ist listfindnocase () zu verwenden, um sicherzustellen, dass die Argumente der Reihenfolge von Klausel sind vergangen gültig:

<cfset variables.safeSortColumn = "name">
<cfset variables.safeSortOrder = "desc">

<cfparam name="url.sortcolumn" type="string" default="#variables.safeSortColumn#">
<cfparam name="url.sortorder" type="string" default="#variables.safeSortOrder#">

<cfif listfindnocase("name,age,address", url.sortcolumn)>
    <cfset variables.safeSortColumn = url.sortcolumn>
</cfif>

<cfif listfindnocase("desc,asc", url.sortorder)>
    <cfset variables.safeSortOrder = url.sortorder>
</cfif>

<cfquery>
select *
from mytable
order by #variables.safeSortcolumn# #variables.safeSortorder#
</cfquery>

Das Problem mit dem Ordnungswert für eine Spalte Referenz verwendet, ist es (ich glaube) der Ordnungswert zum Zeitpunkt der Tabelle SQL-Anweisung erstellen ausgeführt wurde - so wie Sie Spalten der Datenbanktabelle über die Zeit, das GUI-Tool hinzufügen Sie verwenden, um die Spalten angezeigt werden möglicherweise nicht den tatsächlichen Ordnungswert darstellen. Ich würde wirklich bleiben weg von cfqueryparam für diese verwendet wird.

Ich mag die Idee, eine Zahl in dem Anforderungs Verwendung von Variablen (url, Form) angeben, welche Spalte zu sortieren und dann, dass in dem Schalter verwenden und übersetzt es zu ein tatsächlichen Spaltennamen - so dass Sie nicht Ihre Spalte aussetzen Namen für den Benutzer.

bis wann / warum cfqueryparam zu verwenden, hält seine nicht nur um die Eingabevalidierung und verhindern SQL-Injection im Sinne (obwohl das ein sehr schöner Bonus ist) - mit cfqueryparam den zugrunde liegenden SQL auf die Datenbank zurück durch den Fahrer gesendet Verwendung von SQL bind-Variablen - Platzhalter Werte, so kann der databse Optimierer bestimmen, welcher Index in einem generischen Format zu verwenden ... so, wenn Sie eine SQL-Anweisung wie folgt an: SELECT * FROM Produkt WHERE ID = 1 und SELECT * FROM Produkt WHERE ID = 2 die Optimierer laufen beiden Male. aber mit Bind-Variablen, sieht die SQL-ähnliche SELECT * FROM Produkt WHERE ID =? (? = 1) und SELECT * FROM Produkt WHERE ID =? (? = 2), so kann der Optimierer verwendet die zwischengespeicherten Ergebnisse der ersten Analyse genau zu wissen, was Index für die zweite Abfrage zu verwenden. in Abhängigkeit von der Komplexität der SQL und der Datenbank kann dies eine enormen Einsparungen in der Zeit. in meiner Erfahrung seiner sehr hilfreich Leistung klug mit Oracle und Datum / Uhrzeit Spalten in der where-Klausel.

so soweit, wo cfqueryparam zu verwenden, sein, wo ein SQL-Bind Variable verwendet werden kann ...

hth jon

In Bezug auf den Kommentar über „cfqueryparam in der Reihenfolge Klausel gut mit MySQL“ verwenden. Ja, ich glaube, dass es mit MySQL-Datenquellen erlaubt. Obwohl mit der Spalte Ordnungs , nicht Spaltennamen (die als ein konstanten String behandelt zu werden scheinen statt).

Leider scheint es gar nicht für MS SQL-Datenquellen zu arbeiten. Zumindest nicht von dem, was ich sagen kann.

<!--- this works --->
<cfset url.sortColumnNumber = "3">
<cfquery name="getDataByPosition" datasource="MySQLDSN">
   SELECT  RecordID, ProductName, DateAdded
   FROM TestTable
   ORDER BY <cfqueryparam value="#url.sortColumnNumber#" cfsqltype="cf_sql_integer"> ASC
</cfquery>
<cfdump var="#getDataByPosition#">

<!--- this does NOT work --->
<cfset url.sortColumnName = "DateAdded">
<cfquery name="getDataByName" datasource="MySQLDSN">
   SELECT  RecordID, ProductName, DateAdded
   FROM    TestTable
   ORDER BY <cfqueryparam value="DateAdded" cfsqltype="cf_sql_varchar"> ASC
</cfquery>
<cfdump var="#getDataByName#">

Update: In Bezug auf die Kommentare über Ordnungs: Nein, ich glaube, es ist an die Spaltenposition in der Auswahlliste bezieht, nicht die zugrunde liegende Tabelle. So sollte es in Ordnung sein.

Ja, ich stimme SQL-Injection-Schutz ist nicht der Hauptzweck des cfqueryparam. So ist die Beschreibung von Bind-Variablen war eine gute Ergänzung.

Dachte, ich weniger Code auf dieses Problem werfen würde:

<cfset sortColumns = {IncidentID = "IncidentID", AnimalID = "AnimalID", IntakeDate = "IntakeDate", DxDate = "DxDate", OutcomeDate = "OutcomeDate"}>
<cfset sortDirections = {ASC = "ASC", DESC = "DESC"}>

<cfquery datasource="MyDSN" name="qIncidents">
    SELECT IncidentID, AnimalID, IntakeDate, DxDate, OutcomeDate
    FROM Incidents
    WHERE ShelterID = <cfqueryparam cfsqltype="cf_sql_integer" value="#Arguments.ShelterID#">
    ORDER BY #sortColumns[sortBy]# #sortDirections[sortDirection]#
</cfquery>

Wo sortBy und sortDirection kommen über die URL oder wo auch immer.

Ich mag das, weil es sauber ist und man kann nichts über die ORDER BY-Klausel injizieren.

Fragen oder Anregungen?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top