package com.unmi.db;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 读取 SQL 脚本并执行
* @author Unmi
*/
public class SqlFileExecutor {
/**
* 读取 SQL 文件,获取 SQL 语句
* @param sqlFile SQL 脚本文件
* @return List<sql> 返回所有 SQL 语句的 List
* @throws Exception
*/
private List<String> loadSql(String sqlFile) throws Exception {
List<String> sqlList = new ArrayList<String>();
try {
InputStream sqlFileIn = new FileInputStream(sqlFile);
StringBuffer sqlSb = new StringBuffer();
byte[] buff = new byte[1024];
int byteRead = 0;
while ((byteRead = sqlFileIn.read(buff)) != -1) {
sqlSb.append(new String(buff, 0, byteRead));
}
// Windows 下换行是 \r\n, Linux 下是 \n
String[] sqlArr = sqlSb.toString().split("(;\\s*\\r\\n)|(;\\s*\\n)");
for (int i = 0; i < sqlArr.length; i++) {
String sql = sqlArr[i].replaceAll("--.*", "").trim();
if (!sql.equals("")) {
sqlList.add(sql);
}
}
return sqlList;
} catch (Exception ex) {
throw new Exception(ex.getMessage());
}
}
/**
* 传入连接来执行 SQL 脚本文件,这样可与其外的数据库操作同处一个事物中
* @param conn 传入数据库连接
* @param sqlFile SQL 脚本文件
* @throws Exception
*/
public void execute(Connection conn, String sqlFile) throws Exception {
Statement stmt = null;
List<String> sqlList = loadSql(sqlFile);
stmt = conn.createStatement();
for (String sql : sqlList) {
stmt.addBatch(sql);
}
int[] rows = stmt.executeBatch();
System.out.println("Row count:" + Arrays.toString(rows));
}
/**
* 自建连接,独立事物中执行 SQL 文件
* @param sqlFile SQL 脚本文件
* @throws Exception
*/
public void execute(String sqlFile) throws Exception {
Connection conn = DBCenter.getConnection();
Statement stmt = null;
List<String> sqlList = loadSql(sqlFile);
try {
conn.setAutoCommit(false);
stmt = conn.createStatement();
for (String sql : sqlList) {
stmt.addBatch(sql);
}
int[] rows = stmt.executeBatch();
System.out.println("Row count:" + Arrays.toString(rows));
DBCenter.commit(conn);
} catch (Exception ex) {
DBCenter.rollback(conn);
throw ex;
} finally {
DBCenter.close(null, stmt, conn);
}
}
public static void main(String[] args) throws Exception {
List<String> sqlList = new SqlFileExecutor().loadSql(args[0]);
System.out.println("size:" + sqlList.size());
for (String sql : sqlList) {
System.out.println(sql);
}
}
}
Connection conn = DBCenter.getConnection();这个DBCenter的类你是怎么写的
现在手头没有了,就是些管理连接,处理结果集之类的工具方法。
您好,我想定时执行 export to c:\pro.ixf of ixf select * from pro 。这样的 sql 。是db2的。可以吗?这个是单表导出数据的写法。
这是与数据库相关的命令了,如果是 Statement.execute() 能执行的 SQL 语句就行
try iBATIS ^^
确实,刚开始着手解决这个问题的时候考虑过用 iBatis。考虑到 iBatis 对一条语句一个配置的确很合适,但要一个脚本文件中批处理的执行 SQL 语句就有欠妥。也参考过 ANT 中的 任务的实现,但也是针对一条语句的执行。
@隔叶黄莺
ant执行一个sql文件完全没有问题...
所有的sql放到一个文件中...
谢谢楼上的提醒,我再次查了一下 ant 文档,执行 SQL 脚本文件,和多条 SQL 语句都行,它有的例子是:
<sql driver="org.database.jdbcDriver" url="jdbc:database-url" userid="sa" password="pass" src="data.sql"/>
和
<sql driver="org.database.jdbcDriver" url="jdbc:database-url" userid="sa" password="pass" >
insert
into table some_table values(1,2,3,4);
truncate table some_other_table; </sql>
所以如果是写在代码里,完全可以参考 ANT 源代码,它的实现考虑的更完善。把东西写下来,众人众说,总能起到抛砖引玉的作用。
建议试试groovy来进行这项工作,so easy
脚本语言个人还是习惯 Perl,它那强大的正则表达式是无与伦比的。有说 Perl 不适合于大项目,确实,但如果是大项目,我又会选择用 Java。groovy 还不太习惯,虽说它写的东西也是编译成 JVM 可执行的字节码,还能使用到 Java 的任何特性,但觉得有点麻烦,语法也不适应,Ruby就更不用说了,还会激起民族情绪。Perl 写界面也行,可以用好几个界面组件库,如 TK、wxWidgets 或 QT。
还会进一步发掘 Ant 是如何提供执行 SQL 脚本文件支持的。
请问SQL脚本中的语句有错误该怎么处理
那就是事物务理要做的事情了
如果我想执行的是一个建立存储过程的SQL脚本呢?
存储过程建立本身不是一句一句执行的,请问能否使用程序进行整个存储过程SQL执行呢?
loadSql 中的 InputStream sqlFileIn 忘记关闭了
加入有这样一个sql:
INSERT INTO ×××(title, content) VALUES('这是标题', '内容;内容');
因为“'内容;内容'”中有“;”这个程序会出错的
为什么我用了楼主的方法,一到执行那条语句就出错了?
楼主有 测试过么,期待回复
@Lc
用分号分隔的,所以会出错,这是我当时的一个项目中因为需求简单才自己写了一个这样的程序,如果要功能强的话,最好参考下 ant 和 dbUnit 的做法。