How can I create a stored procedure using JDBC? I've tried the following code, but it fails with errors.
Contents of the 'sql' variable which is used in jdbc code
CREATE PROCEDURE 'init'()
BEGIN
DECLARE '_rollback' BOOL DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET '_rollback' = 1;
START TRANSACTION;
DROP TABLE IF EXISTS tst;
CREATE TABLE IF NOT EXISTS tst
(
did INT AUTO_INCREMENT PRIMARY KEY,
stage INT
);
INSERT INTO tst (stage) VALUES (11);
INSERT INTO tst (stage) VALUES (23);
IF '_rollback'
THEN
ROLLBACK;
ELSE
COMMIT;
END IF;
END;
JDBC Code:
Statement statement = connection.createStatement();
statement.executeLargeUpdate(sql);
JDBC Error:
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 ''create_and_populate_schema'()
BEGIN
DECLARE '_rollback' BOOL DEFAULT 0;
' at line 1
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:536)
I hope DELIMITER should not be set because it only works inside 'mysql' client and it seems that there is no any alternative with sql-String that is supposed to be used with JDBC
Related
I just want to create a table, but if it exists it needs to be dropped and re-created.
I use MySQL 8.0.29
Error:
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 'CREATE TABLE users (Id long, name varchar(100), lastName
varchar(100), age tin' at line 1
Code:
public static void main(String[] args) throws SQLException {
try (Connection connection = Util.getConnection()) {
String sqlCommand = "DROP TABLE IF EXISTS `users`;" +
"CREATE TABLE `users` (Id long, name varchar(100), lastName varchar(100), age tinyint)";
Statement statement = connection.createStatement();
statement.executeUpdate(sqlCommand);
System.out.println("table created");
int rows = statement.executeUpdate("INSERT users(Id,name,lastName,age) VALUES (101,'Mike','Manson',31)");
}
}
The following may be the reason:
long is not a valid MySQL data type.
variable sqlCommand contains multiple statements. Each SQL statement should be terminated with a semicolon symbol. Adding a semicolon at the end of CREATE statement can solve your issue.
By default the JDBC driver does not support multiple SQL statements in one execute call. There's a connect string option to enable it:
https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-connp-props-security.html#cj-conn-prop_allowMultiQueries
allowMultiQueries
Allow the use of ';' to delimit multiple queries during one statement.
But there's no good reason to use multi-queries. They make your code more complex, not simpler. Allowing multi-queries creates the opportunity for a type of SQL injection vulnerabilities that are not possible otherwise. See https://xkcd.com/327/
Just run one statement per call to executeUpdate().
Background
To work around the issue in MySql that certain statements are only permitted within a stored procedure I'm trying to create, run, then drop a stored procedure within sql submitted by a JdbcTemplate. A simplied example would be (this happens to be within spring boot):
#Service
public class StartupDatabaseCheck {
private JdbcTemplate template;
#Autowired
public StartupDatabaseCheck(JdbcTemplate template){
this.template = template;
}
#PostConstruct
public void init() {
log.info("Running custom fields table creation (if required)");
try {
String migrateSql = Resources.toString(Resources.getResource("migrateScript.sql"), Charsets.UTF_8);
template.execute(migrateSql);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Where migrateScript.sql is
DELIMITER //
CREATE PROCEDURE migrate()
BEGIN
IF ((SELECT count(1)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'custom_field_instance_data'
and column_name='entity_id' and is_nullable = false) > 0)
THEN
alter table custom_field_instance_data MODIFY COLUMN entity_id char(32) null;
END IF;
END //
DELIMITER ;
call migrate;
drop procedure migrate;
Running this within mySql workbench works fine, but submitted by the JdbcTemplate I get the error
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 'CREATE PROCEDURE migrate_custom_fields()
As I understand it thats because those DELIMITER statements are not permitted by JdbcTemplate but just removing them as suggested in that link leads to other syntax errors
Question
How can a mySQL stored procedure be created (or statements usually only allowed with a stored procedure be executed) by a JdbcTemplate
Notes
The error without the deliminator statements is
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 'CREATE PROCEDURE migrate_custom_fields()
It seems that the driver is not taking the delimited queries into the account.If you want to create an stored procedure on fly using the jdbc.
Using the following property and pass it as the connection parameter in the URL.
jdbc:mysql://localhost:3306/test?allowMultiQueries=true
The above property will allow ';' delimited queries.
You can find more on this at here
Create MySQL stored procedure using JPA Hibernate
The updated migrateScript.sql in this case would be
drop procedure IF EXISTS migrate_custom_fields;
CREATE PROCEDURE migrate_custom_fields()
BEGIN
IF ((SELECT count(1)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'custom_field_instance_data'
and column_name='entity_id' and is_nullable = false) > 0)
THEN
alter table custom_field_instance_data MODIFY COLUMN entity_id char(32) null;
END IF;
END ;
call migrate_custom_fields;
drop procedure migrate_custom_fields;
I'm trying to create a stored procedure in a MySQL database using the contents of a text file:
USE myDatabase;
DROP PROCEDURE IF EXISTS myStoredProcedure;
DELIMITER $$
CREATE PROCEDURE myStoredProcedure
(
_description VARCHAR(50),
_value INT
)
BEGIN
INSERT INTO myTable
(
description,
value
) VALUES (
_description,
_value
);
SELECT
id,
description,
value
FROM myTable
WHERE id = LAST_INSERT_ID();
END;
$$
DELIMITER ;
I execute the SQL using a native query:
Query query = entityManager.createNativeQuery(queryText);
...
query.executeUpdate();
But it gets an error on the DROP PROCEDURE
I commented out the DROP PROCEDURE and then it gets an error on the DELIMITER
Basically, it gets an error on any line after the first semicolon.
It seems as if JPA hibernate is parsing my query and telling me there's a problem with it rather than passing the unadulterated text onto MySQL.
The sql runs in MySQL without error.
I can't find anything in Google about creating a stored procedure with JPA, only calling one.
Does anyone have any insight on what I might be doing wrong? Or if this is even possible.
This can be possible if you mention the following property in the url
spring.datasource.url=jdbc:mysql://localhost:3306/test?allowMultiQueries=true
The allowMultiQueries will instruct the driver to sent delimited queries to the database.
Please note that if you are using native queries be-aware of sql injection attack.
You dont need to put the delimiter(DELIMITER) explicitly.The sql statement
The following query works
SET myDatabase;
DROP PROCEDURE IF EXISTS myStoredProcedure;
CREATE PROCEDURE myStoredProcedure ( _description VARCHAR(50), _value INT )
BEGIN
INSERT INTO
myTable ( description, value )
VALUES ( _description, _value );
SELECT id, description, value
FROM myTable
WHERE id = LAST_INSERT_ID();
END;
There are two database connection in project.
1. oracle database
2. mssql database
Database connection is OK. Issue is when data transferred/inserted in one database[oracle] then it is display error and same time data inserted in another database[mssql] successfully.Insert query is fine but there is another query which is generate sequesnce number. There have problem.
This is the query which belongs to oracle database
return jdbcTemplate.queryForObject("SELECT 'AK'||LPAD(adds_seq.NEXTVAL,13, '0') adds_seq_no FROM sys.dual ",String.class);
Error is :
SELECT 'AK'||LPAD(adds_seq.NEXTVAL,13, '0') adds_seq_no FROM sys.dual ",String.class ]; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '|'.
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:98)
It is working well before when there is no mssql connection.
Below query is for oracle database. When I tried to change code like this:
String sql = " SELECT 'AK'||LPAD(adds_seq.NEXTVAL,13, '0') adds_seq_no FROM sys.dual";
String adSeqNum = null;
try {
adSeqNum = jdbcTemplate.queryForObject(sql, String.class);
} catch (Exception e) {
e.printStackTrace();
}
return addSeqNum;
then the error is
org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL []; ORA-01400: cannot insert NULL into ("ADDSS_HST"."ADDS_SEQ_NO")
1.Can you guide me how to solve this issue?
2.Can you please give me example for how to do separate database connection on one java file?
The "Incorrect syntax near '|'" happens because you are sending the Oracle statement "SELECT 'AK'||LPAD(adds_seq.NEXTVAL,13, '0') adds_seq_no FROM sys.dual " to the MSSQL server connection.
The second error, cannot insert null into "ADDSS_HST"."ADDS_SEQ_NO" I suspect happens because before the posted sql that selects from the sequence, you are inserting records into ADDSS_HST table. Is this correct? If so, I recommend that you put the code that generates adds_seq_no into a trigger like the one below (adjust names for your needs):
CREATE OR REPLACE TRIGGER "APPLICATION_BI_TRG"
BEFORE INSERT ON APPLICATION
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
BEGIN
if :new.application_id is null then
// if no value was given in insert statement for column application_id
SELECT APP_WEB_ID_SEQ.NEXTVAL INTO :NEW.application_id FROM dual;
// select a value from sequence into :NEW.application_id
end if;
END;
/
Why does this statement work fine in workbench but not in Java.
SET #sqlstmt := IF( #exist <= 0, 'select ''INFO: Key does not exist.''', 'ALTER TABLE `SOMETABLE` DROP FOREIGN KEY `SOMEKEY`');
In Java I get
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 'SET #sqlstmt := IF( #exist <= 0, 'select ''INFO: Key does not exist.''', 'ALTER ' at line 1
It turned out to be the fact that multiple statements were being executed (separated by semicolons). In JDBC MYSQL you need allowMultiQueries=true