I am doing a metadata fetch from teradata using jdbc and I would like to get all the datatypes. However for DB fields containing DECIMAL(10,4) I am not able to get the precision. I am attaching my code snippet. Suggestions would be welcome!
DatabaseMetaData md = con.getMetaData();
ResultSet tbls = md.getTables(null, schema, name, null);
if(false == tbls.next()){
nonExistingRdbmsTables.add(name);
LOGGER.error("Table with name {} in schema {} does not exists in source database", name, schema);
continue;
}
RdbmsTableMetadata tableMD = new RdbmsTableMetadata();
List<String> pkList = new ArrayList();
ResultSet primaryKeys = md.getPrimaryKeys(null, schema, name);
while(primaryKeys.next()){
String pk = primaryKeys.getString("COLUMN_NAME");
pkList.add(pk);
}
tableMD.setPkList(pkList);
LOGGER.info("*****Primary key list for table {} is {}", name, pkList);
tableMD.setSchema(schema);
tableMD.setName(name);
tableMD.setTargetName(targetName);
tableMD.setTargetSchema(targetSchema);
List<Column> colList = new ArrayList<>();
ResultSet cols = md.getColumns(null, schema, name, null);
while (cols.next()) {
String columnName = cols.getString("COLUMN_NAME");
String columnType = cols.getString("TYPE_NAME");
String columnLength = cols.getString("COLUMN_SIZE");
}
Is there any way I can query the precision details from jdbc metadata?
For future referencers:-
int precision = cols.getInt("DECIMAL_DIGITS");
This worked fine! Thanks to alex and Mark.
ResultSetMetaData provides getScale(int col) and getPrecision(int col) methods. If those don't give you what you want, you're probably out of luck.
Related
I want to fetch all the tables and their columns metadata present in the database in json format.
in the json file, the tablename key value pair is showing only the last table in the database and not all.
My code is below:
ResultSet tables = databaseMetaData.getTables(catalog, schemaPattern, tableNamePattern, types);
while (tables.next()) {
String tableName = tables.getString(3);
jsonObject.put("tablename", tablename);
ResultSet columnMetadata = databaseMetaData.getColumns(null, null, tableName, null);
while (columnMetadata.next()) {
JSONObject record = new JSONObject();
record.put("Field_Name", columnMetadata.getString("COLUMN_NAME"));
record.put("Field_Length", columnMetadata.getString("COLUMN_SIZE"));
array.put(record);
}
jsonObject.put("field", array);
}
Any help would be appreciated.
I am Retrieving some tables from database and storing those table names in a hashset. Code I am using to retrieve table is as follows
DatabaseMetaData md = conn.getMetaData();
ResultSet rs = md.getTables(null, null, "%", null);
while (rs.next()) {
hash. add(rs. getString(3) ) ;
}
Now I have tables in a hash set.
Now I want to retrieve data from all these tables in a hash set for particular column 'student'. And put all values in a list. I want to retrieve all distinct values of column student in all these tables. Table may contain or may not contain this student column. If a table contains this column then I want to store its distinct values in a list. Please suggest how to do it.
Note that you can not extract table data using the databasemetadata. Databasemetadata will only provide you the details of table like name, columns, datatypes etc. You need to make the JDBC connection with the database and then need to fire the select query to get the desired result.
Below is the simple JDBC program to do so:
DatabaseMetaData md = conn.getMetaData();
// get tables from database
ResultSet rs = md.getTables(null, null, "%", null);
while (rs.next()) {
hash. add(rs. getString(3) ) ;
}
// getColumns of table 'tableName'
ResultSet rs2 = md.getColumns(null, null, tableName, null);
boolean found = false;
while (rs2.next()) {
String columnName = rs2.getString("COLUMN_NAME");
if (columnName.equalsIgnoreCase("student")) {
found = true;
break;
}
}
if (found) {
String driver = "provide the driver for database here like com.mysql.....";
String url = "provide the connection url here like jdbc://...."
String userName = "provide DB username"
String password = "provide DB username"
Class.forName(driver)
Connection conn = DriverManager.getConnection(url, userName, password)
Statement st = conn.createStatement();
Resultset rs3 = null;
// Now take the tableName from your hashset and pass it into below query.
String query = "select student from " + tableName;
rs3 = st.executeQuery(query);
While(rs3.next()) {
// Store the results anywhere you want by obtaining 'rs3.getString(1)'
}
}
Hope this resolves your problem. Please ignore typos in code if any.
I would like to check the database for duplicates before inserting into the database. It is only considered a duplicate when plateNo, driverID and resDate match.
Here is how I get the data that will be inserted to the database
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String client = (String) clientCmb.getSelectedItem();
String[] cparts = client.split("-");
String cpart = cparts[0];
String driver = (String) driverCmb.getSelectedItem();
String[] dparts = driver.split("-");
String dpart = dparts[0];
String van = (String) vanCmb.getSelectedItem();
java.util.Date oDate = jXDatePicker2.getDate();
DateFormat oDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String date = oDateFormat.format(oDate);
model2.addRow(cpart, dpart, van, date);
}
And here's the code for my addRow method
public void addRow(String client, String driver, String van, String res){
try {
String sqlRes = "Select * from reservation";
rs = st.executeQuery(sqlRes);
rs.moveToInsertRow();
rs.updateString("clientID", client);
rs.updateString("plateNo", van);
rs.updateString("driverID", driver);
rs.updateString("resDate", res);
rs.insertRow();
rs.moveToCurrentRow();
rs = st.executeQuery(sqlRes);
this.fireTableDataChanged();
} catch (SQLException ex) {
Logger.getLogger(MyModel2.class.getName()).log(Level.SEVERE, null, ex);
}
Let the database do the work for you. Define a unique index/constraint specifying that those three values are unique in the table:
create unique index unq_reservation_3 on reservation(plateNo, driverID, resDate);
If you attempt to insert a duplicate -- or do an update that results in a duplicate -- then the database will return an error. You simply need to catch the error.
Use MERGE statement: T-SQL or ORACLE, or for MySQL:
PreparedStatement p = con.prepareStatement("
INSERT INTO reservation tgt (clientID, plateNo, driverID, resDate)
SELECT (? As clientID, ? As plateNo, ? As driverID, ? As resDate)
FROM DUAL ins
LEFT JOIN reservation ref
ON ref.resDate = ins.resDate
AND (ref.plateNo = ins.plateNo OR ref.driverID = ins.driverID)
WHERE ref.clientID IS NULL;
");
p.setString(1, client);
p.setString(2, van);
p.setString(3, driver);
p.setString(4, res);
return p.executeUpdate(); /* 1 - Success | 0 - Ignored Duplicate */
I found there is some problem in Oracle 11g to get table name from interface(ResultSet.getMetaData().getTableName(int column));
It always show the empty string.
Is there something wrong for oracle database or jdbc driver? If the jdbc driver's problem , Can I get another jdbc driver to resolve this issue?
Thanks in advance!
According to the documentation this is not supported:
but does not implement the getSchemaName and getTableName methods because Oracle Database does not make this feasible
Earlier Oracle drivers did have this feature, but it needed to be enabled explicitly because of its performance implications. As far as I can tell from the documentation this is no longer available in more recent drivers.
Please look into the following http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSetMetaData.html
You could use:
DatabaseMetaData metadata = currentConnection.getMetaData();
String[] names = {"TABLE"};
ResultSet tables = metadata.getTables(null,"%", "%", names);
while (tables.next()) {
String tableName = tables.getString("TABLE_NAME");
String tableSchema = tables.getString("TABLE_SCHEM");
}
ResultSet columns = metadata.getColumns(null, "%", tableName, "%");
while (columns.next()) {
String columnName = columns.getString("COLUMN_NAME");
String datatype = columns.getString("TYPE_NAME");
int datasize = columns.getInt("COLUMN_SIZE");
int nullable = columns.getInt("NULLABLE");
}
Read this for more info.
after running into this specifical issue face-first a few days ago, I finally came up with a solution that does the job. Of course it's neither pretty nor... well... anything, but it works.
Basically, I check every table in my database against the columns in the ResultSet.
I hope someone else can use this. Took me about a day to get this straight.
Note: I use a CachedRowSet instead of a ResultSet, which doesn't require me to keep the database connection open the whole time.
private static String getTableNameByCols(ResultSetMetaData rsmd, DatabaseMetaData dbmd) throws SQLException{
String errorString = "No matching table found for the given column Set";
String ret = null, origColName, origDatatype, tableName;
String[] names = {"TABLE"};
ResultSet tables = dbmd.getTables(null, username, "%", names);
// get all the columns out of the rsmd and put them into an Array
Integer numberOfColumns = rsmd.getColumnCount();
String[] origColNames = new String[numberOfColumns+1];
String[] origColTypeNames = new String[numberOfColumns+1];
for (int i=1; i<numberOfColumns+1; i++){
origColNames[i] = rsmd.getColumnName(i);
origColTypeNames[i] = rsmd.getColumnTypeName(i);
}
ResultSet columns = null;
while (tables.next()) {
tableName = tables.getString("TABLE_NAME");
columns = dbmd.getColumns(null, null, tableName, null);
CachedRowSet crs = new CachedRowSetImpl();
crs.populate(columns);
Integer tablesNumberOfColumns = crs.size();
int i = 1;
if (numberOfColumns.intValue() == tablesNumberOfColumns.intValue()){
while (crs.next()) {
origColName = origColNames[i];
origDatatype = origColTypeNames[i];
String colName = crs.getString(4);
String datatype = crs.getString(6);
//int datasize = columns.getInt("COLUMN_SIZE");
//int nullable = columns.getInt("NULLABLE");
if (origColName.equals(colName) && origDatatype.equals(datatype) ){
ret = tableName;
} else {
ret = null;
}
i += 1;
} // looked at all the columns
crs.close();
}// same # of columns check over
if (ret != null) {
break;
}
columns.close();
}
verify(ret, errorString);
return ret;
}
The surrounding method:
private static boolean updateLocalTable(ResultSet rs){
ResultSetMetaData rsmd;
DatabaseMetaData dbmd;
String table_name;
boolean ret = false;
try {
rsmd = rs.getMetaData();
dbmd = conn.getMetaData();
table_name = getTableNameByCols(rsmd, dbmd);
/* ... do stuff with it ... */
} catch (Exception e) {
print("kablooey! \n" + e.getStackTrace());
}
return ret;
}
i am useing the following code to get only list of mysql tables and add them to the JComboBox. but what I get is only "[]" in the JComboBox! please help me with it
ArrayList<String> tables = new ArrayList<String>();
public ArrayList<String> tablesArray() throws SQLException
{
ResultSet result = connecting.getMetaData().getCatalogs();
while(result.next())
{
tables.add(result.getString(0));
}
return tables;
}
public JComboBox comboBox()
{
JComboBox<ArrayList> combo = new JComboBox<ArrayList>();
combo.addItem(tables);
combo.setBounds(130,30,190,30);
return combo;
}
ArrayList tables = new ArrayList();
is array that contains one or more Items
combo.addItem(tables);
later you added a.m. array as Item, then output could be correct
pass array as constructor, more see in JComboBox API Constructor Summary
better to create an DefaultComboBoxModel (see a.m. API) and add those Items from ResultSet to model directly
Try the following
while(result.next())
{
tables.add(result.getString(1));
}
See this question for more information: How to check if a particular database in mysql already exists using java or this one how to get list of Databases "Schema" names of MySql using java JDBC
However I am a bit confused are you looking for database names? Or are you trying to find table names?
When using MySQL you can always query the information_Schema views for LOADS of information regarding the tables, databases columns etc.
The getCatalogs() method returns catalog names, not table names. I'm not sure what it will do on MySQL, since AFAIK MySQL does not have catalogs.
If you call DatabaseMetaData.getTables(...) and use null for the first param, catalog, it should give you all table names without narrowing the result to any catalog.
you should try this
ResultSetMetaData meta = (ResultSetMetaData) rs.getMetaData();
int columns = meta.getColumnCount();
while(rs.next()){
for(int i =1; i<=columns; i++){
String yourValues = rs.getString(i);
theCombo.addItem(yourValues);
//rs is the result set for the executed query.
}
Here is a complete code to retrieve all tables of a database into JComboBox:
public JComboBox<String> comboBox() throws SQLException
{
ResultSet rs = connecting.getMetaData().getTables(null, null, "%", null);
ResultSetMetaData meta = (ResultSetMetaData) rs.getMetaData();
int columns = meta.getColumnCount();
while(rs.next())
{
String table_names = rs.getString("TABLE_NAME");
combo.addItem(table_names);
}
combo.setBounds(130,30,190,30);
combo.setSelectedIndex(0);
combo.setMaximumRowCount(5);
return combo;
}