I have a MSSQL Database, and I have a stored procedure for any possible query, most of them just return a row of data with 3 columns or just execute an INSERT
How in java to connect to the DB and execute a stored procedure, and retrieve some data ?
A connection pool like DBCP makes a big difference. The connection time can be save this way.
Prepared statements can help the database to skip query parsing. The parsed statements will be cached.
Batch updates help when you're executing a statement repeatedly.
Setting the right fetch size is another optimization for queries.
Use the MSSQL JDBC Driver to create a connection to the database
In jdbc, you need to create a CallableStatement to execute the procedure. It's like this:
.
CallableStatement callable = null;
try {
String sqlCommand = "{call yourProcNameHere (?, ? /* ... */)}";
callable = conn.prepareCall(sqlCommand);
// ...
}
catch (SQLException e) {
// ...
}
finally {
/ ...
}
By reading and working through a JDBC Tutorial.
Related
I have a query which batch of sql commands in one string,
String SQLQuery =
"CREATE VOLATILE TABLE v1;
CREATE VOLATILE TABLE v2;
INSERT INTO v1;
//do stuff
INSERT INTO v2;
//do stuff
UPDATE xx;
//do stuff
DROP TABLE v1;
DROP TABLE v2;"
I tried to execute them with executeUpdate(), executeBatch() both of them fails with java jdbc client, which works in Teradata client.
Error mesg:
[TeraJDBC 15.10.00.35] [Error 3576] [SQLState 25000] Data definition not valid unless solitary.
Java code:
PreparedStatement stmt10 = null;
try {
stmt10 = conn.prepareStatement(SQLQuery);
//stmt10.executeUpdate();
stmt10.executeBatch();
//conn.commit();
} catch (Exception ex) {
throw new Exception(ex.getMessage());
} finally {
if (stmt10 != null) {
stmt10.close();
}
}
how can i do this?
In teradata you cannot execute DDL statements together. It's not a problem with the JDBC or the java code - just the way you want to use teradata. That is what that error is basically saying:
http://teradataerror.com/3576-Data-definition-not-valid-unless-solitary.html
So you need to send the separate the DDL statements in separate transactions with a separate requests. If it was multiple updates and selects it would work just fine but create table cannot be executed like that.
I believe it is due to the fact that any DDL request MUST be commited before actually happening. And if you use it like that it is not. I think it is actually OK to have DDL in a multiple commands query if it is only one and it is the last statement .
I have trouble executing the following using a JDBC prepared statement:
CREATE OR REPLACE TRIGGER Time_trg BEFORE INSERT ON Time FOR EACH ROW
BEGIN
SELECT Time_seq.NEXTVAL INTO :new.id FROM dual;
END;
The code:
try {
PreparedStatement statement = connection.prepareStatement( sql );
preparedStatement.executeUpdate();
} finally {
statement.close();
}
I'm getting this error:
java.sql.SQLException: Missing IN or OUT parameter at index:: 1
I'm working on a database agnostic solution so I need something that is portable. So what is oracle's problem?
There is no need to write our own stored procedure to do this. Oracle provides a built-in stored procedure we can use: DBMS_UTILITY.EXEC_DDL_STATEMENT:
DBMS_UTILITY.EXEC_DDL_STATEMENT('create table t1 (id number)');
In fact this is safer than the workaround procedure suggested in the accepted answer as it doesn't allow the execution of DML and so is protected against SQL injection
Use oracle.jdbc.OraclePreparedStatement
OraclePreparedStatement statement = (OraclePreparedStatement)connection.prepareStatement( sql );
As this is much specific to Oracle, regular PrepareStatement doesn't help. Oracle provides a wrapper for the same, with additional functionalities as well.
Similarly, Oracle provides OracleCallableStatement similar to CallableStatement
WorkAround: (When PreparedStatement has to be used - Risk of being misused
CREATE PROCEDURE EXECUTE_MY_DDL(INSTRING VARCHAR2)
AS
BEGIN
EXECUTE IMMEDIATE INSTRING;
END;
Reference JavaDoc
Since you cannot have any bind variables in Oracle DDL anyway, why use a PreparedStatement? You can use a static statement instead and shouldn't run into this problem:
try (Statement s = connection.createStatement()) {
s.executeUpdate(sql);
}
I am working on the web application project developed using java. In my working project,
i have the requirement like i need to create the database dynamically after the user has been registered.I had done that approach.
But, now i want to call one stored procedure that is available in another schema(Master DB).The stored procedures contains tables. Now, i want to call that procedure in dynamically created DB.
I have written the code like following, can anybody help me to know what's wrong in this code,
Connection c1 = DriverManager.getConnection(URL, USER, PASSWORD);
java.sql.CallableStatement cstmt=null;
System.out.println("Invoking the stored procedure from subscription DB........");
String callSP="{call masterdb.createCorporateDBProc()};";
cstmt= c1.prepareCall(callSP);
cstmt.execute();
java.sql.CallableStatement cstmt=null;
try {
System.out.println("Invoking the stored procedure from subscription DB........");
String callSP="{call subscription.createCorporateDBProc()}";
cstmt = c1.prepareCall(callSP);
int r = cstmt.executeUpdate();
System.out.println("SP created"+r);
System.out.println("SP invoked and executed successfully in corporate DB....");
} catch(com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException e){
e.printStackTrace();
cstmt.close();
c1.close();
}
See javadoc for Statement:
http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#executeUpdate%28java.lang.String%29
Returns:
either (1) the row count for SQL Data Manipulation Language (DML) statements or (2) 0 for SQL statements that return nothing
This means that execute for procedure will return 0. Check your database as well, if the call was successful.
With SQL Plus for Oracle Database, I can call
SET autotrace on
and then see Execution Plan, statistics, etc.
The problem is that I want access to information about the Execution Plan and statistics in my Java program. I typically have done something like this to execute a sql statement,
Connection connection = //INITIALIZE HERE;
Statement getColumn = connection.createStatement();
ResultSet results = getColumn.executeQuery("INSERT SQL QUERY HERE");
while(results.next())
{
//view results
}
Is there a way I can get the Execution Plan and Statistics? Thanks.
You can query the V$SQL_PLAN table to get the explain plain. Alternatively you can query the PLAN_TABLE, you can see more details on this HERE.
I am using Microsoft JDBC Driver 2.0 with SQL Server 2005. To explain my question better, let me start with a sample code to call a stored procedure.
public static void executeSproc(Connection con)
{
CallableStatement cstmt = con.prepareCall("{call dbo.getEmployeeManagers(?)}");
cstmt.setInt(1, 50);
ResultSet rs = cstmt.executeQuery();
while (rs.next()) {
// print results in the result set
}
rs.close();
cstmt.close();
}
Using SQL Profiler I see that the JDBC driver generates the following sql statements to make the call -
declare #P1 int
set #P1=1
exec sp_prepexec #P1 output, N'#P0 int', N'EXEC getEmployeeManagers #P0', 50
select #P1
So this means when I execute a stored procedure using a CallableStatement, the sp_prepexec
statement is called. And later when I close the statement, the sp_unprepare
is called. This seems to be the default behavior of the JDBC driver. The
problem is, the overhead to generate a prepared statement and then close it
has performance impact. Is there a way for the driver to execute the stored
procedure directly? Why can't the driver just do this -
exec getEmployeeManagers #P0=50
Try using the jTDS driver for SQLServer. I use it at work and it seems to be a lot better than the driver provided by MS.