문제

저는 Oracle 데이터베이스에서 테이블의 모든 열 이름을 가져오는 코드 작업으로 바쁘습니다.내가 생각해낸 코드는 다음과 같습니다.

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

이 코드를 실행했을 때 놀랍게도 너무 많은 열이 반환되었습니다.자세히 살펴보면 ResultSet에 모든 열의 중복 세트가 포함되어 있음이 드러났습니다.모든 열은 두 번 반환되었습니다.내가 얻은 결과는 다음과 같습니다.

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

Oracle SQL Developer를 사용하여 테이블을 보면 테이블에 세 개의 열(ID, NAME, CITY)만 있는 것으로 나타났습니다.내 데이터베이스의 여러 다른 테이블에 대해 이 코드를 시도했는데 일부는 제대로 작동하지만 다른 일부는 이상한 동작을 나타냅니다.

Oracle JDBC 드라이버에 버그가 있을 수 있습니까?아니면 내가 여기서 뭔가 잘못하고 있는 걸까요?


업데이트: 덕분에 켄스터 이제 열 이름을 검색하는 다른 방법이 있습니다.다음과 같이 ResultSet에서 가져올 수 있습니다.

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

이것은 잘 작동하는 것 같고 중복 항목이 반환되지 않습니다!궁금하신 분들을 위해:~에 따르면 이 블로그 getColumnName() 대신 getColumnLabel()을 사용해야 합니다.

도움이 되었습니까?

해결책

오라클에서 Connection.getMetaData() 메타 데이터를 반환합니다 전체 연결된 스키마뿐만 아니라 데이터베이스. 그래서 당신이 공급할 때 null 처음 두 주장으로 meta.getColumns(), 당신은 스키마의 결과 만 필터링하는 것이 아닙니다.

Oracle 스키마의 이름을 처음 두 매개 변수 중 하나에 제공해야합니다. meta.getColumns(), 아마도 두 번째 일 것입니다

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

이 작업을 수행해야한다는 것은 약간 자극적이지만 Oracle 사람들이 JDBC 드라이버를 구현하기로 선택한 방식입니다.

다른 팁

이것은 귀하의 질문에 직접적으로 대답하지는 않지만 다른 접근 방식은 쿼리를 실행하는 것입니다.

select * from tablename where 1 = 0

행을 선택하지 않더라도 ResultSet이 반환됩니다.결과 집합 메타데이터는 선택한 테이블과 일치합니다.수행 중인 작업에 따라 이 방법이 더 편리할 수 있습니다. tablename 선택할 수 있는 것은 무엇이든 될 수 있습니다. 대소문자를 정확하게 입력하거나 어떤 스키마에 있는지 걱정할 필요가 없습니다.

귀하의 질문에 대한 업데이트에서 나는 당신이 Kenster의 대답의 주요 부분을 놓쳤다는 것을 알았습니다. 그는 당신이 가지고 있지 않은 'Where'의 'where'조항 '을 지정했습니다. 당신이 그것을 떠나면, 오라클은 전체 테이블을 시도하고 반환하기 때문에 이것은 중요합니다. 그리고 당신이 모든 레코드를 끌어 당기지 않으면, Oracle은 그들에게 붙잡을 것입니다. 절을 추가하면 여전히 메타 데이터를 제공하지만 오버 헤드는 없습니다.

또한, 나는 개인적으로 'Rownum <1'을 개인적으로 사용합니다. Oracle은 모든 Rownums가 그 과거를 지나친 것을 즉시 알고 있기 때문에 '1 = 0'에 대한 각 레코드를 시도하고 테스트하지 않을 정도로 똑똑한 지 확실하지 않습니다.

Skaffman의 답변 외에도 -

Oracle에서 다음 쿼리를 사용하십시오.

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

Java에서 그렇게하도록 제한된 경우 현재 스키마 이름에 액세스하려면.

이것은 JDBC API에 의해 의무화 된 동작입니다 - 널을 첫 번째 및 두 번째 매개 변수로 전달하는 것은 카탈로그 이름이나 스키마 이름이 검색을 좁히는 데 사용되지 않음을 의미합니다.문서에 대한 링크 . 일부 다른 JDBC 드라이버는 기본적으로 다른 동작을 가지고 있다는 것은 사실이지만 (예 : 기본적으로 MySQL의 Connectorj는 현재 카탈로그로 제한됩니다) 이는 표준이 아니며 문서화됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top