JDBC joins across two MySQL databases on the same server? - java

Basically I need to run the following query through jdbc. Both databases are MySQL and on the same server.
SELECT * FROM DB1.ACCOUNT a
JOIN DB2.ITEM i ON a.AccountID = i.AccountID
My jdbc connection is set up like this:
Class.forName("com.mysql.jdbc.Driver").newInstance();
DB1 = DriverManager.getConnection("jdbc:mysql://serverloc.com:3300/DB1", "username", "password");
DB2 = DriverManager.getConnection("jdbc:mysql://serverloc.com:3300/DB2", "username", "password");
This is where I run into problems. I can now create a statement against DB1 or DB2, but I can't find a way to JOIN against both databases. I've tried running my query against one of the databases (below) but that returns null.
Statement statement = DB1.createStatement();
ResultSet resultSet = statement.executeQuery(" QUERY HERE ");
I've seen that you can use UnityJDBC to run JOIN queries across DB's, but I'm looking for a free/open source option.
Thanks!

1) Yes, you can "join" between two different databases in mySQL.
2) No, you don't need two different connections to do it.
For example:
http://www.webhostingtalk.com/showthread.php?t=476982
p2.upc_code FROM db1.products p1 LEFT OUTER JOIN db2.products p2 ON p1.prod_id=p2.prod_id";

Related

Compare tables on different servers

Using java and SQL Server 2008, I need to compare the content of two tables, the thing to bear in mind is that they are on different servers so I have a connection to the first server (lets call it conn1) and a connection to the second server (lets call it conn2).
I copy the tables into temp tables and then attempt to use the EXCEPT operator to compare the temp tables.
A very basic example of trying to do this in java:
String s1 = "select * into #temp1 from FACTOR";
String s2 = "select * into #temp2 from FACTOR'";
String s3 = "SELECT * FROM #temp1 EXCEPT SELECT * FROM #temp2";
Statement st = null;
ResultSet rs = null;
st = conn1.createStatement();
st.execute(s1);
Statement st1 = null;
ResultSet rs1 = null;
st1 = conn2.createStatement();
st1.execute(s2);
Statement st3 = null;
ResultSet rs3 = null;
st3 = conn2.createStatement();
rs3 = st3.executeQuery(s3);
I'm getting the following error on the last line in the above code snippet:
Stack trace:java.sql.SQLException: Invalid object name '#temp1'.
Is it because I'm using the two connections to the different servers, conn2 can't see #temp1?
Any ideas how I could acheive what I'm trying to do?
Thanks.
What you are trying to do doesn't make sense. Remember that the SQL gets executed on the SQL Server, not in Java. So if the 2 SQL Servers cant see each other, you cant execute queries across SQL Servers that cant see each other.
One solution is to execute the queries on both the servers, and get the data into Java ResultSet, and then process the data in java.
alternatively, copy all the data to one SQL Server, and do your EXCEPT query on that Server
If the SQL Servers can "see" each other, then you can do the whole thing from one connection:
"SELECT * FROM Server1.database.schema.FACTOR
EXCEPT
SELECT * FROM Server2.database.schema.Factor"
I would suggest listing the column names in case they change in the future.
Normal Temp tables are only visible to the connection they are used within. Global temp tables denoted by'##' instead of '#' are visible to multiple connections but disappear when the connection that created them is closed.
This would be better done in a stored procedure using a linked server. e.g.
CREATE PROCEDURE uspCompareTables
AS
BEGIN
select * from Factor
EXCEPT
select * from OTHER_SERVER.dbo.Factor
END
Then you can just call it from your java application. using the normal...
exec uspCompareTables

Connecting to Oracle with JDBC causes queries to return zero rows.

