Frage

Ich bin auf einem Stück Code beschäftigt die Spaltennamen einer Tabelle aus einer Oracle-Datenbank erhalten alle. Der Code kam ich mit sieht wie folgt auf:

DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection(
  "jdbc:oracle:thin:@<server>:1521:<sid>", <username>, <password>);

DatabaseMetaData meta = conn.getMetaData();
ResultSet columns = meta.getColumns(null, null, "EMPLOYEES", null);
int i = 1;
while (columns.next())
{
  System.out.printf("%d: %s (%d)\n", i++, columns.getString("COLUMN_NAME"), 
    columns.getInt("ORDINAL_POSITION"));
}

Wenn ich diesen Code zu meiner Überraschung lief zu viele Spalten zurückgegeben wurden. Ein genauerer Blick offenbart, dass die ResultSet ein Duplikat Satz aller Spalten enthalten sind, das heißt jede Spalte zweimal zurückgegeben wurde. Hier ist die Ausgabe Ich habe:

1: ID (1)
2: NAME (2)
3: CITY (3)
4: ID (1)
5: NAME (2)
6: CITY (3)

Als ich am Tisch Entwickler mit Oracle SQL aussehen zeigt es, dass die Tabelle nur drei Spalten (ID, Name, Stadt). Ich habe diesen Code versucht, gegen mehrere verschiedene Tabellen in meiner Datenbank und einige Arbeit ganz gut, während andere diese seltsame Verhalten zeigen.

Gibt es einen Fehler in dem Oracle-JDBC-Treiber sein? Oder mache ich etwas falsch hier?


Update: Dank Kenster Ich habe jetzt eine alternative Möglichkeit, die Spaltennamen abzurufen . Sie können sie von einem ResultSet, wie diese:

DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver());
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@<server>:1521:<sid>", <username>, <password>);

Statement st = conn.createStatement();
ResultSet rset = st.executeQuery("SELECT * FROM \"EMPLOYEES\"");
ResultSetMetaData md = rset.getMetaData();
for (int i=1; i<=md.getColumnCount(); i++)
{
    System.out.println(md.getColumnLabel(i));
}

Das scheint zurückgekehrt sind ganz gut und keine Duplikate zu arbeiten! Und für diejenigen, die sich fragen: nach diesem Blog verwenden sollte getColumnLabel () anstelle von getColumnName ().

War es hilfreich?

Lösung

In Oracle gibt Connection.getMetaData() Meta-Daten für die gesamte Datenbank, nicht nur das Schema der Sie verbunden werden passieren. Also, wenn Sie null als die ersten beiden Argumente liefern meta.getColumns(), Sie filtern die Ergebnisse nicht nur für Ihr Schema.

Sie müssen die Namen des Oracle-Schemas zu einem der ersten beiden Parametern von meta.getColumns() liefern, die wahrscheinlich die zweiten, z.

meta.getColumns(null, "myuser", "EMPLOYEES", null);

Es ist ein wenig irritierend, dies zu tun zu haben, aber das ist die Art, wie die Oracle Leute wählten ihre JDBC-Treiber zu implementieren.

Andere Tipps

Dies ist nicht direkt Ihre Frage zu beantworten, aber ein anderer Ansatz besteht darin, die Abfrage auszuführen:

select * from tablename where 1 = 0

Dies wird ein ResultSet zurückkehren, auch wenn es keine Zeilen aus. Die Ergebnismenge Metadaten werden in der Tabelle übereinstimmen, die Sie ausgewählt. Je nachdem, was Sie tun, kann dies bequemer sein. tablename kann alles, was Sie wählen auf können -. Sie müssen nicht den Fall bekommen richtig oder Sorgen darüber, was Schema es in

In dem Update auf Ihre Frage stellte ich fest, dass Sie einen wichtigen Teil der Kenster Antwort verpaßt. Er präzisierte, eine ‚wo‘ Klausel von ‚1 = 0‘, die Sie nicht haben. Dies ist wichtig, denn wenn man es weglassen, dann wird Oracle versuchen, und die gesamte Tabelle zurück. Und wenn Sie alle Datensätze nicht überziehen, wird Orakel zu ihnen halten, für Sie, um durch sie zu warten. Fügte hinzu, dass, wo Klausel noch gibt Ihnen die Metadaten, aber ohne den Overhead.

Auch ich persönlich benutze ‚wo rownum <1‘, da Orakel weiß sofort, dass alles rownums Vergangenheit, die ist, und ich bin nicht sicher, ob es klug genug, nicht zu versuchen, jeden Datensatz testen für ‚1 = 0‘.

Neben skaffman Antwort -

Verwenden Sie die folgende Abfrage in Oracle:

select sys_context( 'userenv', 'current_schema' ) from dual;  

Ihre aktuellen Schemanamen zugreifen, wenn Sie beschränkt sind so in Java zu tun.

Dies ist das Verhalten von dem JDBC-API beauftragt - nulls als erster und zweiten Parameter getColumns bedeutet beiläufig, dass weder Katalog Name noch Schemanamen werden verwendet, um die Suche einzugrenzen. Link zur Dokumentation . Es ist wahr, dass einige andere JDBC-Treiber standardmäßig unterschiedliches Verhalten haben (zum Beispiel MySQL ConnectorJ standardmäßig beschränkt auf den aktuellen Katalog), aber dies ist nicht Standard, und als solche dokumentiert

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