Pergunta

Estou ocupado em um pedaço de código para obter alle os nomes de coluna de uma tabela de um banco de dados Oracle. O código que eu vim com esta aparência:

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

Quando eu corri este código para minha surpresa muitas colunas foram devolvidos. Um olhar mais atento revela que o ResultSet continha um conjunto duplicado de todas as colunas, ou seja, cada coluna foi devolvido duas vezes. Aqui está a saída que eu tenho:

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

Quando eu olhar para a tabela usando o Oracle SQL Developer isso mostra que a tabela só tem três colunas (ID, nome, cidade). Eu tentei este código contra várias tabelas diferentes no meu banco de dados e alguns trabalhos muito bem, enquanto outros apresentam esse comportamento estranho.

Pode haver um bug no driver JDBC Oracle? Ou estou fazendo algo errado aqui?


Update: Graças ao Kenster agora tenho uma maneira alternativa para recuperar os nomes das colunas . Você pode obtê-los a partir de um ResultSet, como este:

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

Isso parece funcionar muito bem e há duplicatas são devolvidos! E para aqueles que se perguntam: de acordo com neste blog você deve usar getColumnLabel () em vez de getColumnName ().

Foi útil?

Solução

Na Oracle, Connection.getMetaData() retorna meta-dados para o inteira banco de dados, não apenas o esquema tiver que ser conectado. Então, quando você fornecer null como os dois primeiros argumentos para meta.getColumns(), você não está filtrando os resultados para apenas o seu esquema.

Você precisa fornecer o nome do esquema do Oracle a um dos dois primeiros parâmetros de meta.getColumns(), provavelmente, o segundo, por exemplo.

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

É um pouco irritante ter que fazer isso, mas essa é a maneira como as pessoas da Oracle optou por implementar o seu driver JDBC.

Outras dicas

Esta não responder diretamente sua pergunta, mas uma outra abordagem é para executar a consulta:

select * from tablename where 1 = 0

Isso irá retornar um ResultSet, embora não selecionar nenhuma linha. Os metadados conjunto de resultados irá coincidir com a tabela que você selecionou. Dependendo do que você está fazendo, isso pode ser mais conveniente. tablename pode ser qualquer coisa que você pode selecionar em -. você não tem que ter o caso correto ou se preocupar com o esquema que está em

Na actualização à sua pergunta eu notei que você perdeu uma parte chave da resposta de Kenster. Ele especificou uma cláusula 'onde' de 'onde 1 = 0', que você não tem. Isto é importante porque se você deixá-lo fora, em seguida, a Oracle vai tentar voltar a tabela inteira. E se você não puxar todos os registros sobre, oracle vai realizar-lhes, esperando por você para página através deles. Acrescentando que onde cláusula ainda lhe dá os metadados, mas sem qualquer um dos acima.

Além disso, eu pessoalmente uso 'onde rownum <1', desde que a Oracle sabe imediatamente que todos os rownums são passado que, e eu não tenho certeza se ele é inteligente o suficiente para não experimentar e testar cada registro para '1 = 0'.

Além de resposta de skaffman -

usar a seguinte consulta no Oracle:

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

para acessar o nome do esquema atual, se você está restrito a fazê-lo em Java.

Este é o comportamento estipulado pela API JDBC - passando nulos como primeiro e segundo parâmetro para meios GetColumns que nem nome de catálogo nem nome de esquema são usados ??para restringir a pesquisa. link para a documentação . É verdade que alguns outros drivers JDBC tem um comportamento diferente por padrão (ConnectorJ de exemplo MySQL por restringe padrão para o catálogo atual), mas isso não é padrão, e documentado como tal

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top