Compare tables on different servers - java

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

Related

Java prepared statement does not allow large strings in the where clause of the query

I am trying to retrieve data from DB2 using Java prepared statement
String select_statement = "SELECT * FROM schema_name.table_name where NME='xxx002' and LINE =7200 and FILE_NME='720001042021XYZ002' with ur";
try (Connection connection = DataBaseConnection.getGeoCarDBConnection_TESTDATA();
PreparedStatement ps = connection.prepareStatement(select_statement);) {
ResultSet rs = null;
rs = ps.executeQuery();
}
The problem I am facing is that I include the FILE_NME in the where clause of the query, as shown above, 0 rows are returned. But any other string fields can be passed and I get the desired number of rows.
Any integer fields in the where clause works too.
But only the string fields that are large(In this case, FILE_NME field) are not working. In the DB2 table, where I am pulling the data from, the FILE_NME field is of varchar(30).
Things that did not work for me was
String select_statement = "SELECT * FROM schema_name.table_name where NME='xxx002' and LINE =7200 and FILE_NME = ? with ur";
then I set the String value using,
ps.setString(1, "'720001042021XYZ002'")
ps.setString(1, "720001042021XYZ002")
Both did not work.
None of the google links were helpful. Have spent more than a day on it.
This code used to work flawlessly before, Even the java version hasn't changed(as per my knowledge)
I am running it in windows 10.
Java version : 1.8 ((build 1.8.0_221-b11))
I run the same query in the database client and it works.
Someone please help me or point me in the right direction. I don't know what I am missing
Thank in advance
The problem was that there was indeed no data, I was checking the same query in the database client in a different environment. I am closing this.

Slow queries with preparedStatement but not with executeQuery

I'm having a weird problem with an Grails application accessing data. Going deeper I've isolated the problem to a plain java8 small application using PreparedStatement.executeQuery vs Statement.executeQuery.
Consider the following snippet of code:
// executes in milliseconds
directSql = "select top(10) * from vdocuments where codcli = 'CCCC' and serial = 'SSSS' ORDER BY otherField DESC;";
stmt = con.createStatement();
rs = stmt.executeQuery(directSql);
// More than 10 minutes
sqlPrepared = "select top(10) * from vdocuments where codCli = ? and serial = ? ORDER BY otherField DESC;";
PreparedStatement pStatement = con.prepareStatement( sqlPrepared );
pStatement.setString(1, "CCCC");
pStatement.setString(2, "SSSS");
rsPrepared = pStatement.executeQuery();
Same query.
Data comes from a view on SqlServer (2008, I think, have no access right now) from a table with more than 15 Million records. There are indexes for all needed fields and the same query (the first one) executed from console runs also quite fast.
If I execute the slow PreparedStatement query without the ORDER clause it also runs fast.
It looks clear to me that for any cause the database it's not using indexes and make a full scan when using preparedStatement, but maybe I'm wrong so I'm open to any idea.
I thought maybe the driver (sqlserver official latest and jtds has been tested) was holding the data waiting for any kind of EOF from connection but I've checked with tcpdump on my side and no data is received.
I can't find why this is happening so any idea will be welcomed.
Thank you in advanced!
I've finally found a solution, at least in for my case. I got it here http://mehmoodbluffs.blogspot.com.es/2015/03/hibernate-queries-are-slow-sql-servers.html . Telling (driver? sqlServer?) not to send parameters as Unicode have resolved the problem.
Current connection string it's now:
String connectionUrl = "jdbc:sqlserver://server:port;databaseName=myDataBase;sendStringParametersAsUnicode=false";
And now both direct queries and preparedStatements runs at millisecond speed.
Thank you #DanGuzman for your suggestions!

How to query SQL Server CDC through JDBC incrementally

I am trying to incrementally read SQL Server CDC changes.
In my first interval, I query
Statement statement = connection.createStatement();
String queryString = "SELECT * FROM cdc.fn_cdc_get_all_changes_dbo_mytable(sys.fn_cdc_get_min_lsn('dbo_mytable'), " +
"sys.fn_cdc_get_max_lsn(), 'all') ORDER BY __$seqval";
ResultSet rs = statement.executeQuery(queryString);
Now I know that __$start_lsn is an LSN (Log Sequence Number) in binary(10). Although I don't understand how I can read it as a Java type so that I can include it my next query and how should I create my next query where I will like to specify the min_lsn as the last LSN which I processed.
You can use several options for retrieving the data from the ResultSet
Then for creating a new query, look at using a a PreparedStatement. There are several options for setting the data based on the type that you you pulled out of the initial query.

Connect to a SQL Server database

