How to load large .sql script against oracle database using JDBC - java

I have a sql script for oracle database:
set define off;
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "XYZ" AS
import javax.crypto.SecretKey;
.......
import java.security.NoSuchProviderException;
public class XYZ {
.... fields
.... methods
}
/
I'm trying to execute this statement using following java code:
String createStoredProcedureSqlString = new String(Files.readAllBytes(storedProcedureSqlFile.toPath()));
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
statement.execute(createStoredProcedureSqlString);
}
After executing this code I faced with exception message:
java.sql.SQLException: Non supported SQL92 token at position: 479
I believe that this exception occurs while script contains "{" or "}" symbols. But I don't really know how to escape them and not affect script itself.
What am I doing wrong?

Related

JDBC Driver Does Not Exist

I’m trying to connect a Java program to a remote Oracle DB. After doing some research online, I decided that the easiest way to do this was with the Oracle JDBC driver. I downloaded and ran the jar file and got the message “***** JCE UNLIMITED STRENGTH IS INSTALLED *****.” The problem is that when I try to add the driver to my classpath (javac -classpath ojdbc8.jar Connect.java), I keep getting an error message saying “package oracle.jdbc.driver does not exist.” I’ve been researching how to fix this online, but I’m only getting confused. Any ideas on what I did wrong?
import java.sql.*;
public class Class1 {
public static void main (String args [])
throws SQLException
{
// Load the Oracle JDBC driver
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
// Connect to the database
// You must put a database name after the # sign in the connection URL.
// You can use either the fully specified SQL*net syntax or a short cut
// syntax as `<host>`:`<port>`:`<sid>`. The example uses the short cut syntax.
Connection conn =
DriverManager.getConnection ("jdbc:oracle:thin:hr/hr#myhostname:1521:orcl",
"myUsername", "myPassword");
// Create a Statement
Statement stmt = conn.createStatement ();
// Select the ENAME column from the EMP table
ResultSet rset = stmt.executeQuery ("select ENAME from EMP");
// Iterate through the result and print the employee names
while (rset.next ())
System.out.println (rset.getString (1));
conn.close(); // ** IMPORTANT : Close connections when done **
}
}
The error is:
java: package oracle.jdbc.driver does not exist
Can you try to run the sample DataSourceSample.java? Make sure you have the JDBC driver in the classpath. You can also refer to this quickstart for detailed instructions.

Can I run a "source" command (SQL script) from a JDBC connection?

I'm writing an application that has a data access layer to abstract the underlying connections to SQLITE3 or MySQL databases.
Thanks to some help here yesterday I was shown how to use a process builder to run a command line import into the SQLITE3 DB using output redirection.
Now I am trying to create the same database but in MySQL by importing a dump file. The load works fine from the command line client. I just tell it to source the file and the DB is created successfully.
However I am trying to do this through code at runtime and my method for executing a SQL statement fails to execute the source command.
I suspect that this is because "source" is not SQL but I don't know what else to use to try and run it.
My error message is:
java.sql.SQLSyntaxErrorException: 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 'source /tmp/ISMCoreActionPack_mysql.sql' at line 1
The failing command string:
source /tmp/ISMCoreActionPack_mysql.sql;
My method is:
public Boolean executeSqlStatement(String sql) {
Boolean rc = false;
try {
Connection connection = getConnection();
Statement statement = connection.createStatement();
rc = statement.execute(sql);
connection.close();
} catch (SQLException e) {
e.printStackTrace();
System.err.println(e.getClass().getName() + ": " + e.getMessage());
System.exit(1);
}
return rc;
}
Can anyone suggest how to do this?
You cannot run 'source' command, because it's not supported by JDBC driver, only MySQL.
My advice to you the following. Write some parser, which reads queries from a file, and executes them using JDBC statements.
source is not part of MySQL's dialect of SQL; it is a MySQL shell command. Still, you shouldn't need to write your own parser. You could use something like SqlTool as explained in this answer.

Teradata external Java Stored Procedure error: No suitable driver found for jdbc:default:connection

I wrote a Java stored procedure, packed it into a jar and installed it into the Teradata database. I want to use the default database connection as described here. Most of the code was generated by the Teradata wizard for stored procedures.
public class TestSql {
public static void getEntryById(int id, String[] resultStrings) throws SQLException {
Connection con = DriverManager.getConnection("jdbc:default:connection");
String sql = "SELECT x FROM TEST_TABLE WHERE ID = " + id + ";";
Statement stmt = (Statement) con.createStatement();
ResultSet rs1 = ((java.sql.Statement) stmt).executeQuery(sql);
rs1.next();
String resultString = rs1.getString(1);
stmt.close();
con.close();
resultStrings[0] = resultString;
}
}
I installed the jar:
CALL SQLJ.REPLACE_JAR('CJ!/my/path/Teradata-SqlTest.jar','test');
And created the procedure:
REPLACE PROCEDURE "db"."getEntryById" (
IN "id" INTEGER,
OUT "resultString" VARCHAR(1024))
LANGUAGE JAVA
MODIFIES SQL DATA
PARAMETER STYLE JAVA
EXTERNAL NAME 'test:my.package.TestSql.getEntryById(int,java.lang.String[])';
Now when I call this procedure, I get this error message:
Executed as Single statement. Failed [7827 : 39001] Java SQL Exception SQLSTATE 39001: Invalid SQL state (08001: No suitable driver found for jdbc:default:connection).
Now when I log off from Teradata and log on again and call the procedure, the error message becomes:
Executed as Single statement. Failed [7827 : 39001] A default connection for a Java Stored Procedure has not been established for this thread.).
What is the problem here? I'm connecting to Teradata using the Eclipse plugin. Teradata v. 15.0.1.01.
After many hours I finally found the problem. Eclipse packed all dependencies into the jar - which basically is ok. However it also packed the Teradata JDBC driver files (tdgssconfig.jar and terajdbc4.jar) into the result jar, which was the problem.
I adjusted the jar building process so that these files are not included and the errors went away.

