Get status message of MySQL query (including execution time) with JDBC - java

Suppose that I am implementing a query in MySQL say
Create Database newdb;
then the database responds the result
database created in 0.05 sec
Now my question is how to get this message in a Java program using JDBC?

The following code works for me
try (Statement s = conn.createStatement()) {
s.execute("SET PROFILING=1;");
s.execute("CREATE DATABASE newdb;");
try (ResultSet rs = s.executeQuery("SHOW PROFILES;")) {
rs.next();
System.out.printf(
" Statement: %s%nExecution time: %f seconds.%n",
rs.getString("Query"),
rs.getDouble("Duration"));
}
s.execute("SET PROFILING=0;");
}
The console output is
Statement: CREATE DATABASE newdb
Execution time: 0.002014 seconds.

No you cannot do that. Not at least with JDBC. All you can do is -
Class.forName(jdbcDriver);
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/?user=root&password=");
Statement statement = connection .createStatement();
int result = statement.executeUpdate("CREATE DATABASE IF NOT EXISTS" + dbName)
and you will get result as 0.
Note that when the return value for executeUpdate is 0, it can mean one of two things:
The statement executed was an update statement that affected zero rows.
The statement executed was a DDL statement.
Documentation

Related

SQL Update Maria DB with Prepared Statement