I am trying to connect to a SQL Server database, but I don't really know how to go about it using the info I was given. I was given the following:
Provider
DataSource
Persist Security Info
User ID
Initial Catalog
I have always connected via a web address or something, so I didn't really know how to go about using this. I am attempting to do this is Java using JDBC.
See here a wide list of examples, depending on which version you're using:
SQL Server 2000
SQL Server 2005
SQL Server 2008
To connect to MSSQL Server from a Java application, you need to use the JDBC API. The JDBC API provides classes and methods that connect to the database, load the appropriate driver, send SQL queries, retrieve results etc.
HOW TO CONNECT TO THE DATABASE: A ‘Connection’ object represents a connection with a database. To establish the connection, use the method ‘DriverManager.getConnection’. This method takes a string containing a URL which represents the database we are trying to connect to. Below is the sample code for establishing a connection:
private String DATABASE_URL = "jdbc:odbc:embedded_sql_app"; // establish connection to database
Connection connection = DriverManager.getConnection( DATABASE_URL,"sa","123" );
Detailed discussion about the Database URL and how to create it can be found in the resource provided at the end of this post.
QUERYING THE DATABASE: The JDBC API provides three interfaces for sending SQL statements to the database, and corresponding methods in the ‘Connection’ interface create instances of them. 1. Statement - created by the ‘Connection.createStatement’ methods. A ‘Statement’ object is used for sending SQL statements with no parameters.
2. PreparedStatement - created by the ‘Connection.prepareStatement methods’. A ‘PreparedStatement’ object is used for precompiled SQL statements. These can take one or more parameters as input arguments (IN parameters).
3. CallableStatement - created by the ‘Connection.prepareCall’ methods. ‘CallableStatement’ objects are used to execute SQL stored procedures from Java database applications.
RETRIEVING THE RESULT: A ‘ResultSet ‘is a Java object that contains the results of executing a SQL query. The data stored in a ‘ResultSet’ object is retrieved through a set of get methods that allows access to the various columns of the current row. The ‘ResultSet.next’ method is used to move to the next row of the ‘ResultSet’, making it the current row. The following code fragment executes a query that returns a collection of rows, with column ‘a’ as an ‘int’, column ‘b’ as a ‘String’, and column ‘c’ as a ‘float’:
java.sql.Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (rs.next()) { // retrieve and print the values for the current row
int i = rs.getInt("a");
String s = rs.getString("b");
float f = rs.getFloat("c");
System.out.println("ROW = " + i + " " + s + " " + f);
}
This is just a brief introduction on how to interact with a database from Java. For more details on the items discussed above as well as information on passing parameters, executing stored procedures etc. please refer to the following resource: ( http://www.shahriarnk.com/Shahriar-N-K-Research-Embedding-SQL-in-C-Sharp-Java.html#Shahriar_N_Embedding_SQL_in_Java ) Here, you will also find information on how to interact with a database programmatically; i.e. without using SQL. Hope you find this useful.
Source:
http://www.shahriarnk.com/Shahriar-N-K-Research-Embedding-SQL-in-C-Sharp-Java.html

How do I retrieve data from multiple tables (PostgreSQL) in Java Servlet?

I having difficulties on retrieving data from multiple tables. It is going to be a search form and its a relational database.
Question1: How do I retrieve data from multiple tables now?
Question2: At the same time another problem I face is that I can not get any results if I try to search only by Name or Lastname. I get results only when I use date of birth. Why?
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
java.io.PrintWriter out = response.getWriter();
Connection conn = null;{ // while there is no connections, proceed to the next step
try {
Class.forName("org.postgresql.Driver"); // importing the driver to use the getConnection method
conn = DriverManager.getConnection(
"jdbc:postgresql://localhost:5432/caglar", "postgres", //?searchpath=cag
"abracadabra");
System.out.println("Connected to the database"); // console message
String agent_name = request.getParameter("givenname"); // variable - reads from user input
String agent_lastname = request.getParameter("familyname"); // variable - reads from user input
String dob = request.getParameter("birthyear"); // variable - reads from user input
ArrayList al=null;
ArrayList agent_list =new ArrayList();
//Problem 1: If dob is not given, it is not searching by name or lastname.
//String query = "select * from agent where givenname='"+agent_name+"' or familyname='"+agent_lastname+"' or birthyear='"+dob+"' order by givenname";
String query = "select * from agent where givenname='"+agent_name+"' or familyname='"+agent_lastname+"' ";
if(dob!=null && !"".equals(dob)) // if date of birth fiel is left blank, it will still proceed to the results page
query = query + " or birthyear='"+dob+"'"; // if date of birth exists, it will take it into account as well
query = query+ "order by givenname"; // ordering by first name
System.out.println("query" + query); // console message
Statement st = conn.createStatement(); // connection statement
ResultSet rs = st.executeQuery(query); // executing our query
while(rs.next())
{
al = new ArrayList();
al.add(rs.getString(1));//id
al.add(rs.getString(2));//dob
al.add(rs.getString(3));//name
al.add(rs.getString(4));//lastname
System.out.println("al :: "+al);
agent_list.add(al);
}
request.setAttribute("agentList",agent_list);
To reiterate what the others are pointing out above, this is "dangerous" code. By not using PreparedStatements, you are opening up yourself to SQL Injection attacks - by which, a malicious user can craft a SQL statement to delete all the data in a table. As #craig-ringer points above, it would be trivial submit data that would delete the table from the database.
Having pointed that out, underlined it several times and highlighted it in a fluorescent yellow mark, lets move on and try to answer your questions:
1) You can query data from multiple tables by using SQL Joins. Here's a PostgreSQL tutorial on JOINS - there are many others out there, I just picked the first one I found.
2) Without the exact data in the database, and the exact parameters being supplied, it is difficult to answer - however, I imagine that the issue is case sensitivity. Comparisons in PostgreSQL are case sensitive - so if the family name in the database is 'Smith' and the parameter is 'smith', no data will be found. So, for simplicity, you'll need to covert both the parameter and the data to the same case e.g. lower. e.g. SELECT * FROM agent where LOWER(familyname)='smith'
I'd also point out that you may run into problems with date formatting - again, this would be addressed using prepared statements.
It appears you are quite new to java, SQL and JDBC; I would suggest you try and follow some tutorials and read some books. There's quite a lot to get to grips with - good luck!

Categories

Resources