我在为MariaDB创建SP时遇到了一个有趣的问题。 当我直接从HeidiSQL(MySql的db客户端应用程序)执行DDL以下时,我可以轻松创建SP。
DROP PROCEDURE IF EXISTS `sp_delete_merchant`;
CREATE PROCEDURE `sp_delete_merchant`(IN `mer_id` BIGINT)
BEGIN
DECLARE stop BIT DEFAULT FALSE;
DECLARE comm_id BIGINT;
DECLARE commodities CURSOR FOR SELECT id FROM tbl_commodity WHERE merchant_id = mer_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET stop = TRUE;
# DELETE RECORDS FROM tbl_package2commodity BASED ON COMMODITY ID
OPEN commodities;
read_loop: LOOP
FETCH commodities INTO comm_id;
DELETE FROM tbl_package2commodity WHERE commodity_id = comm_id;
IF stop THEN
LEAVE read_loop;
END IF;
END LOOP;
CLOSE commodities;
# DELETE RECORDS FROM OTHER TABLES BASED ON MERCHANT ID
DELETE FROM tbl_commodity WHERE merchant_id = mer_id;
DELETE FROM tbl_package WHERE merchant_id = mer_id;
DELETE FROM tbl_contact_person WHERE merchant_id = mer_id;
DELETE FROM tbl_sales_force WHERE merchant_id = mer_id;
DELETE FROM tbl_merchant WHERE id = mer_id;
END;
但是当我尝试从Spring JdbcTemplate 执行上面的DDL时,如下代码:
public class DbStoreProceduresCreator implements InitializingBean {
private static Logger log = LoggerFactory.getLogger(DbStoreProceduresCreator.class);
@Value("classpath:com/litaal/commerce/config/setup_store_procedures.sql")
private Resource createStoreProcedures;
@Autowired
private DataSource coreDS;
@Override
public void afterPropertiesSet() throws Exception {
BufferedReader br = null;
StringBuffer sql = new StringBuffer();
try {
InputStream is = createStoreProcedures.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = br.readLine()) != null) {
sql.append(line);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (br != null) {
br.close();
}
}
if (sql.length() > 0) {
try {
JdbcTemplate tmp = new JdbcTemplate(coreDS);
tmp.execute(sql.toString());
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
}
它会抛出如下错误:
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 '' at line 1
我已经尝试使用谷歌搜索并改变我的脚本十次或更多次,但仍然无法找到我的DDL有什么问题。
我想从我的Java应用程序创建SP的原因是为了让我的应用程序尽可能便携,而无需对数据库执行任何操作。
答案 0 :(得分:1)
事实证明,JdbcTemplate
无法在选择/更新等过程中执行带有注释(#
)(--
)的SQL过程。JdbcTemplate
执行此操作在语句的开头支持(--
,#
)注释,以便:
-- --------------------------------------------
-- Summary Comments!
-- Note: This comes before a delimited statement (;).
# These are okay too.
-- --------------------------------------------
SELECT *
FROM User
-- This comment fails.
WHERE id > 0;
这是我如何分解程序(来自MySQL)。
<强>程序强>
USE `DbName`;
DROP procedure IF EXISTS `ProcName`;
DELIMITER $$
USE `DbName`$$
CREATE PROCEDURE `ProcName` ()
BEGIN
# Here's a comment that would normally fail.
SELECT
u.id
FROM
User as u
END$$
DELIMITER ;
<强>分析器强>
StringBuilder builder = new StringBuilder();
String[] lines = script.split("\n");
String delimiter = ";";
for (int i = 0; i < lines.length; i++) {
String line = lines[i];
if (line.contains("DELIMITER")) {
String[] tokens = line.split(" ");
delimiter = tokens[1];
builder = new StringBuilder();
continue;
}
//Comments cannot be executed properly by the JdbcTemplate, strip them out.
if (line.contains("#")) {
line = line.substring(0, line.indexOf('#'));
}
if (line.contains(delimiter)) {
builder.append(line.replace(delimiter, ""));
template.execute(builder.toString());
builder = new StringBuilder();
} else {
builder.append(line);
}
}
答案 1 :(得分:0)
也许您的代码存在一些问题,但其中一个问题是JdbcTemplate.execute(String sql)
只执行一个语句
/**
* Issue a single SQL execute, typically a DDL statement.
* @param sql static SQL to execute
* @throws DataAccessException if there is any problem
*/
void execute(String sql) throws DataAccessException;
因此,您必须将执行分为两次执行,一次针对DROP PROCEDURE IF EXISTS "sp_delete_merchant";
,另一次针对其余的执行。
BTW:你应该看看org.springframework.jdbc.datasource.init.ScriptUtils
另一件让我感到担忧的事情是你的字符串引号。
答案 2 :(得分:0)
最后......我找到了答案。 问题在于 JdbcTemplate 如何执行SQL脚本。它逐行执行(由新行分隔)。所以我更改了部分代码以删除所有新行,如下面的
....
if (sql.length() > 0) {
String query = sql.toString().replaceAll("\\n", " ");
query = query.replaceAll("\\t", " ");
log.info(query);
try {
JdbcTemplate tmp = new JdbcTemplate(dataSource);
tmp.execute(query);
} catch (Exception e) {
log.error(e.getMessage());
}
}
...
现在一切都像魅力一样。