无法从 .sql 文件创建存储过程 - JDBC

Posted

技术标签:

【中文标题】无法从 .sql 文件创建存储过程 - JDBC【英文标题】:Cannot create stored procedure from .sql file - JDBC 【发布时间】:2012-03-10 22:31:06 【问题描述】:

我正在尝试使用 jdbc 在安装我的 Web 项目期间执行一个 .sql 文件。谷歌建议的 2 个选项:手动解析脚本(通过拆分“;”字符)或使用 ant.我更喜欢简单的方法,所以 ant 是一个不错的选择。这是我用来设置数据库的代码:

public void executeSql(String sqlFilePath) 
        final class SqlExecuter extends SQLExec 
            public SqlExecuter() 
                Project project = new Project();
                project.init();
                setProject(project);
                setTaskType("sql");
                setTaskName("SQL Init");
            
        

        SqlExecuter executer = new SqlExecuter();
        executer.setSrc(new File(sqlFilePath));
        executer.setDriver("com.mysql.jdbc.Driver") ;
        executer.setPassword("123456");
        executer.setUserid("root");
        executer.setUrl("jdbc:mysql://localhost:3306/abc");
        executer.execute();
    

代码工作正常,直到满足创建过程的部分

DELIMITER //
CREATE PROCEDURE LOG (IN period INT)
BEGIN
    INSERT INTO log_archive
        SELECT * FROM ablog
            WHERE log_date < DATE_SUB(CURRENT_DATE(), INTERVAL period DAY);
    DELETE FROM ablog
        WHERE log_date < DATE_SUB(CURRENT_DATE(), INTERVAL period DAY);
END//
DELIMITER ;

并给出这个错误:

原因:com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:你的SQL语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的“DELIMITER // CREATE PROCEDURE LOG(IN period INT) BEGIN INSERT INTO log_archi”附近使用正确的语法

如果我删除存储过程部分,那么它将运行良好。 sql 文件也从 mysql 命令提示符成功执行。你有什么建议来解决这个问题吗?

【问题讨论】:

【参考方案1】:

考虑使用liquibase 之类的工具。它支持mysql,但有一些小问题。

【讨论】:

我认为这是从单独的文件中执行存储过程的唯一方法。谢谢你的链接 @bubuzz :不,任何人都可以加载一个sql,根据SQL引擎格式化,然后调用JDBC。 Liquibase 做得更好:)【参考方案2】:

试试这个方法 http://forums.mysql.com/read.php?46,271411,271411

CREATE PROCEDURE LOG (period INT)
BEGIN
    INSERT INTO log_archive
        SELECT * FROM ablog
            WHERE log_date < CURRENT_DATE- INTERVAL period DAY;
    DELETE FROM ablog
        WHERE log_date < CURRENT_DATE - INTERVAL period DAY;
END

如果需要,您可以添加分隔符在命令行中运行它 mysql&gt;\. yoursqlfile.sql 它刚刚从命令行使用delimiter //END// 工作。


命令行:

delimiter //
CREATE PROCEDURE LOG (period INT)
BEGIN
    INSERT INTO log_archive
        SELECT * FROM ablog
            WHERE log_date < CURRENT_DATE- INTERVAL period DAY;
    DELETE FROM ablog
        WHERE log_date < CURRENT_DATE - INTERVAL period DAY;
END//

希望对你有所帮助

【讨论】:

是的,我也在创建问题后尝试过。我也收到此错误消息 Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax;检查与您的 MySQL 服务器版本相对应的手册,以在第 1 行的 '' 附近使用正确的语法。显然,当我创建包含它的字符串并使用 executeUpdate 时,没有分隔符的代码运行良好 @bubuzzz 你检查过这个链接吗docs.oracle.com/javase/tutorial/jdbc/basics/… 他们也有例子 感谢您的链接。我也试过了。也许这可能是它不起作用的原因bugs.mysql.com/bug.php?id=58425。希望它会帮助一些人。不过还是找不到解决办法 作为一种解决方案,您可以将过程放在 SQL 文件中并在部署应用程序之前运行它。这也是一种正常的做法。【参考方案3】:

如果您只使用一个分隔符(例如\\ 或我使用了$$)并且不更改中间脚本(没有DELIMITER XX),那么您可以运行相当复杂的脚本。

dbConnection = DriverManager.getConnection(connectionString, user, password);
statement = dbConnection.createStatement();
for (String sqlpart : sqlFileContents.split("\\$\\$"))

    if (!sqlpart.trim().isEmpty())
        statement.addBatch(sqlpart);

statement.executeBatch();

例如

DROP PROCEDURE IF EXISTS Log $$
CREATE PROCEDURE Log (period INT)
BEGIN
    INSERT INTO log_archive
        SELECT * FROM ablog
            WHERE log_date < CURRENT_DATE- INTERVAL period DAY;
    DELETE FROM ablog
        WHERE log_date < CURRENT_DATE - INTERVAL period DAY;
END $$

【讨论】:

以上是关于无法从 .sql 文件创建存储过程 - JDBC的主要内容,如果未能解决你的问题,请参考以下文章

使用JDBC从Java调用Oracle SQL中的存储过程的示例

JDBC 调用函数或存储过程

从 SQL 存储过程创建/更改

无法从 TST(SQL 自动化工具)执行远程存储过程

无法使用存储过程pyodbc SQL SERVER创建数据库

JDBC调用存储过程的例子