So I have been playing around with querying databases using the standard
Statement s = connection.createStatement();
ResultSet rs = s.executQuery(queryString);
ResultSetMetadata rsmd = rs.getMetaData();
while(rs.next)){
String code = "";
String value = "";
for(int i = 1; i <= rsmd.getColumnCount(); i++){
Object obj = rs.getObject(i);
if(i == 1){
code = obj.toString():
}
else{
label = obj.toString();
}
}
//Store code and labels in map
}
...go on to close statement and move on.
I am trying to select two columns from a table in each instance.
For the most part this works well. When working with MySql & Microsoft Sql databases I get a result set full of data in the table. However when I try to do this with an Oracle database I get an empty result set.
I have tested my query string in the SQL Developer application and it works fine, returns my data. But the result set doesnt contain anything. The resultSet metadata says that it has two columns though. Is there anything I need to do when interacting with an Oracle Database that is different from the other two? Thanks.
If your query works when you run it against the Oracle database, and you know the code works since you've run it against MySQL, then some other things to try are:
1.) Make sure your JDBC connection URL is correct. Are you sure you are connecting to the database that you intend to? (i.e. - the one that would return the rows you expect?)
2.) Take into account credentials. Make sure you are using the same credentials through JDBC that you are when connecting to Oracle directly.
3.) Make sure both connections are being made from the same machine and with the same environment. Oracle drivers rely on environment variables to find a file (I believe it is called tnsnames.ora, or something like that) that contains the alias & connection info. Getting different versions of that file could point you to different Oracle instances.
4.) Try manually specifying your schema name in the query. So instead of select * from my_table use select * from my_schema.my_table. Sometimes Oracle clients will configure their sessions to have default schemas set up in their preferences.
5.) If your are attempting to select data that you've inserted with your Oracle client, make sure you've committed the transaction in your Oracle client so that the data is visible to other sessions.
One last debugging tool to use is to try connecting via the Squirrel DB client. Squirrel is a 100% pure java SQL client that connects to any DB using JDBC. It would be a good test to make sure your JDBC Driver, Connection URL, etc. are all valid.
The database table has records but the JDBC client can't retrieve the records. Means the JDBC client doesn't have the select privileges. Please run the below query on command line:
grant all on emp to hr;

JDBC:is it possible to execute multi-database Querys in java?

I want to execute an sql-query over 2 databases using java
but have some problems finding out how to do it without writing everything by myself
maybe someone has an idea how to do it.
example:
database1
table1(names): id,Name,zip,something
database2
table2(towns): id,townname,zip
SELECT *
FROM database1.names, database2.towns
WHERE database1.names.zip = database2.towns.zip
the example works in mysql when i use phpMyAdmin and the User has rights on both databases
edit:
The question is: How do i get Java to execute such a query since i can only connect to one database(?)
or: How can I connect to 2 Databases executing an Sql Query that uses tables from both databases using java.
the way i execute sql commands in java looks like:
Connection c = DriverManager.getConnection("jdbc:mysql://localhost/database?user=root&password=");
PreparedStatement pstmt = c.prepareStatement("Select * from something");
pstmt.executeQuery();
but i cant use that to get a Sql Query that uses tables from 2 databases?
Assuming that these databases are not visible from the same datasource, you have to use a mediation software to query on them, such as http://www.unityjdbc.com/doc/multiple/multiplequery.php.
It's not a trivial problem, since your "SQL" will have to deal with each datasource availability and transaction.
Some DB vendors provide some sort of dblinks (e.g. http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_5005.htm) that help you a little to deal with heterogeneous DBs.
So it would be nice if you narrow your question to what DBMSs you are interested.

different results from query in java code and on oracle db server: but no connection error