How to create a HSQL in-memory-db from script file?

I have two HSQL databases in memory. With the first database I create the database structure and test data which is time-consuming. This database is exported via the SCRIPT command into a sql file. My second database (not necessarily in the same JVM) should be build from that exported sql file.
public static void main(String[] args) throws Exception {
try (Connection firstConnection = DriverManager.getConnection("jdbc:hsqldb:mem:connection1", "sa", "")) {
try (Statement statement = firstConnection.createStatement()) {
statement.execute("CREATE TABLE table1 (id INT)");
statement.execute("SCRIPT 'my.script'");
}
}
try (Connection secondConnection = DriverManager.getConnection("jdbc:hsqldb:mem:connection2", "sa", "")) {
ScriptUtils.executeSqlScript(secondConnection, new FileSystemResource("my.script"));
}
}
When invoking ScriptUtils.executeSqlScript() I get the following exception:
Caused by: java.sql.SQLInvalidAuthorizationSpecException: invalid authorization specification - already exists: SA in statement [CREATE USER SA PASSWORD DIGEST 'd41d8cd98f00b204e9800998ecf8427e']
at org.hsqldb.jdbc.JDBCUtil.sqlException(JDBCUtil.java:327)
at org.hsqldb.jdbc.JDBCUtil.sqlException(JDBCUtil.java:247)
at org.hsqldb.jdbc.JDBCStatement.fetchResult(JDBCStatement.java:1817)
at org.hsqldb.jdbc.JDBCStatement.execute(JDBCStatement.java:638)
at org.springframework.jdbc.datasource.init.ScriptUtils.executeSqlScript(ScriptUtils.java:457)
... 3 more
Caused by: org.hsqldb.HsqlException: invalid authorization specification - already exists: SA
at org.hsqldb.error.Error.error(Error.java:83)
at org.hsqldb.error.Error.error(Error.java:72)
at org.hsqldb.rights.GranteeManager.addUser(GranteeManager.java:623)
at org.hsqldb.rights.UserManager.createUser(UserManager.java:115)
at org.hsqldb.StatementSchema.getResult(StatementSchema.java:1026)
at org.hsqldb.StatementSchema.execute(StatementSchema.java:268)
at org.hsqldb.Session.executeCompiledStatement(Session.java:1378)
at org.hsqldb.Session.executeDirectStatement(Session.java:1248)
at org.hsqldb.Session.execute(Session.java:1008)
at org.hsqldb.jdbc.JDBCStatement.fetchResult(JDBCStatement.java:1809)
... 5 more
What is the correct way to export an existing in-memory-database and import it later into another (empty) in-memory-database?
The SCRIPT statements creates a full database script that can be opened as a file database. Open the second database as a file: database that does not store the modifications.
Connection secondConnection = DriverManager.getConnection("jdbc:hsqldb:file:my;files_readonly=true", "sa", "")
The problem appear to be with the script not the code running it.
The error is that its attempting to create the SA user CREATE USER SA which already exists (its the user you've authenticated with to run the script in the first place).
You should be remove (comment out) that line in the script and you should then be able to progress further.

"Parameter is not an OUT parameter" error while calling stored procedure via CallableStatement

I have been trying call procedure "proc" which were created in MySQL Workbanch:
create database test_database;
use test_database;
delimiter &&
create procedure proc(inout param INT UNSIGNED)
begin
set param = 2*param;
end&&
using this application :
package test;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
public class Test {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1", "root", "root");
connection.createStatement().execute("USE test_database");
CallableStatement callableStatement = connection.prepareCall("{call proc(?)}");
callableStatement.setInt(1, 5);
callableStatement.registerOutParameter(1, java.sql.Types.INTEGER);
ResultSet result = callableStatement.executeQuery();
if (result.first()) {
System.out.println(result.getInt(1));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}}
but i always get this error:
java.sql.SQLException: Parameter number 1 is not an OUT parameter
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1094)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:997)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:983)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:928)
at com.mysql.jdbc.CallableStatement.checkIsOutputParam(CallableStatement.java:695)
at com.mysql.jdbc.CallableStatement.registerOutParameter(CallableStatement.java:2016)
at test.Test.main(Test.java:16)
I have been trying to find out what is wrong many hours, but without success.
I saw many questions, but :
this is useless because in function cannot be transaction
this is useless because when i use named parameter NullPointerEx is throwed(why??)
this is useless because procedure exists, and dont throw any exception when i use only IN param, but with INOUT or OUT is throwed mentioned exception
this is useless because i cant see any obvious mistake
this is useless because update JDBC connector didnt help
So my question is simple : Any idea what can be wrong?
I would try two things:
Use "jdbc:mysql://127.0.0.1/test_database" connection string, and remove the call of execute("USE test_database")
Swap setInt and registerOutParameter lines.
In general, executing USE test_database should be fine, but MySQL documentation explicitly cautions agains using it:
Always use the Connection.setCatalog() method to specify the desired database in JDBC applications, rather than the USE database statement.
Although the context is slightly different, it appears that the same advise applies to your situation as well.

Categories