【问题标题】:How can I execute this sql backup script with JDBC?如何使用 JDBC 执行此 sql 备份脚本?
【发布时间】:2017-04-02 13:15:10
【问题描述】:

如何使用 JDBC 对我的数据库实例执行以下查询,我尝试的一切都返回“无结果集”错误。

com.microsoft.sqlserver.jdbc.SQLServerException: The statement did not return a result set.

当我没有真正回顾数据时,我该怎么办?

.sql 文件

DECLARE @name VARCHAR(50) -- database name  
DECLARE @path VARCHAR(256) -- path for backup files  
DECLARE @fileName VARCHAR(256) -- filename for backup  
DECLARE @fileDate VARCHAR(20) -- used for file name
DECLARE @fileFolder VARCHAR(20) -- used for file name


-- specify database backup directory
SET @path = 'C:\SQLBackups\'


-- specify filename format
SELECT @fileDate = CONVERT(VARCHAR(20),GETDATE(),112) 


DECLARE db_cursor CURSOR FOR  
SELECT name 
FROM master.dbo.sysdatabases 
WHERE name NOT IN ('master','model','msdb','tempdb')  -- exclude these databases


OPEN db_cursor   
FETCH NEXT FROM db_cursor INTO @name   


WHILE @@FETCH_STATUS = 0   
BEGIN   
       SET @fileName = @path + @name + '_' + @fileDate + '.BAK'  
       BACKUP DATABASE @name TO DISK = @fileName  


       FETCH NEXT FROM db_cursor INTO @name   
END   


CLOSE db_cursor   
DEALLOCATE db_cursor

我执行上述查询的代码(到目前为止)

    public static void connect(String instance, String saPassword, String query)  {
    Connection conn = null;
    query = "DECLARE @name VARCHAR(50) -- database name   " +
            "DECLARE @path VARCHAR(256) -- path for backup files   " +
            "DECLARE @fileName VARCHAR(256) -- filename for backup   " +
            "DECLARE @fileDate VARCHAR(20) -- used for file name " +
            "-- specify database backup directory " +
            "SET @path = 'C:\\SQLBackups\\'   " +
            "-- specify filename format " +
            "SELECT @fileDate = CONVERT(VARCHAR(20),GETDATE(),112)  " +
            "DECLARE db_cursor CURSOR FOR   " +
            "SELECT name  " +
            "FROM master.dbo.sysdatabases  " +
            "WHERE name NOT IN ('master','model','msdb','tempdb')  -- exclude these databases " +
            "OPEN db_cursor    " +
            "FETCH NEXT FROM db_cursor INTO @name    " +
            "WHILE @@FETCH_STATUS = 0    " +
            "BEGIN    " +
            "       SET @fileName = @path + @name + '_' + @fileDate + '.BAK'   " +
            "       BACKUP DATABASE @name TO DISK = @fileName   " +
            "       FETCH NEXT FROM db_cursor INTO @name    " +
            "END    " +
            "CLOSE db_cursor    " +
            "DEALLOCATE db_cursor ";
    try {
        Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
        String dbURL = "jdbc:sqlserver://10.0.0.0\\"+ instance;
        String user = "user";
        String pass = saPassword;
        conn = DriverManager.getConnection(dbURL, user, pass);
        Statement stmt = conn.createStatement();
        stmt.executeQuery(query);

    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        try {
            if (conn != null && !conn.isClosed()) {
                conn.close();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

我可以在 SSMS 中很好地执行我的查询,将 .sql 文本转换为字符串会导致问题吗?我对这里的结果不太在意,因为它应该在服务器上创建很多 .bak 文件(当我通过 SSMS 执行它时确实会发生这种情况,我通过抓取一个简单的 SELECT 结果集来改变查询,它工作得很好,所以我现在有点迷路了。

覆盖该方法中的(查询)只是为了测试目的,一旦我将 .bak 文件登陆到远程服务器目录,我将整理它,凭据因显而易见的原因被屏蔽。

谢谢

【问题讨论】:

    标签: java sql-server jdbc


    【解决方案1】:

    您的代码不可读(因此难以维护),因为您将两种 SQL 和 Java 语言混合在一起,所以我强烈建议使用callableStatement,您可以查看here一个简单的例子。 简单来说,你需要将你所有的SQL代码移动到数据库中的一个过程中,然后callableStatement.execute()

    【讨论】:

    • 从技术上讲,您不能一次执行多个语句是正确的,但是allowMultiQueries=true 是特定于 MySQL 的,问题是关于 SQL Server。而且 SQL Server 显然确实允许执行多条语句。
    • 谢谢马克,我不知道它是特定于 MySQL 的,我已经更新了我的答案(现在只有一个选项)
    • 谢谢你们,我已将它添加为 SP 并调用它不会将我的文件放在服务器上,所以稍作休息后,我将开始解决现在发生的权限问题
    • 嗨 Javaguy,我终于看到了我在远程服务器上创建的 .bak 文件,非常棒。是否可以只使用 JDBC 执行查询,例如“EXEC DatabaseBackups”来调用 SP?这就是我正在做的事情及其目前的工作,但对你的想法感到好奇。也感谢@MarkRotteveel
    • 是的,没关系,你也可以用call DatabaseBackups
    【解决方案2】:

    在您的 java 代码中调用 execute() 而不是 executeQuery()。后者假设你的查询需要返回一个结果集,但前者不假设。

    所以,而不是:

    stmt.executeQuery(query);
    

    呼叫:

    stmt.execute(query);
    

    【讨论】:

    • 我改成stmt.execute(query);但是服务器上没有出现 .bak 文件,虽然它在运行时清除了异常,查询本身手动运行良好,我的查询字符串看起来可能是那里的问题吗?
    • 运行此代码的用户在服务器上的文件夹/文件写入权限如何?
    • 我假设因为我通过 JDBC 使用 sa 连接到 sql 实例(这也是我在 SSMS 上登录以手动执行它的同一用户,它会很好?现在将调查一些日志
    • 请检查C:\SQLBackups文件夹写入权限。并检查谁可以写入此文件夹。当您手动运行代码时,有效的 windows-user 是手动运行此代码的用户,但是当您通过 jdbc 进行调用时,有效的 windows 用户是正在用于运行的用户sql-agent 服务。
    • 这可能解释了我的另一个无法 makeDirectory() 的问题,有趣的是我会检查一下
    猜你喜欢
    • 2010-12-02
    • 1970-01-01
    • 2013-10-06
    • 2011-08-17
    • 2012-03-20
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    相关资源
    最近更新 更多