We are using SQL Server 2016 with a linked server to zDB2 (mainframe) via Microsoft OLE DB Provider for DB2 Version 5.0.
When executing a failing SQL statement remote on a linked server (zDB2) the error description is clear in SQL studio but useless in Java.
Example of statement (missing schema name):
EXEC (N'UPDATE TABLENAME SET COLUMN1=''SOMEVALUE'' WHERE COLUMN2= ''032'' ') AT ZDB2
Gives the following result in SQL Studio:
OLE DB provider "DB2OLEDB" for linked server "ZDB2" returned message "DB2GRP.TABLENAME IS AN UNDEFINED NAME SQLSTATE: 42704, SQLCODE: -204".
Msg 7215, Level 17, State 1, Line 6
Could not execute statement on remote server 'ZDB2'.
But the following result in a Java SQLException:
com.microsoft.sqlserver.jdbc.SQLServerException: Could not execute statement on remote server 'ZDB2'.
SQL State: S0001
SQL Error code: 7215
Using a debugger and inspecting the SQL Exception object, it seems the SQLException has no other data on the error.
How can I get a more useful explanation out of the SQLException on what went wrong besides "Could not execute statement on remote server" ?
And where is the documentation of what S0001 and 7215 means ? (I already googled)
Thank you in advance.
I believe the S0001 and 7215 are responses back from the Microsoft JDBC driver. The DB2 error info is "SQLSTATE: 42704, SQLCODE: -204" which is unfortunately not showing up in the Java output. It looks like the Microsoft driver is substituting it's own sqlstate/code instead of passing along DB2's.
The -204 is "name is an undefined name" (as is stated in the text before the sqlstate and code).
http://www.ibm.com/support/knowledgecenter/SSEPEK_10.0.0/codes/src/tpc/db2z_n.html
Since you mention Java code, note that DB2 provides a JDBC driver for direct connectivity. That should at least eliminate the possibility of the MS driver interfering with the error codes returned by DB2. You typically have to get the driver and license file from your systems guys--AFAIK, they aren't publicly provided by IBM but they are included with DB2 for z/OS. But I'd recommend trying to use the IBM driver unless there's some compelling reason why you have to use the Microsoft driver--I am confused about the mention of both OLE DB Provider and JDBC.
Apparently errors from a linked server are stored as warnings on the statement rather than part of the SQLException when using Microsofts JDBC Driver.
This is how i did it:
try{
...
} catch (SQLException e) {
SQLWarning sqlWarning = currentStatement.getWarnings();
if (sqlWarning != null) {
warning = sqlWarning.getMessage();
}
}
Related
I am trying to connect to database using DB2JDBC Type 2 driver. Below is my java code
try
{
String urlPrefix = "jdbc:db2:";
String url = urlPrefix + paramString1;
String user = paramString2;
String password = paramString3;
log.debug(context, 1010, "Connecting to : " + paramString1);
Class.forName("COM.ibm.db2.jdbc.app.DB2Driver").newInstance();
localConnection = DriverManager.getConnection(url, user, password);
localConnection.setAutoCommit(false);
I have added db2java.zip to my calss path and db2jdbc.dll is available in C:\Program Files (x86)\IBM\SQLLIB\BIN(Prior to this error I faced db2jdbc.dll not found error)
When I run my code am getting java.sql.SQLException: No suitable driver exception. What am I missing. Should I check the versions of the driver I have downloaded.
DB2 JDBC Type 2 Driver is discontinued since Db2 10.1.
Resolution
Use the IBM Data Server Driver for JDBC and SQLJ instead of the DB2
JDBC Type 2 Driver. Refer to the task Upgrading database applications
and subtask Upgrading Java applications that use DB2 JDBC Type 2
driver.
If you use the DB2 JDBC Type 2 Driver to compile your Java
applications or routines, you will receive an error as the driver
cannot be found.
Java package names are class sensitive. The "COM" needs to be in lowercase:
Class.forName("com.ibm.db2.jdbc.app.DB2Driver").newInstance();
// Here--------^
Can anyone offer a clue on how to diagnose the error listed below? Note, I CAN connect to this DB2 instance via DB2 connect, but not thru jdbc.
org.apache.openjpa.persistence.PersistenceException: Unable to open a test
connection to the given database. JDBC url = jdbc:db2://dxxx_xxx.xxx.com:5000/XXXXX:deferPrepares=false, username = NNNNN. Terminating connection pool. Original Exception: ------
com.ibm.db2.jcc.am.SqlSyntaxErrorException: [jcc][10165][10051][3.63.75] Invalid database URL syntax: jdbc:db2:/dxxx_xxx.xxx.com:5000/XXXXX:deferPrepares=false. ERRORCODE=-4461, SQLSTATE=42815
at com.ibm.db2.jcc.am.fd.a(fd.java:679)
at com.ibm.db2.jcc.am.fd.a(fd.java:60)
at com.ibm.db2.jcc.am.fd.a(fd.java:85)
at com.ibm.db2.jcc.DB2Driver.tokenizeURLProperties(DB2Driver.java:911)
at com.ibm.db2.jcc.DB2Driver.connect(DB2Driver.java:408)
at java.sql.DriverManager.getConnection(DriverManager.java:571)
at java.sql.DriverManager.getConnection(DriverManager.java:215)
at com.jolbox.bonecp.BoneCP.obtainRawInternalConnection(BoneCP.java:256)
at com.jolbox.bonecp.BoneCP.<init>(BoneCP.java:305)
at com.jolbox.bonecp.BoneCPDataSource.maybeInit(BoneCPDataSource.java:150)
The error message is pretty self-explanatory:
Invalid database URL syntax
You must not have any spaces in the URL, and key-value pairs are separated with semicolons, not commas. Note that you must put a semicolon after the last value too.
jdbc:db2://dxxx_xxx.xxx.com:5000/XXXXX:deferPrepares=false;username=NNNNN;
Details can be found in the manual.
Take a look at this information taken from the DB2 documentation (added link of the reference below).
Message text: text-from-getMessage
Explanation: The specified value is invalid or out of range.
User response: Call SQLException.getMessage to retrieve specific information about the problem.
SQLSTATE: 42815
Reference: https://www.ibm.com/support/knowledgecenter/SSEPGG_9.7.0/com.ibm.db2.luw.apdv.java.doc/src/tpc/imjcc_rjvjcsqc.html
One of our customers is trying to connect to an Oracle database with the following JDBC URL:
jdbc:oracle:thin:#(DESCRIPTION=(FAILOVER=ON)LOAD_BALANCE=OFF)(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=server1.domain.com)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=server2.domain.com)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=FOO)))
They get this error:
Caused by: oracle.net.ns.NetException: NL Exception was generated
at oracle.net.resolver.AddrResolution.resolveAddrTree(AddrResolution.java:614) ~[ojdbc5_11g-11.2.0.1.0.jar:11.2.0.1.0]
at oracle.net.resolver.AddrResolution.resolveAndExecute(AddrResolution.java:411) ~[ojdbc5_11g-11.2.0.1.0.jar:11.2.0.1.0]
at oracle.net.ns.NSProtocol.establishConnection(NSProtocol.java:672) ~[ojdbc5_11g-11.2.0.1.0.jar:11.2.0.1.0]
at oracle.net.ns.NSProtocol.connect(NSProtocol.java:237) ~[ojdbc5_11g-11.2.0.1.0.jar:11.2.0.1.0]
at oracle.jdbc.driver.T4CConnection.connect(T4CConnection.java:1042) ~[ojdbc5_11g-11.2.0.1.0.jar:11.2.0.1.0]
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:301) ~[ojdbc5_11g-11.2.0.1.0.jar:11.2.0.1.0]
Questions:
I've never seen such a connection URL before. It looks more like an entry in TNSNAMES.ORA. How can I find out what this connection string means?
What could be causing this useless error message?
The syntax is the 'Oracle Net connection descriptor syntax', see table 8.3 in the JDBC Developers Guide.
The syntax is indeed the same as the syntax used in tnsnames.ora; this syntax is described in the Oracle Database Net Services Reference.
As to the specific issue, it looks to me like you have unbalanced parentheses in the descriptor, specifically:
(FAILOVER=ON)LOAD_BALANCE=OFF)
Should be:
(FAILOVER=ON)(LOAD_BALANCE=OFF)
(note the additional (.)
I generated the following connection URL from your tnsnames entry :
jdbc:oracle:thin:#server1.domain.com:1521/FOO
try to use the above connection URL.
Also do check if the listener is up and running :
in windows : ctrl + r, services.msc, check whether service : "Oracle*TNSListener" is started.
jdbc:oracle:thin:#(DESCRIPTION=(FAILOVER=ON)LOAD_BALANCE=OFF)(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=server1.domain.com)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=server2.domain.com)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=FOO)))
So Google Cloud SQL has a neat feature where you should be able to connect to your local DB instance for debugging locally as described here:
I've got the following VM arguements:
-Xmx512m -javaagent:C:\eclipse\plugins \com.google.appengine.eclipse.sdkbundle.1.4.2_1.4.2.v201102111811\appengine-java-sdk-1.4.2\lib\agent\appengine-agent.jar
-Drdbms.server=local
-Drdbms.driver=com.mysql.jdbc.Driver
-Drdbms.url=jdbc:mysql://localhost:3306/testdb?user=root&password=pass
I've put the msql driver in the C:\eclipse\plugins \com.google.appengine.eclipse.sdkbundle.1.4.2_1.4.2.v201102111811\appengine-java-sdk-1.4.2\lib\impl folder and added it to the class path.
However when running a simple SELECT query (and this runs fine when deployed on GAE) it tosses the following exception.
java.sql.SQLException: Table not found in statement [SELECT * FROM SOME_TABLE]
Here's the offending code snippet:
Connection c = null;
try {
DriverManager.registerDriver(new AppEngineDriver());
c = DriverManager.getConnection(MY GOOGLE CLOUD SQL CXN STRING);
PreparedStatement ps = c.prepareStatement("SELECT * FROM SOME_TABLE");
ResultSet rs = ps.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
I suspect it's not realizing it has to connect locally, what should I be checking?
Just to mark this as answered: solution provided by Dave W. Smith above
From Dave W. Smiths comment:
I don't know how significant this is to the problem at hand, but 1.4.2
is pretty far out of date.
I am trying to write a simple Java
client program that uses koi8r as its character set, and keep on failing.
Class.forName("com.mysql.jdbc.Driver");
Connection conn2 = DriverManager.getConnection ("jdbc:mysql://localhost:3306/test","root",null);
Statement stmt = conn2.createStatement();
int result;
result = stmt.executeUpdate("SET CHARACTER SET koi8r");
stmt = conn2.createStatement();
result = stmt.executeUpdate("DROP TABLE IF EXISTS װֱֱֲֳֹּ, t1, t2");
stmt.close();
assertEquals(0, result);
I'm getting
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '???????, t1, t2' at line 1
When I put these commands in a script file and execute them using MySql client it works fine
SET CHARACTER SET koi8r
DROP TABLE IF EXISTS װֱֱֲֳֹּ, t1, t2
I sniffed the network and I saw the the jdbc connector sends it with ?????? to the server, so I guess I'm missing some setting to the connection.
Actually I tried (setEncoding, setCharactersEncoding, setConncetionCollation ...), but still failed.
You need to tell the JDBC driver which encoding it should use to transfer the characters over network. It namely defaults to platform default encoding which is in your case apparently not UTF-8.
You can do this by adding the following two query parameters to the JDBC URL:
jdbc:mysql://localhost:3306/test?useUnicode=yes&characterEncoding=UTF-8
See also the documentation.