i've got some code that is triggering a syntax error because of some misplaced semicolons. if this was running on the command line, i'd solve this with a delimiter. unfortunately, the jdbc4 driver doesn't seem to recognize delimiters. anyway to get this to run?
delimiter |
CREATE TRIGGER obs_update BEFORE UPDATE ON obs
FOR EACH ROW
BEGIN
IF OLD.voided = 0 AND NEW.voided = 1 THEN
DELETE FROM clinic_obs WHERE id = OLD.obs_id;
ELSE
UPDATE clinic_obs SET clinic_obs.revision_token = NOW()
WHERE NEW.obs_id = clinic_obs.id;
END IF;
END;
|
delimiter ;
Delimiter is a command for SQL client. There is no need to use delimiter in JDBC.
Example below shows it:
import java.sql.*;
public class TriggerExample {
public static void main(String args[]) {
String connectionURL = "jdbc:mysql://localhost:3306/test";
Connection con = null;
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection(connectionURL, "login",
"password");
Statement stmt = con.createStatement();
stmt.execute("CREATE TRIGGER obs_update BEFORE UPDATE ON obs "
+ "FOR EACH ROW "
+ "BEGIN "
+ "IF OLD.voided = 0 AND NEW.voided = 1 THEN "
+ " DELETE FROM clinic_obs WHERE id = OLD.obs_id; "
+ "ELSE "
+ " UPDATE clinic_obs SET clinic_obs.revision_token = NOW() "
+ " WHERE NEW.id = clinic_obs.id; "
+ "END IF; "
+ "END;");
con.close();
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
Try removing the semi colon after the final END word. so it looks like this:
delimiter |
CREATE TRIGGER obs_update BEFORE UPDATE ON obs
FOR EACH ROW
BEGIN
IF OLD.voided = 0 AND NEW.voided = 1 THEN
DELETE FROM clinic_obs WHERE id = OLD.obs_id;
ELSE
UPDATE clinic_obs SET clinic_obs.revision_token = NOW()
WHERE NEW.obs_id = clinic_obs.id;
END IF;
END|
It should work because I have done a similar trigger/procedure using jdbc driver.
Related
As part of my java application, I have to create oracle packages from java code. Sometimes, the package code might have issues and compilation might fail. However, I am unable to capture simple failures from java. So, i have to compile > 350 oracle packages from java, and if there are errors in the package, I need to inform the user to fix them. I have pasted oracle package and java code below.
CREATE OR REPLACE PACKAGE plat_test IS
FUNCTION getmsg (
p_empno IN NUMBER
) RETURN VARCHAR2;
END plat_test;
/
CREATE OR REPLACE PACKAGE BODY plat_test AS
FUNCTION getmsg (
p_empno IN NUMBER
) RETURN VARCHAR2 IS
BEG
RETURN 'sss';
END getmsg;
END plat_teest;
Compiling / running the above code in sql developer throws:
LINE/COL ERROR
--------- -------------------------------------------------------------
0/0 PL/SQL: Compilation unit analysis terminated
1/14 PLS-00201: identifier 'PLAT_TEEST' must be declared
1/14 PLS-00304: cannot compile body of 'PLAT_TEEST' without its specification
Errors: check compiler log
I want to create the above package in java and get the result. So that I can inform the user on the failure. In java I am not able to capture the errors and the program always succeeds.
How can I capture the output in java
The java code I have:
import java.sql.*;
public class NewJDBCTester {
public static void one() {
String s_sql = "CREATE OR REPLACE PACKAGE BODY plat_test AS\n" +
" FUNCTION getmsg (\n" +
" p_empno IN NUMBER\n" +
" ) RETURN VARCHAR IS\n" +
" BEG" +
" RETURN 'ret_val';\n" +
" END getmsg;\n" +
"\n" +
"END plat_test\n" +
"/";
// String s_sql ="alter table Metric_idf from ssssssss_ssst";
// System.out.println(" SQL Stmt: " + sql);
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Connection conn = null;
Statement stmt = null;
try {
conn = DriverManager.getConnection("jdbc:oracle:thin:bhasoor/password#10.100.1.61:34171/ssssssssssdb");
stmt = conn.createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
try {
stmt.execute (s_sql);
System.out.println(" SQL Executed Successfully ");
} catch (SQLException sqe) {
System.out.println("Error Code = " + sqe.getErrorCode());
// sqe.
System.out.println("SQL state = " + sqe.getSQLState());
System.out.println("Message = " + sqe.getMessage());
System.out.println("printTrace /n");
sqe.printStackTrace();
}
}
public static void main(String[] args) throws ClassNotFoundException {
one();
}
}
You can know if an error occurs by this way:
boolean result = stmt.execute(s_sql);
System.out.println(result ? " SQL Executed Successfully " : " SQL Executed with error ");
Then, the following query give you the error:
select *
from ALL_ERRORS
where owner = 'METRICSTREAM'
and name = 'PLAT_TEST'
--and type = 'PACKAGE BODY'
order by sequence
Here, there is no SQLException because the compilation has been completed, but with some errors.
You should use try-with-resource like this to avoid memory leaks:
try ( //
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:#10.100.1.61:34171/pdb", "metricstream", "password"); //
Statement stmt = conn.createStatement(); //
) {
boolean result = stmt.execute(s_sql);
System.out.println(result ? " SQL Executed Successfully " : " SQL Executed with error ");
}
catch (SQLException sqe) {
System.out.println("Error Code = " + sqe.getErrorCode());
System.out.println("SQL state = " + sqe.getSQLState());
System.out.println("Message = " + sqe.getMessage());
System.out.println("printTrace /n");
sqe.printStackTrace();
}
You could have a look at this blog from a few years ago.
You can use the libraries from Oracle SQLDeveloper or Oracle SQLcl to run scripts like you would on the command line.
https://barrymcgillin.blogspot.com/2018/04/run-your-sql-script-from-java-now.html
In your script, you can do simple sqlplus things like
Begin
my stuff;
end;
/
show errors
You can also get the errors from the executor object after it has run.
So finally I acheived this like this. Execute the create or replace package then get the errors from dba_errors...
Posting code here...
import java.sql.*;
public class NewJDBCTester {
public static void one() throws ClassNotFoundException {
String s_sql = "CREATE OR REPLACE PACKAGE BODY plat_test AS\n" +
" FUNCTION getmsg (\n" +
" p_empno IN NUMBER\n" +
" ) RETURN VARCHAR2 IS\n" +
" BEGIN\n" +
// " RETURN 'sss';\n" +
" END getmsg;\n" +
"END plat_test;\n";
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = null;
Statement stmt = null;
ResultSet rset = null;
try {
conn = DriverManager.getConnection("jdbc:oracle:thin:user/password#10.100.1.61:34171/somedb");
stmt = conn.createStatement();
System.out.println("EXECUTING QUERY");
rset = stmt.executeQuery(s_sql);
rset.close();
stmt.close();
stmt = conn.createStatement();
rset = stmt.executeQuery("SELECT line, text FROM DBA_ERRORS WHERE OWNER = 'Bhasoor' AND NAME = 'PLAT_TEST' ORDER BY SEQUENCE desc");
while (rset.next()) {
System.out.println("ERROR AT LINE ::: " + rset.getString("line"));
System.out.println("\n");
System.out.println("ERROR DETAILS::: " + rset.getString("text"));
}
} catch (SQLException sqe) {
System.out.println("Error Code = " + sqe.getErrorCode());
System.out.println("SQL state = " + sqe.getSQLState());
System.out.println("Message = " + sqe.getMessage());
System.out.println("printTrace \n");
sqe.printStackTrace();
}
}
public static void main(String[] args) throws ClassNotFoundException {
one();
}
}
I have following stored procedure:
CREATE DEFINER=`root`#`localhost` PROCEDURE `blast10`()
BEGIN
SELECT concat("ROUND ",draws.izvlacenje_id,": ", draws.1,",",draws.2,",",draws.3,",",draws.4,",",draws.5,",",draws.6,",",draws.7,",",draws.8,",",draws.9,",",draws.10,",",draws.11,",",draws.12,",",draws.13,",",draws.14,",\n",draws.15,",",draws.16,",",draws.17,",",draws.18,",",draws.19,",",draws.20,",",
draws.21,",",draws.22,",",draws.23,",",draws.24,",",draws.25,",",draws.26,",",draws.27,",",draws.28,",",draws.29,",",draws.30,",",draws.31,",",draws.32,",",draws.33,",",draws.34,",",draws.35,"")
rzlt from macau.draws order by iddraws desc limit 10;
END`
This procedure returns 10 rows of data and i want to send that data through TCP/IP communication, this is what i achieved by now:
public void blastTen() throws SQLException {
String blastTen = "";
String bl10 = "LAST 10 RESULTS";
try {
Statement st = Conex.conn.createStatement();
String SQLEdit = "{ call blast10() }";
ResultSet rs = st.executeQuery(SQLEdit);
while (rs.next()) {
blastTen = bl10 + "\n" + rs.getString("rzlt") + "\n";
}
os.println(blastTen + "\n");
}
catch (Exception e2) {
System.out.println(e2);
}
}
The problem is I can send only one row and can't seem to get the other rows.
Any help is appreciated
The code
while (rs.next())
{
blastTen=bl10+"\n"+rs.getString("rzlt")+"\n";
}
won't assign anything to bl10 so you'll always only get the latest row... Try
...
bl10 = bl10 + "\n" + rs.getString( "rzlt" );
}
os.println( bl10 );
instead.
Cheers,
When writing to a mySQL db, i get the following error:
java.sql.BatchUpdateException: Unknown column 'ALFA' in 'where clause'
this is my java code:
public void pushWinner(String game, String teamW) throws SQLException{
String[] t1 = game.split("-");
String statement = "update games set winner=(?) where team1 = "+t1[0]+" AND team2 = "+t1[1];
try (PreparedStatement pstmt = conn.prepareStatement(statement)) {
pstmt.setString(1, teamW);
pstmt.addBatch();
pstmt.executeBatch();
pstmt.close();
} catch (SQLException ex) {
System.out.println(ex);
}
}
I realy can't see what's wrong with the where clause...
EDIT
See my comment, forgot to mention what 'ALFA' is.
Data types for team1 and team2 are both VARCHAR(45).
try this: since datatype of column team1 and team2 are VARCHAR so put single quote to compare it.
queryString= "update games set winner=(?) where team1 = '"+t1[0]+"' AND team2 = '"+t1[1]+"'";
If your datatype is string that you need Single Quote around your passed variable values
something like this...
String statement = "update games set winner=(?) where team1 = '"+t1[0]+"' AND team2 = ' "+ t1[1] + "'";
Your asking for trouble making sql like this. use a prepared statement with seperate parameters instead of inline param building. will stop issues like this and take care of parameter escaping. So use ? in the main sql to denoate location of a parm and use .setString(1, value); to set first (yes its 1 based). Or setInt(1, intValue) ... depending on data type. For date use java.sql.Timestamp - can convert a calendar to date and java.util.Date to sql timestamp OR new javax.time or joda. But dont use inline.
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html
Why
ease of programming and
https://www.owasp.org/index.php/SQL_Injection
Copied from the java tutorial :
String updateString =
"update " + dbName + ".COFFEES " +
"set SALES = ? where COF_NAME = ?";
String updateStatement =
"update " + dbName + ".COFFEES " +
"set TOTAL = TOTAL + ? " +
"where COF_NAME = ?";
try {
con.setAutoCommit(false);
updateSales = con.prepareStatement(updateString);
updateTotal = con.prepareStatement(updateStatement);
for (Map.Entry<String, Integer> e : salesForWeek.entrySet()) {
updateSales.setInt(1, e.getValue().intValue());
updateSales.setString(2, e.getKey());
updateSales.executeUpdate();
updateTotal.setInt(1, e.getValue().intValue());
updateTotal.setString(2, e.getKey());
updateTotal.executeUpdate();
con.commit();
}
} catch (SQLException e ) {
JDBCTutorialUtilities.printSQLException(e);
if (con != null) {
try {
System.err.print("Transaction is being rolled back");
con.rollback();
} catch(SQLException excep) {
JDBCTutorialUtilities.printSQLException(excep);
}
}
} finally {
if (updateSales != null) {
updateSales.close();
}
if (updateTotal != null) {
updateTotal.close();
}
con.setAutoCommit(true);
}
}
I am trying to update a table using Java JDBC. The method I am using does not throw any errors but the table is not updating. The create table method is below:
public static void Table()
{
Connection c = null;
Statement stmt = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:WalkerTechCars.db");
System.out.println("Opened database successfully");
stmt = c.createStatement();
String sql = "CREATE TABLE IF NOT EXISTS CUSTOMERS2 " +
"(PHONE TEXT PRIMARY KEY NOT NULL," +
" SURNAME TEXT NOT NULL, " +
" FIRSTNAME TEXT NOT NULL, " +
" HOME TEXT, " +
" ADDRESS TEXT, " +
" POSTCODE Text)";
stmt.executeUpdate(sql);
stmt.close();
c.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
}
System.out.println("Customers2 created successfully");
}
The update method is below:
public static void updateCustomers()
{
Connection c = null;
PreparedStatement pstmt = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:WalkerTechCars.db");
c.setAutoCommit(false);
System.out.println("Opened database successfully");
String query = "UPDATE CUSTOMERS2 set ADDRESS = ? where PHONE = ? ";
pstmt = c.prepareStatement(query); // create a statement
pstmt.setString(1, "1"); // set input parameter 1
pstmt.setString(2, "DOES THIS WORK"); // set input parameter 2
pstmt.executeUpdate(); // execute update statement
pstmt.close();
c.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
}
System.out.println("Update Completed successfully HELLO");
}
I have tried to find some clear instructions on this but cant find any. I do not really understand JDBC and prepared statement very well
When autoCommit is false (c.setAutoCommit(false);), you must manually commit the transaction...
Add...
c.commit()
After pstmt.executeUpdate();
You code also has a flaw, in that if some kind of error occurs during the preparation or execution of the statement, both the Connection and PreparedStatement could be left open, causing a resource leak
If you're using Java 7+ you can use the try-with-resources feature, for example...
try {
Class.forName("org.sqlite.JDBC");
try (Connection c = DriverManager.getConnection("jdbc:sqlite:WalkerTechCars.db")) {
c.setAutoCommit(false);
System.out.println("Opened database successfully");
String query = "UPDATE CUSTOMERS2 set ADDRESS = ? where PHONE = ? ";
try (PreparedStatement pstmt = c.prepareStatement(query)) {
pstmt.setString(1, "1"); // set input parameter 1
pstmt.setString(2, "DOES THIS WORK"); // set input parameter 2
pstmt.executeUpdate(); // execute update statement
c.commit();
}
} catch (SQLException exp) {
exp.printStackTrace();
}
} catch (ClassNotFoundException exp) {
exp.printStackTrace();
System.out.println("Failed to load driver");
}
This will ensure that regardless of how you leave the try block the resource will be closed.
You might also consider taking a look at the JDBC(TM) Database Access
Your update method will set ADDRESS to 1 if there is any row in table with PHONE = does this work.
Try to put Address in 1st Input parameter and Phone 2nd Input parameter
When a connection is created, it is in auto-commit mode.
We need to use [setAutoCommit] method only when we need to make Auto Commit false and make it manual commit after executing the query.
More details at Oracle site on JDBC Transaction.
private void jbutton1ActionPerformed(java.awt.event.ActionEvent evt) {
try
{
MainClass mc=new MainClass();
Connection connection;
connection=DriverManager.getConnection(mc.StrUrl,mc.StrUid,mc.StrPwd);
ResultSet rs;
String StrQr="";
if (prid.getText().trim().length()>0 )
{
StrQr=StrQr + " and pid = " + prid.getText().trim() + " ";
}
if (StrQr.length()==0)
{
JOptionPane.showMessageDialog(null,"Enter search critaria.");
return;
}
PreparedStatement st=connection.prepareStatement("select pid, pname,pslno,pcategory,pqty,ppurcst,plpurcst,psalprc,pcmprc from addproducts where 1=1 " + StrQr + " order by pid");
rs = st.executeQuery();
JOptionPane.showMessageDialog(null,"connected");
while (rs.next()) {
purcst.setText(rs.getString("ppurcst"));
salprc.setText(rs.getString("psalprc"));
prid.setText(rs.getString("Pid"));
prname.setText(rs.getString("Pname"));
category.setText(rs.getString("Pcategory"));
cprc.setText(rs.getString("Pcmprc"));
qnty.setText(rs.getString("Pqty"));
slno.setText(rs.getString("Pslno"));
lpurcst.setText(rs.getString("plpurcst"));
}
rs.close();
}
catch (Exception e)
{
System.err.println(e);
//System.exit(1);
}
}
code display only pid = 104 like numbers .
it cant display special charectors( _,- )pid= A_1103like anybody can help me.
com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Unknown column 'A' in 'where clause'
i declare pid as varchar in mysql
A_1103 needs to be quoted, otherwise MySQL will try and resolve it to a column value.
... pid = 'A_1103' ...
In fact, you should be relying on PreparedStatement in order to prevent possible SQL injection problems.
See Using Prepared Statements for more details
For example...
Connection connection;
connection=DriverManager.getConnection(mc.StrUrl,mc.StrUid,mc.StrPwd);
ResultSet rs;
// I'm assuming there are other elements to this query that
// may be included, otherwise this is a lot of overhead
// for little benifi...
List values = new ArrayList(5);
String StrQr="";
if (prid.getText().trim().length()>0 )
{
StrQr += " and pid = ? ";
values.add(prid.getText().trim());
}
if (StrQr.length()==0)
{
JOptionPane.showMessageDialog(null,"Enter search critaria.");
return;
}
PreparedStatement st=connection.prepareStatement("select pid, pname,pslno,pcategory,pqty,ppurcst,plpurcst,psalprc,pcmprc from addproducts where 1=1 " + StrQr + " order by pid");
// Bind the values to the parameters
for (int index = 0; index < values.size(); index++) {
st.setObject(index + 1, values.get(index));
}
rs = st.executeQuery();
JOptionPane.showMessageDialog(null,"connected");
In prepared statement you have to set a ? or any parameter and bind the value.
String StrQr="";
if (prid.getText().trim().length()>0 )
{
StrQr=StrQr + " and pid = ? ";
}
...
PreparedStatement st=connection.prepareStatement("select pid, pname,pslno,pcategory,pqty,ppurcst,plpurcst,psalprc,pcmprc from addproducts where 1=1 " + StrQr + " order by pid");
if (prid.getText().trim().length()>0 )
st.bind(1prid.getText().trim() )
rs = st.executeQuery();
JOptionPane.showMessageDialog(null,"connected");