I have a sql query fro which I need the column name and data type and it's table name and schema name:
Thsi is the method I am using for using and testing it for SQLSERVER:
public static void getMetadataForConn(Connection conn) throws SQLException
{
ResultSet rs = null;
try
{
Statement stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT AB_DEMO_SRC.dbo.employee.dept_id dept_id, AB_DEMO_SRC.dbo.employee.email_add email_add, AB_DEMO_SRC.dbo.employee.emp_address emp_address, AB_DEMO_SRC.dbo.employee.emp_id emp_id, AB_DEMO_SRC.dbo.employee.emp_name emp_name FROM AB_DEMO_SRC.dbo.employee ");
ResultSetMetaData md = rs.getMetaData();
int columnCount = md.getColumnCount();
for (int i = 1; i <= columnCount; i++)
System.out.print(md.getColumnName(i) + "(" + md.getColumnType(i) + ") "+md.getSchemaName(i)+"."+md.getTableName(i));
System.out.println();
while (rs.next())
{
for (int i = 1; i <= columnCount; i++)
{
Object o = rs.getObject(i);
System.out.print(null == o ? "" : o.toString() + " ");
}
System.out.println();
}
}
finally
{
if (null != rs)
{
rs.close();
}
}
}
I get all the other metadata details like data type, precision and scale..Strangely, I am getting tablename and schema name as "" that is blank..IS there any other way to fetch the metadata of the columns present in a Query?
I think the problem is that the columns of a ResultSet are not related to any table, they are related just to the query. The query could be complex, it could have computed columns etc. That is why their table names are blank.
If you want to get the information about the columns of a specific table, you can use the metadata of the database:
DatabaseMetaData meta = conn.getMetaData();
ResultSet columns = meta.getColumns(null, "dbo", "employee", null);
You can fetch column name by calling 'getMetaData' method of ResultSet.
ResultSetMetaData metaData= resultSet.getMetaData();
String columnName = metaData.getColumnName(1);
All other column meta data can also be fetching using object of ResultSetMetaData
Related
I need to verify if a column already exists in a table . My class extends CustomTaskChange so my method receives a Database object as an argument. Can I make the verification I want trough the ResultSetObject?
#Override
public void execute(Database database) throws CustomChangeException {
JdbcConnection connection = (JdbcConnection) database.getConnection();
DatabaseMetaData metadata;
metadata = connection.getMetaData();
String[] types = {"TABLE"};
ResultSet rs = metadata.getTables(null, null, "%", types);
Statement s = connection.createStatement();
while (rs.next()) {
String tableName = rs.getString(3);
if (tableName.endsWith(this.suffix)) {
String sql = sqlStatement.replaceAll("name", tableName);
s.execute(sql);
}
}
}
Basically what this piece of code is doing is going through all the tables in my database. If, a table name ends in a suffix, I will add the column to it. This way I can add a column to multiple tables at the same time.
But I want to add another verification to add the column to a table, and that is that there can't already be a column with that name in that table. Something like this(pseudocode)
if(tableName.endsWith(this.suffis) && columnName doesn't exist in that table){
String sql = sqlStatement.replaceAll("name", tableName);
s.execute(sql);
}
you can fetch columns from each of the tables then you can check column exist or not.
{
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM TABLENAME LIMIT 1");
ResultSetMetaData md = rs.getMetaData();
int col = md.getColumnCount();
for (int i = 1; i <= col; i++){
String col_name = md.getColumnName(i);
if(col_name.equals("YourColumnName"){
/*Then the column already exist*/
}}
With the above code, you can check the metadata and then execute the SQL query to delete the same.
I have a Java SQL question relative to the insert method. If I have a database with multiple tables, I want to write a single insert method that can insert a row of data into any selected table for any type of relational database. If some tables contain different data types, for examples (integer, date, varchar, and etc.). My codes:
public void insertData(String tablename, String... values)
throws SQLException {
Connection con = null;
PreparedStatement prepStmt = null;
if (values.length == 0) {
throw new SQLException("Must supply values");
}
try{
con = getConnection();
String sql = "insert into "+tablename+" values(";
for (int i = 0; i < values.length; i++) {
sql += "?";
if (i != values.length-1) sql += ",";
}
sql += ")";
prepStmt = con.prepareStatement(sql);
for (int i = 0; i < values.length; i++) {
prepStmt.setString(i, values[i]);
}
prepStmt.executeUpdate();
}
finally {
closeStatement(prepStmt);
closeConnection(con);
}
}
For example, use case:
Table Teacher has int id, varchar(50) name, int age, text subject, int
classid;
Table Student has int id, varchar(50) name, date dateofbirth, text
address;
Table Class has int id, text subject;
If I use:
insertData(Teacher, new String[] {"10", "Cass", "32", "Math", "10222"});
Will that data insert into the table successfully? I heard the database is only using varchar. If that is the case, then I don't have to worry about the type. If the type is varchar, should I use prepStmt.setString()?
I need to support multiple different types of database, such like SQL Server, MySQL, Oracle and others. Will that one insertData() method work for all different databases?
The database meta data can tell you the details of the table.
What you can do is using DatabaseMetaData to get the column names, types and size, then you can choose PreparedStatement corresponding setXXX methods:
DatabaseMetaData metadata = connection.getMetaData();
ResultSet resultSet = metadata.getColumns(null, null, "mytable", null); // table name is mytable
while (resultSet.next()) {
String name = resultSet.getString("COLUMN_NAME");
String type = resultSet.getString("TYPE_NAME");
int size = resultSet.getInt("COLUMN_SIZE");
}
Another way is using ResultSetMetaDatabut you have to query from the table to get the ResultSet
ResultSet rs = stmt.executeQuery(query);
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount() ; // returns the number of columns
for(int i = 1; i < columnCount + 1; i++){
rsmd.getColumnName(i); //get name
}
After you get the table's information(column name, type...), then you can choose proper query to update the table
Your scenario will work only in case when you are passing value for every column, if there is any nullable column in your table and you don't want to insert value on that it will not work and will throw sql exception as you have to specify the column name too in insert statement but when in your case you can pass Object array instead of String array and then call the appropriate setXXX according to the class type of parameter which your can fine from getClass method.
I have a basic java application and a sqlite DB.
I can create table manually through sqLite browser. And I am able to access these tables from my JAVA application.
E.g. Reading from existing table: (I have omitted the try catch blocks in the sample below just to reduce the length of question)
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
String query = "select * from test1 where uname = ? and name = user1";
preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, "test");
resultSet = preparedStatement.executeQuery();
if(resultSet.next())
return true;
else
return false;
I am able to perform this query successfully.
However, if I create / modify a table, changes does not show up in SQlite DB (I am viewing db in sqLite browser). If I copy paste the same query in SQlite browser, the query runs successfully and a row is added.
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
String query = "INSERT INTO COMPANY (ID,NAME,AGE) VALUES (3, 'tOM', 32);";
preparedStatement = connection.prepareStatement(query);
preparedStatement.executeUpdate();
Am I missing something?
EDIT: Both the above tables exist in my sqlite db. Both were created through sqlite browser
EDIT2: I was getting true from my example 1 above, that's why I felt that I am able to read from db. I update my code to print the data read and nothing gets printed which means I am not able to read the data as well:
resultSet = preparedStatement.executeQuery("SELECT * FROM test1");
and
private static void outputResultSet(ResultSet rs) throws Exception {
ResultSetMetaData rsMetaData = rs.getMetaData();
int numberOfColumns = rsMetaData.getColumnCount();
for (int i = 1; i < numberOfColumns + 1; i++) {
String columnName = rsMetaData.getColumnName(i);
System.out.print(columnName + " ");
}
System.out.println();
System.out.println("----------------------");
while (rs.next()) {
for (int i = 1; i < numberOfColumns + 1; i++) {
System.out.print(rs.getString(i) + " ");
}
System.out.println();
}
}
The connection string is:
Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:C:\\Users\\akshay\\sqlite_test.sqlite");
conn.setAutoCommit(true);
return conn;
I've learned some MySQL recently and now I'm trying to work with a database in Java.
Today I've faced a problem of retrieving data from the whole column.
I already know, that if i do like:
ResultSet res = st.executeQuery("SELECT * FROM table_name WHERE id = n");
I get the whole raw. And then using
ResultSetMetaData metadata = res.getMetaData();
int colCount = metadata.getColumnCount();
while (res.next()) {
for (int i = 1; i <= colCount; i++){
String colValue = res.getString(i);
System.out.println(colValue);
}
}
I can sysout all values of the columns of this raw.
Now I have this
ResultSet res = st.executeQuery("SELECT column_name FROM table_name");
So I get one column and I need to iterate through it and sysout all the values.
Thanks in advance! :)
You can do
while (res.next()) {
String colValue = res.getString("column_name");
System.out.println(colValue);
}
And it will grab the String value from that row of the result set.
You can directly try, if you don't know the column count then use
ResultSetMetaData metadata = res.getMetaData();
So just execute like
ResultSet res = st.executeQuery("SELECT column_name FROM table_name");
while (res.next()) {
String colValue = res.getString(1);
//-------------OR--------------
String colValue2 = res.getString("column_name");
System.out.println(colValue);
System.out.println(colValue2);
}
String [] tableTypes = { "TABLE" };
DatabaseMetaData md = (DatabaseMetaData) dbConnection.getMetaData();
ResultSet rs = md.getTables(null, null, "%", tableTypes);
while (rs.next()) {
System.out.println(rs.getString(3));
}
Im using this part of the code to get all tables from my local oracle database but I need to change it in order to get back only the tablet that have only one primary key. Any ideas?
You could use DatabaseMetaData.getPrimaryKeys() for each table in that loop:
String [] tableTypes = { "TABLE" };
DatabaseMetaData md = dbConnection.getMetaData(); // the cast is unnecessary!
ResultSet rs = md.getTables(null, null, "%", tableTypes);
while (rs.next())
{
String schema = rs.getString(2);
String table = rs.getString(3);
ResultSet pkRs = md.getPrimaryKeys(null, schema, table);
int colCount = 0;
while (pkRs.next())
{
colCount ++;
}
pkRs.close();
if (colCount = 1)
{
System.out.println("Table " + table + " has a single column primary key");
}
}
However, this will be awfully slow. Using a query that retrieves this information directly from user_constraints and user_cons_columns is going to be a lot faster:
select col.table_name, count(*)
from user_constraints uc
join user_cons_columns col
on col.table_name = uc.table_name
and col.constraint_name = uc.constraint_name
where constraint_type = 'P'
group by col.table_name
having count(*) = 1;
You can use this code :
static Statement statement = null;
static ResultSet result = null;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
try {
Class.forName(driverClassName);
dbConnection = DriverManager.getConnection(url, username, passwd);
statement = dbConnection.createStatement();
String[] tableTypes = {"TABLE"};
DatabaseMetaData dbmd;
dbmd = dbConnection.getMetaData();
result = dbmd.getTables("%", username, "%", new String[]{tableTypes[0]});
while (result.next()) {
String tableName = result.getString("TABLE_NAME");
ResultSet tempSet = dbmd.getPrimaryKeys(null, username, tableName);
String keyName="";
int counter=0;
while (tempSet.next()) {
keyName = tempSet.getString("COLUMN_NAME");
counter++;
}
if(counter == 1) {
System.out.println(tableName);
}
}
} catch (Exception e) {
}
}
Table can have up to one primary key. This primary can be compound - i.e. consisting of multiple columns. The other (2nd) key might be UNIQUE (+ not NULL) which is not exactly the same as primary.
Best way how to check columns is to query ALL_CONTRAINTS view. JDBC method DatabaseMetaData has only limited functionality.