I have java code that connects to a remote oracle 11g EE db server. If i run a particular query in sqlplus it returns one result
SQL> SELECT COURSENAME from COURSES where skillID=1;
COURSENAME
--------------------
basic
But if I run the same query from the java code below it returns no results. I can copy the query syntax out of the query variable in the java debugger and running it on oracle so I know there is no syntax issue with the query. Also, it is not SQL exceptions or class not found exceptions so it seems to be running the query successfully -- just returning zero results.
What might be going on?
private String getCourseForSkill(int skillID){
try{
Class.forName("oracle.jdbc.OracleDriver");
String query="SELECT COURSENAME from COURSES where skillID=" + skillID ;
con = DriverManager.getConnection(url, user, password);
Statement stmt = con.createStatement();
rs = stmt.executeQuery(query);
rs.next();
return rs.getString("COURSENAME");
}
catch (ClassNotFoundException ex){
System.out.println(ex.getMessage());
}
catch (SQLException ex) {
System.out.println(ex.getMessage());
}
return null;
}
I think you're connecting to different Oracle instances, or more likely, as different Oracle users in the two cases
#GreyBeardedGeek the URL looks like "jdbc:oracle:thin:#website:port:orcl I get to the manual query by doing ssh#website, authenticating and then running command=sqlplus
Safer to run sqlplus <username>/<password>#<orainstancename>, because you can explicitly specify the oracle instance ID. In your case, it seems your program is using jdbc connection jdbc:oracle:thin:#website:port:orcl, so your orainstancename would be 'orcl' - just ensure that your tnsnames.ora file has the instance 'orcl' with the same 'port' as used by the jdbc connection
How to debug a little more
Run the following code:
con = DriverManager.getConnection(url, user, password);
con.setAutoCommit(false);
String insert="INSERT INTO COURSES (SKILLID, COURSE)"+ // can add other columns
"values (?, ?) );" // add ? for other columns
PreparedStatement ps = con.createPreparedStatement();
ps.setInt(1, 999);
ps.setString(2, "Complete Bullwarks");
// can set other columns
ps.executeUpdate(insert);
con.commit();
NOW connect manually, re-run your original select statement & see if the added row is there. If no error in java and no new row in Oracle: extremely likely you're using 2 different Oracle instances/schemas.
ALSO rerun your original java select code, but with SkillID=999 - extremely likely it will work.
Cheers
I had to do a commit to add the rows. When I typed commit; into the sql plus terminal then the remote jdbc connection could 'see' the rows. I am used to SQL server where you don't have to explicitly do these kinds of commits when using linq-to-sql or sql management studio.
It can be three issues.
1) skillID <> 1 in your Java code. Add debug and check.
2a) You are connecting to another database.
2b) You are connecting to the same database but SELECTING from a table in another schema.
To check 2a and 2b:
select user from dual; -- connect username
select name from v$database; -- database name
select host_name from v$instance; -- host name database is running on
This query returns all three into one result.
select user || '' || d.name || '' || i.host_name
from v$database d, v$instance i;
Assuming you are actually connecting to the same database this is caused by not committing the INSERT in the sql*plus connection.
Oracle by default does not run in auto-commit mode when connecting via OCI (which sql*plus uses to connect). Any DML(INSERT ...) executed in sql*plus will not be visible to any other session until it is committed. This is because Oracle provides a read committed isolation level by default. The only thing visible to other users across sessions are write locks.
It doesn't matter if you connect the second connection via JDBC or OCI, it won't see the changes till you commit the first connection.
To test this out try opening 2 sql*plus connections and run the following:
-- Executing DDL in Oracle causes an implicit commit before and after the
-- command so the second connection will see the existence of this table:
CREATE TABLE foobar ( x VARCHAR(1) );
Execute this in connection #1 - you should get zero (we haven't inserted anything yet):
SELECT COUNT(*) FROM foobar;
Execute this in connection #2:
INSERT INTO foobar ( x ) VALUES ( 'A' );
Execute this in connection #1 - you should still get zero (INSERT is not committed so connection #1 cannot see it):
SELECT COUNT(*) FROM foobar;
Execute this in connection #2:
COMMIT;
Execute this in connection #1 - you should get 1 (it's committed now):
SELECT COUNT(*) FROM foobar;

Migrate data from old MySQL database

I recently rewrote a Java EE web application (running on a MySQL database) to Rails 3.1. The problem now is that the database model of the new application is not the same as the old one because I added, removed and renamed some attributes. The database table names are also different.
Is there a way of migrating this data? The only way I can imagine to do this is writing a stored procedure with many ALTER TABLE and CREATE TABLE statements to update the database to the new model.
Thanks in advanced.
Solution:
I finally used INSERT..SELECT statements in a mysql stored procedure to migrate the data. INSERT INTO new_schema.new_table SELECT FROM old_schema.old_table. I am now considering making a Rake task to call that procedure and doing other stuff.
The only way is to write a script that take the data from the old db and insert thme in the new db. Or you can in some way to connect to the two databases and then make some select and insert query, something like
insert into new_db.table as select old_db.table.field1, ....
or
insert into new_db.table (field_1, field_2) values (select old_db.table.field_1, ...)
In any way, is a manual process, also if can be automated to some extend with a script
Instead of a Store procedure you can try with rails and some sql within the rails console using the information_schema of mysql
sql = ActiveRecord::Base.connection()
old_tables = sql.execute "select table_name from information_schema.tables where table_schema = your_old_schema"
res.each do | old_table|
old_fields = sql.execute "select distinct column_name, data_type from information_schema.columns where table_name='#{old_table}' and table_schema='your_old_schema'"
new_fields = sql.execute "select distinct column_name, data_type from information_schema.columns where table_name='#{old_table}' and table_schema='your_new_schema'"
#compare fields and so on...
end

Categories

Resources