Please help.. I have search it. But I still don't know where is my fault. Maybe I just miss something.
Here is the error :
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?, ID_JABATAN=?, TANGGAL_MASUK=?, TANGGAL_KELUAR=?, ID_JENIS_KARYAWAN=? WHERE ID' at line 1
And this is my code :
try {
DBConnection knk = new DBConnection();
Connection conn = knk.bukaKoneksi();
String sql = "UPDATE KARYAWAN SET NAMA_KARYAWAN=?, ID_JABATAN=?, TANGGAL_MASUK=?, TANGGAL_KELUAR=?, ID_JENIS_KARYAWAN=? WHERE ID_KARYAWAN=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, karyawan.getNamaKaryawan());
ps.setInt(2, karyawan.getIdJabatan());
ps.setDate(3, karyawan.getTanggalMasuk());
ps.setDate(4, karyawan.getTanggalKeluar());
ps.setInt(5, karyawan.getIdJenisKaryawan());
ps.setInt(6, karyawan.getIdKaryawan());
int hasil = ps.executeUpdate(sql);
return hasil > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
And the column of the table :
Try this:
int hasil = ps.executeUpdate();
remove the Parameter from int hasil = ps.executeUpdate(sql);
if you call it with Parameter, the query will be executet, not the prepared Statement.
See the javadoc:
int executeUpdate(String sql)
throws SQLException
Executes the given SQL statement, which may be an INSERT, UPDATE, or
DELETE statement or an SQL statement that returns nothing, such as an
SQL DDL statement. Note:This method cannot be called on a
PreparedStatement or CallableStatement. Parameters:sql - an SQL Data
Manipulation Language (DML) statement, such as INSERT, UPDATE or
DELETE; or an SQL statement that returns nothing, such as a DDL
statement.Returns:either (1) the row count for SQL Data Manipulation
Language (DML) statements or (2) 0 for SQL statements that return
nothingThrows:SQLException - if a database access error occurs, this
method is called on a closed Statement, the given SQL statement
produces a ResultSet object, the method is called on a
PreparedStatement or CallableStatementSQLTimeoutException - when the
driver has determined that the timeout value that was specified by the
setQueryTimeout method has been exceeded and has at least attempted to
cancel the currently running Statement
int executeUpdate()
throws SQLException
Executes the SQL statement in this PreparedStatement object, which
must be an SQL Data Manipulation Language (DML) statement, such as
INSERT, UPDATE or DELETE; or an SQL statement that returns nothing,
such as a DDL statement. Returns:either (1) the row count for SQL Data
Manipulation Language (DML) statements or (2) 0 for SQL statements
that return nothingThrows:SQLException - if a database access error
occurs; this method is called on a closed PreparedStatement or the SQL
statement returns a ResultSet objectSQLTimeoutException - when the
driver has determined that the timeout value that was specified by the
setQueryTimeout method has been exceeded and has at least attempted to
cancel the currently running Statement

multiple sql command

I'm trying to execute multiple sql commands, but it gives me "error in your SQL syntax;"
Db_Connection dbconn = new Db_Connection();
Connection myconnection = dbconn.Connection();
String sqlString = "SELECT DISTINCT std_id FROM std_crs WHERE crs_id ='222123'; "
+ "SELECT * FROM cplus_grades ;";
Statement myStatement = myconnection.createStatement();
boolean results = myStatement.execute(sqlString);
do {
if (results) {
ResultSet rs = myStatement.getResultSet();
while (rs.next()) {
}
rs.close();
}
results = myStatement.getMoreResults();
} while(results);
myStatement.close();
I did a small test with three JDBC drivers:
MS SQL: works, returns two result sets
MySQL: fails with a syntax error - that is what you are seeing
HSQLDB: runs, but returns only one result set.
So I guess it simply depends on the JDBC driver if this technique works. Maybe it works only in MS SQL JDBC.
UPDATE:
It also works with Postgres.
please
1. String dbUrl = "jdbc:mysql://yourDatabase?allowMultiQueries=true";
this should be your jdbc connection url

Execute multiple SQL statements in java

I want to execute a query in Java.
I create a connection. Then I want to execute an INSERT statement, when done, the connection is closed but I want to execute some insert statement by a connection and when the loop is finished then closing connection.
What can I do ?
My sample code is :
public NewClass() throws SQLException {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
System.out.println("Where is your Oracle JDBC Driver?");
return;
}
System.out.println("Oracle JDBC Driver Registered!");
Connection connection = null;
try {
connection = DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:orcl1", "test",
"oracle");
} catch (SQLException e) {
System.out.println("Connection Failed! Check output console");
return;
}
if (connection != null) {
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * from test.special_columns");
while (rs.next()) {
this.ColName = rs.getNString("column_name");
this.script = "insert into test.alldata (colname) ( select " + ColName + " from test.alldata2 ) " ;
stmt.executeUpdate("" + script);
}
}
else {
System.out.println("Failed to make connection!");
}
}
When the select statement ("SELECT * from test.special_columns") is executed, the loop must be twice, but when (stmt.executeUpdate("" + script)) is executed and done, then closing the connection and return from the class.
Following example uses addBatch & executeBatch commands to execute multiple SQL commands simultaneously.
import java.sql.*;
public class jdbcConn {
public static void main(String[] args) throws Exception{
Class.forName("org.apache.derby.jdbc.ClientDriver");
Connection con = DriverManager.getConnection
("jdbc:derby://localhost:1527/testDb","name","pass");
Statement stmt = con.createStatement
(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
String insertEmp1 = "insert into emp values
(10,'jay','trainee')";
String insertEmp2 = "insert into emp values
(11,'jayes','trainee')";
String insertEmp3 = "insert into emp values
(12,'shail','trainee')";
con.setAutoCommit(false);
stmt.addBatch(insertEmp1);
stmt.addBatch(insertEmp2);
stmt.addBatch(insertEmp3);
ResultSet rs = stmt.executeQuery("select * from emp");
rs.last();
System.out.println("rows before batch execution= "
+ rs.getRow());
stmt.executeBatch();
con.commit();
System.out.println("Batch executed");
rs = stmt.executeQuery("select * from emp");
rs.last();
System.out.println("rows after batch execution= "
+ rs.getRow());
}
}
Result:
The above code sample will produce the following result.The result may vary.
rows before batch execution= 6
Batch executed
rows after batch execution= = 9
Source: Execute multiple SQL statements
In the abscence of the schema or the data contained in each table I'm going to make the following assumptions:
The table special_columns could look like this:
column_name
-----------
column_1
column_2
column_3
The table alldata2 could look like this:
column_1 | column_2 | column_3
---------------------------------
value_1_1 | value_2_1 | value_3_1
value_1_2 | value_2_2 | value_3_2
The table alldata should, after inserts have, happened look like this:
colname
---------
value_1_1
value_1_2
value_2_1
value_2_2
value_3_1
value_3_2
Given these assumptions you can copy the data like this:
try (
Connection connection = DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:orcl1", "test", "oracle")
)
{
StringBuilder columnNames = new StringBuilder();
try (
Statement select = connection.createStatement();
ResultSet specialColumns = select.executeQuery("SELECT column_name FROM special_columns");
Statement insert = connection.createStatement()
)
{
while (specialColumns.next())
{
int batchSize = 0;
insert.addBatch("INSERT INTO alldata(colname) SELECT " + specialColumns.getString(1) + " FROM alldata2");
if (batchSize >= MAX_BATCH_SIZE)
{
insert.executeBatch();
batchSize = 0;
}
}
insert.executeBatch();
}
A couple of things to note:
MAX_BATCH_SIZE should be set to a value based on your database configuration and the data being inserted.
this code is using the Java 7 try-with-resources feature to ensure the database resources are released when they're finished with.
you haven't needed to do a Class.forName since the service provider mechanism was introduced as detailed in the JavaDoc for DriverManager.
There are two problems in your code. First you use the same Statement object (stmt) to execute the select query, and the insert. In JDBC, executing a statement will close the ResultSet of the previous execute on the same object.
In your code, you loop over the ResultSet and execute an insert for each row. However executing that statement will close the ResultSet and therefor on the next iteration the call to next() will throw an SQLException as the ResultSet is closed.
The solution is to use two Statement objects: one for the select and one for the insert. This will however not always work by default, as you are working in autoCommit (this is the default), and with auto commit, the execution of any statement will commit any previous transactions (which usually also closes the ResultSet, although this may differ between databases and JDBC drivers). You either need to disable auto commit, or create the result set as holdable over commit (unless that already is the default of your JDBC driver).

using JDBC preparedStatement in a batch

Im using Statements batchs to query my data base.
Iv'e done some research now and i want to rewrite my application to use preparedStatement instead but i'm having hard time to figure out how to add queries to a preparedStatement batch.
This is what i'm doing now:
private void addToBatch(String sql) throws SQLException{
sttmnt.addBatch(sql);
batchSize++;
if (batchSize == elementsPerExecute){
executeBatches();
}
}
where sttmnt is a class member of type Statement.
What i want to do is to use the preparedStatement's setString(int, String) method to set some dynamic data and then add it to the batch.
Unfortunately, i don't fully understand how it works, and how i can use setString(int, String) to a specific sql in the batch OR create a new preparedStatemnt for every sql i have and then join them all to one batch.
is it possible to do that? or am i really missing something in my understanding of preparedStatement?
Read the section 6.1.2 of this document for examples. Basically you use the same statement object and invoke the batch method after all the placeholders are set. Another IBM DB2 example which should work for any JDBC implementation. From the second site:
try {
connection con.setAutoCommit(false);
PreparedStatement prepStmt = con.prepareStatement(
"UPDATE DEPT SET MGRNO=? WHERE DEPTNO=?");
prepStmt.setString(1,mgrnum1);
prepStmt.setString(2,deptnum1);
prepStmt.addBatch();
prepStmt.setString(1,mgrnum2);
prepStmt.setString(2,deptnum2);
prepStmt.addBatch();
int [] numUpdates=prepStmt.executeBatch();
for (int i=0; i < numUpdates.length; i++) {
if (numUpdates[i] == -2)
System.out.println("Execution " + i +
": unknown number of rows updated");
else
System.out.println("Execution " + i +
"successful: " + numUpdates[i] + " rows updated");
}
con.commit();
} catch(BatchUpdateException b) {
// process BatchUpdateException
}
With PreparedStatement's you have wild cards in a way, for example
Sring query = "INSERT INTO users (id, user_name, password) VALUES(?,?,?)";
PreparedStatement statement = connection.preparedStatement(query);
for(User user: userList){
statement.setString(1, user.getId()); //1 is the first ? (1 based counting)
statement.setString(2, user.getUserName());
statement.setString(3, user.getPassword());
statement.addBatch();
}
This will create 1 PreparedStatement with that query shown above.You can loop through list when you want to insert or whatever you intentions are. When you want to execute you,
statement.executeBatch();
statement.clearBatch(); //If you want to add more,
//(so you don't do the same thing twice)
I'm adding an extra answer here specifically for MySQL.
I found that the time to do a batch of inserts was similar to the length of time to do individual inserts, even with the single transaction around the batch.
I added the parameter rewriteBatchedStatements=true to my jdbc url, and saw a dramatic improvement - in my case, a batch of 200 inserts went from 125 msec. without the parameter to about 10 to 15 msec. with the parameter.
See MySQL and JDBC with rewriteBatchedStatements=true

Return ROWID Parameter from insert statement using JDBC connection to oracle

I can't seem to get the right magic combination to make this work:
OracleDataSource ods = new oracle.jdbc.pool.OracleDataSource();
ods.setURL("jdbc:oracle:thin:app_user/pass#server:1521:sid");
DefaultContext conn = ods.getConnection();
CallableStatement st = conn.prepareCall("INSERT INTO tableA (some_id) VALUES (1) RETURNING ROWID INTO :rowid0");
st.registerReturnParameter(1, OracleTypes.ROWID);
st.execute();
The error I get is "Protocol Violation". If I change to registerOutParameter(), I get notified that I haven't registered all return variables. If I wrap the statement in a PL/SQL begin; end; block then I get the parameter just fine using a regular registerOutParameter() call. I would really prefer to avoid wrapping all my inserts statements in PL/SQL - so what is missing from above?
Usually you don't want to make code database dependent. Instead of OraclePreparedStatement, you should use CallableStatement.
CallableStatement statement = connection.prepareCall("{call INSERT INTO tableA (some_id) VALUES (1) RETURNING ROWID INTO ? }");
statement.registerOutParameter( 1, Types.VARCHAR );
int updateCount = statement.executeUpdate();
if (updateCount > 0) {
return statement.getString(1);
}
A few things you'll need to do
Change CallableStatement to OracleCallableStatement
Try and return into a NUMBER, ie: OracleTypes.Number
Sample code for returning info from a query:
OraclePreparedStatement pstmt = (OraclePreparedStatement)conn.prepareStatement(
"delete from tab1 where age < ? returning name into ?");
pstmt.setInt(1,18);
/** register returned parameter
* in this case the maximum size of name is 100 chars
*/
pstmt.registerReturnParameter(2, OracleTypes.VARCHAR, 100);
// process the DML returning statement
count = pstmt.executeUpdate();
if (count>0)
{
ResultSet rset = pstmt.getReturnResultSet(); //rest is not null and not empty
while(rset.next())
{
String name = rset.getString(1);
...
}
}
More info on Oracle's JDBC extensions:
http://download-uk.oracle.com/docs/cd/B19306_01/java.102/b14355/oraint.htm
Don't know if this applies or not since you don't specify what version you're using.
From Oracle Metalink:
Cause
In the 10.1.0.x JDBC driver, returning DML is not supported:
Per the JDBC FAQ:
"10.1.0 (10g r1)
Is DML Returning Supported ?
Not in the current drivers. However, we do have plans to support it in post 10.1.0 drivers. We
really mean it this time."
As the application code is trying to use unsupported JDBC features, errors are raised.
Solution
Upgrade the JDBC driver to 10.2.0.x, because per the FAQ the 10.2.0.x JDBC drivers do support returning clause:
"10.2.0 (10g r2)
Is DML Returning Supported ?
YES! And it's about time. See the Developer's Guide for details. "
EDIT
Just for grins, you can check the version of JDBC Oracle thinks it's using with:
// Create Oracle DatabaseMetaData object
DatabaseMetaData meta = conn.getMetaData();
// gets driver info:
System.out.println("JDBC driver version is " + meta.getDriverVersion());
If that shows a JDBC driver 10.2.0.x or later, then I'm out of ideas and perhaps a support request to oracle is in order...
PreparedStatement prepareStatement = connection.prepareStatement("insert...",
new String[] { "your_primary_key_column_name" });
prepareStatement.executeUpdate();
ResultSet generatedKeys = prepareStatement.getGeneratedKeys();
if (null != generatedKeys && generatedKeys.next()) {
Long primaryKey = generatedKeys.getLong(1);
}
I have found the answer this is perfectly works. I can insert from JAVA and its return with the key.
Full version:
CREATE TABLE STUDENTS
(
STUDENT_ID NUMBER NOT NULL PRIMARY KEY,
NAME VARCHAR2 (50 BYTE),
EMAIL VARCHAR2 (50 BYTE),
BIRTH_DATE DATE
);
CREATE SEQUENCE STUDENT_SEQ
START WITH 0
MAXVALUE 9999999999999999999999999999
MINVALUE 0;
And the Java code
String QUERY = "INSERT INTO students "+
" VALUES (student_seq.NEXTVAL,"+
" 'Harry', 'harry#hogwarts.edu', '31-July-1980')";
// load oracle driver
Class.forName("oracle.jdbc.driver.OracleDriver");
// get database connection from connection string
Connection connection = DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:sample", "scott", "tiger");
// prepare statement to execute insert query
// note the 2nd argument passed to prepareStatement() method
// pass name of primary key column, in this case student_id is
// generated from sequence
PreparedStatement ps = connection.prepareStatement(QUERY,
new String[] { "student_id" });
// local variable to hold auto generated student id
Long studentId = null;
// execute the insert statement, if success get the primary key value
if (ps.executeUpdate() > 0) {
// getGeneratedKeys() returns result set of keys that were auto
// generated
// in our case student_id column
ResultSet generatedKeys = ps.getGeneratedKeys();
// if resultset has data, get the primary key value
// of last inserted record
if (null != generatedKeys && generatedKeys.next()) {
// voila! we got student id which was generated from sequence
studentId = generatedKeys.getLong(1);
}
}
source : http://viralpatel.net/blogs/oracle-java-jdbc-get-primary-key-insert-sql/
Try using ? instead of :rowid0 on your SQL string. I have had problems before with named parameters and Oracle.

Categories

Resources