Sau khi thiết kế ngược lại các giao tiếp thực sự giữa máy khách và máy chủ, tôi có thể tiết lộ rằng các phương thức DatabaseMetaData.getColumns () của Oracle gửi truy vấn SQL sau (mặc dù điều này có thể thay đổi với các phiên bản và cài đặt trình điều khiển ODBC):
declare
in_owner varchar2(128);
in_name varchar2(128);
in_column varchar2(128);
xyzzy SYS_REFCURSOR;
begin
in_owner := :1; // Which resolves to the schema (user) name supplied
in_name := :2; // Which resolves to the table name supplied
in_column := :3; // Which gets set to '%';
open xyzzy for
SELECT NULL AS table_cat,
t.owner AS table_schem,
t.table_name AS table_name,
t.column_name AS column_name,
DECODE( (SELECT a.typecode
FROM ALL_TYPES A
WHERE a.type_name = t.data_type),
'OBJECT', 2002,
'COLLECTION', 2003,
DECODE(substr(t.data_type, 1, 9),
'TIMESTAMP',
DECODE(substr(t.data_type, 10, 1),
'(',
DECODE(substr(t.data_type, 19, 5),
'LOCAL', -102, 'TIME ', -101, 93),
DECODE(substr(t.data_type, 16, 5),
'LOCAL', -102, 'TIME ', -101, 93)),
'INTERVAL ',
DECODE(substr(t.data_type, 10, 3),
'DAY', -104, 'YEA', -103),
DECODE(t.data_type,
'BINARY_DOUBLE', 101,
'BINARY_FLOAT', 100,
'BFILE', -13,
'BLOB', 2004,
'CHAR', 1,
'CLOB', 2005,
'COLLECTION', 2003,
'DATE', 93,
'FLOAT', 6,
'LONG', -1,
'LONG RAW', -4,
'NCHAR', -15,
'NCLOB', 2011,
'NUMBER', 2,
'NVARCHAR', -9,
'NVARCHAR2', -9,
'OBJECT', 2002,
'OPAQUE/XMLTYPE', 2009,
'RAW', -3,
'REF', 2006,
'ROWID', -8,
'SQLXML', 2009,
'UROWI', -8,
'VARCHAR2', 12,
'VARRAY', 2003,
'XMLTYPE', 2009,
1111)))
AS data_type,
t.data_type AS type_name,
DECODE (t.data_precision, null,
DECODE(t.data_type, 'NUMBER',
DECODE(t.data_scale, null, 0 , 38),
DECODE (t.data_type, 'CHAR', t.char_length, 'VARCHAR', t.char_length, 'VARCHAR2', t.char_length, 'NVARCHAR2', t.char_length, 'NCHAR', t.char_length, 'NUMBER', 0, t.data_length) ), t.data_precision)
AS column_size,
0 AS buffer_length,
DECODE (t.data_type, 'NUMBER', DECODE(t.data_precision, null, DECODE(t.data_scale, null, -127 , t.data_scale), t.data_scale), t.data_scale) AS decimal_digits,
10 AS num_prec_radix,
DECODE (t.nullable, 'N', 0, 1) AS nullable,
NULL AS remarks,
t.data_default AS column_def,
0 AS sql_data_type,
0 AS sql_datetime_sub,
t.data_length AS char_octet_length,
t.column_id AS ordinal_position,
DECODE (t.nullable, 'N', 'NO', 'YES') AS is_nullable,
null as SCOPE_CATALOG,
null as SCOPE_SCHEMA,
null as SCOPE_TABLE,
null as SOURCE_DATA_TYPE,
'NO' as IS_AUTOINCREMENT,
t.virtual_column as IS_GENERATEDCOLUMN
FROM all_tab_cols t
WHERE t.owner LIKE in_owner ESCAPE '/'
AND t.table_name LIKE in_name ESCAPE '/'
AND t.column_name LIKE in_column ESCAPE '/'
AND t.user_generated = 'YES'
ORDER BY table_schem, table_name, ordinal_position;
end;
Bạn có thể đánh giá cao lý do tại sao điều đó có thể hơi chậm, đặc biệt là các bảng ALL_TAB_COLS và ALL_TYPES mỗi bảng có thể dài 1000 bản ghi. Tuy nhiên, trong khi Oracle đấu tranh để thực hiện lệnh gọi đầu tiên (phút) các cuộc gọi tiếp theo trả về kết quả gần như ngay lập tức. Đây là một vấn đề về hiệu suất tham gia bảng cổ điển trong đó mặc dù một tập dữ liệu con được yêu cầu nhưng công cụ vẫn tham gia toàn bộ tập dữ liệu trước đó tính toán và phân phối tập hợp con được yêu cầu. Sau đó, bộ nhớ đệm dữ liệu / kết quả hoạt động để cải thiện hiệu suất của các truy vấn tiếp theo.
Giải pháp tốt hơn có thể là sử dụng get_ddl () và phân tích cú pháp định nghĩa bảng được trả về theo chuỗi này .
Ngoài ra bạn có thể truy vấn siêu dữ liệu trên bảng nhanh hơn bằng cách thực hiện một truy vấn giả, sau đó sử dụng resultSetMetadata như sau (Lưu ý:siêu dữ liệu nhận xét cột có thể không khả dụng ngay lập tức):
ResultSet rs = connection.CreateStatement.executeQuery("SELECT * from MyTable WHERE 1=0");
ResultSetMetaData md = rs.getMetaData();
for (int ix = 1; ix <= md.getColumnCount(); ix++)
{
int colSize = md.getPrecision(ix);
String nativeType = md.getColumnTypeName(ix);
int jdbcType = md.getColumnType(ix);
// and so on....
}