2009-03-04 10 views
3

Ich versuche, auf einen Spaltennamen zu verweisen, um eine Abfrage in einer Anwendung zu bestellen, die mit einer Oracle-Datenbank kommuniziert. Ich möchte eine Bind-Variable verwenden, damit ich dynamisch bestimmen kann, wofür die Abfrage angeordnet werden soll.Kann man in Oracle über Bind-Variablen auf Spaltennamen verweisen?

Das Problem, das ich habe, ist, dass die Datenbank die Reihenfolge nach Spalte zu ignorieren scheint.

Weiß jemand, ob es eine bestimmte Möglichkeit gibt, über eine Bindevariable auf eine Datenbankspalte zu verweisen, oder ob es überhaupt möglich ist?

zB meine Abfrage ist

SELECT * FROM PERSON ORDER BY :1 

(wo :1 zu PERSON.NAME gebunden wird) Die Abfrage wird nicht Ergebnisse in alphabetischer Reihenfolge der Rückkehr, ich mache mir Sorgen, dass die Datenbank dies als interpretiert: -

SELECT * FROM PERSON ORDER BY 'PERSON.NAME' 

die offensichtlich nicht funktioniert.

Alle Vorschläge werden sehr geschätzt.

Antwort

6

Nein. Sie können Bind-Variablen nicht für Tabellen- oder Spaltennamen verwenden.

Diese Informationen werden benötigt, um den Ausführungsplan zu erstellen. Ohne zu wissen, was Sie bestellen möchten, wäre es zum Beispiel unmöglich herauszufinden, welcher Index verwendet werden soll.

Anstatt Variablen zu binden, müssen Sie den Spaltennamen direkt in die SQL-Anweisung interpolieren, wenn Ihr Programm sie erstellt. Unter der Annahme, dass Sie Vorkehrungen gegen die SQL-Injektion treffen, gibt es keinen Nachteil.

Update: Wenn Sie wirklich durch Reifen springen wollen, werden Sie wahrscheinlich so etwas wie

order by decode(?, 'colA', colA, 'colB', colB) 

tun könnten, aber das ist einfach albern. Und langsam. Nicht.

+0

+1 btw Ich weiß nicht, ob das für Oracle gilt, aber es gibt definitiv einen Nachteil in anderen Datenbanken (wie DB2) - es macht viel schwieriger für die Datenbank, Abfragen zwischenzuspeichern, wenn Sie den Text des Abfragebefehls ändern Zeit (und nicht nur die Werte der Parameter) –

+0

Das passiert auch in Orakel. Aber Sie ändern den Befehlstext nicht ständig.Es gibt nur wenige Optionen für den Spaltennamen, sodass nur fünf Cache-Einträge vorhanden sind. – Thilo

+0

Vielen Dank, das macht Sinn für mich. Ich werde versuchen, den Code zu verstehen, wenn er die order by-Klausel betrachtet, und wenn er eine bind-Variable enthält, werde ich ihn durch seinen Wert ersetzen. – Scottm

2

Wie Sie JDBC verwenden. Sie können Ihren Code in etwas ohne Bindevariablen umschreiben. Auf diese Weise können Sie auch dynamisch den Auftrag durch z.B .: Oder sogar

String columnName = getColumnName(input); 
    Statement select = conn.createStatement(); 
    ResultSet result = select.executeQuery("SELECT * FROM PERS ORDER BY "+columnName); 
+0

SQL ist am besten in der Datenbank übrig. –

+0

Ich stimme nicht zu - das ist ein guter Vorschlag Edwin, danke. Es sieht so aus, als müsste ich so etwas tun. Ich muss auch einige Platzhalter aus der Abfragezeichenfolge entfernen, wenn ich die Reihenfolge nach Spalte hinzufüge. – Scottm

0

ResultSet result = select.executeQuery

String query = "SELECT * FROM PERS "; 
    if (condition1){ 
     query = query+ " order by name "; 
    // insert more if/else or case statements 
    } else { 
     query = query+ " order by other_column "; 
    } 
    Statement select = conn.createStatement(); 
    ResultSet result = select.executeQuery(query); 

ändern ("SELECT * FROM PERS ORDER BY" + column);

wird immer eine neue Aussage zur Datenbank sein. Das heißt, es ist, wie Thilo bereits erklärt hat, unmöglich, eine bereits gebundene, kalkulierte, vorbereitete, analysierte Aussage "neu zu ordnen". Wenn Sie dieses Ergebnis in Ihrer Anwendung immer wieder verwenden und nur die Reihenfolge der Präsentation ändern, versuchen Sie, das Set in Ihrem Client-Code zu bestellen. Ansonsten ist dynamisches SQL zwar in Ordnung, hat aber einen großen Footprint.

+0

Es wird nur eine neue Aussage sein, wenn columnName * immer * anders ist. Ich würde erwarten, dass columnName nur einen kleinen Satz von Werten annimmt, was bedeutet, dass der Schaden am gemeinsamen Pool minimal ist. –