mysql中statement_Statement (操作 SQL 语句)

Statement, PreparedStatement, CallableStatement

一旦建立好连接, 就可以与数据库交互. JDBC 中Statement, PreparedStatement 和 CallableStatement 提供了SQL操作的相关API. 其中 CallableStatement 继承自 PreparedStatement, 而 PreparedStatement 又继承自 Statement. 他们的区别是:

Statement 提供基本的 SQL 操作. 适合静态SQL语句, 且传入的 SQL 语句无法接受参数.

PreparedStatement 可以在 SQL 中传递参数, 适合多次使用的 SQL 语句.

CallableStatement 可以调用 PL/SQL 存储过程.

尽管接口功能有不同, 但是使用方式大体相同, 分以下几步:

创建 Statement

执行 SQL 语句

关闭 Statement

在执行 SQL 语句的时候, 常用以下几个方法:

boolean execute(String SQL) : 如果有 ResultSet 产生返回true, 否则, 返回 false. 一般用于 CREATE, ALTER 这些操作, 或者用来检查一个Query有没有返回.

int executeUpdate(String SQL) : 返回被影响的记录的条数, 一般用于 INSERT, UPDATE, DELETE 这些操作.

ResultSet executeQuery(String SQL) : 返回查询结果集, 专用语 SELECT.

以下三个例子分别示例了如何适用他们.

Statement 例子.

public class StatementExample {

private Properties dbProps = new Properties();

StatementExample() {}

public void setDBProperties(Properties dbProps) {

this.dbProps = dbProps;

}

public Connection getConnection() throws SQLException {

String url = dbProps.getProperty("url");

String user = dbProps.getProperty("user");

Connection conn = null;

if (user.length() == 0) {

conn = DriverManager.getConnection(url);

} else {

conn = DriverManager.getConnection(url, dbProps);

}

String dbName = dbProps.getProperty("dbName");

conn.setCatalog(dbName);

return conn;

}

public void deleteAll() throws SQLException {

String sql = "DELETE FROM posts";

Connection conn = getConnection();

Statement stmt = conn.createStatement();

int nRows = stmt.executeUpdate(sql);

System.out.println(nRows + (nRows == 1 ? " post is " : " posts are ") + "deleted.");

stmt.close();

conn.close();

}

public void insertPost(Post post) throws SQLException {

String sql = "INSERT INTO posts VALUES";

String title = post.getTitle();

String content = post.getContent();

Boolean visible = post.isVisible();

sql += "("

+ "NULL" + ","

+ "\"" +title + "\"" + ","

+ "\"" + content + "\"" + ","

+ "DEFAULT" + ","

+ (visible ? "TRUE" : "FALSE")

+ ")";

Connection conn = getConnection();

Statement stmt = conn.createStatement();

int nRows = stmt.executeUpdate(sql);

stmt.close();

conn.close();

}

public ArrayList<Post> queryAll() throws SQLException {

ArrayList<Post> list = new ArrayList<Post>();

String sql = "SELECT * FROM posts";

Connection conn = getConnection();

Statement stmt = conn.createStatement();

ResultSet rs = stmt.executeQuery(sql);

rs.beforeFirst();

while (rs.next()) {

Post temp = new Post();

temp.setId(rs.getInt("id"));

temp.setTitle(rs.getString("title"));

temp.setContent(rs.getString("content"));

temp.setDate(rs.getTimestamp("dt_create"));

temp.setVisible(rs.getBoolean("visible"));

list.add(temp);

}

stmt.close();

conn.close();

return list;

}

public static void main(String[] args) {

try {

Properties props = new Properties();

props.load(ClassLoader.getSystemResourceAsStream("db.mysql.props"));

StatementExample example = new StatementExample();

example.setDBProperties(props);

ArrayList<Post> posts = example.queryAll();

System.out.println(posts);

Post toInsert = new Post();

toInsert.setTitle("new Post");

toInsert.setContent("This is a new post!");

example.insertPost(toInsert);

posts = example.queryAll();

System.out.println(posts);

example.deleteAll();

posts = example.queryAll();

System.out.println(posts);

} catch (SQLException e) {

DBUtils.printSQLException(e);

} catch (Exception e) {

e.printStackTrace();

}

}

}

PreparedStatement 例子.

public class PreparedStatExample {

private Properties dbProps = new Properties();

PreparedStatExample() {}

public void setDBProperties(Properties dbProps) {

this.dbProps = dbProps;

}

public Connection getConnection() throws SQLException {

String url = dbProps.getProperty("url");

String user = dbProps.getProperty("user");

Connection conn = null;

if (user.length() == 0) {

conn = DriverManager.getConnection(url);

} else {

conn = DriverManager.getConnection(url, dbProps);

}

String dbName = dbProps.getProperty("dbName");

conn.setCatalog(dbName);

return conn;

}

public void deletePost(int id) throws SQLException {

String sql = "DELETE FROM posts WHERE id = ?";

Connection conn = getConnection();

PreparedStatement stmt = conn.prepareStatement(sql);

stmt.setInt(1, id);

stmt.executeUpdate();

DBUtils.printWarnings(stmt.getWarnings());

stmt.close();

conn.close();

}

public void insertPost(Post post) throws SQLException {

String sql = "INSERT INTO posts VALUES(NULL, ?, ?, DEFAULT, ?)";

Connection conn = getConnection();

PreparedStatement stmt = conn.prepareStatement(sql);

stmt.setString(1, post.getTitle());

stmt.setString(2, post.getContent());

stmt.setBoolean(3, post.isVisible());

stmt.executeUpdate();

DBUtils.printWarnings(stmt.getWarnings());

stmt.close();

conn.close();

}

public ArrayList<Post> queryByTitle(String title) throws SQLException {

ArrayList<Post> list = new ArrayList<Post>();

String sql = "SELECT * FROM posts WHERE title like ?";

Connection conn = getConnection();

PreparedStatement stmt = conn.prepareStatement(sql);

stmt.setString(1, title);

ResultSet rs = stmt.executeQuery();

rs.beforeFirst();

while (rs.next()) {

Post temp = new Post();

temp.setId(rs.getInt("id"));

temp.setTitle(rs.getString("title"));

temp.setContent(rs.getString("content"));

temp.setDate(rs.getTimestamp("dt_create"));

temp.setVisible(rs.getBoolean("visible"));

list.add(temp);

}

stmt.close();

conn.close();

return list;

}

public static void main(String[] args) {

try {

Properties props = new Properties();

props.load(ClassLoader.getSystemResourceAsStream("db.mysql.props"));

PreparedStatExample example = new PreparedStatExample();

example.setDBProperties(props);

// 此时数据库中有一条 title 为 111 的数据

ArrayList<Post> posts = example.queryByTitle("111");

System.out.println(posts); //[Post{id=34, title='111', content='111', date=2015-01-25 12:58:32.0, visible=true}]

Post toInsert = new Post();

toInsert.setTitle("111");

toInsert.setContent("111111");

example.insertPost(toInsert);

posts = example.queryByTitle("111");

System.out.println(posts); // [Post{id=39, title='111', content='111', date=2015-01-25 13:00:49.0, visible=true}, Post{id=41, title='111', content='111111', date=2015-01-25 13:00:59.0, visible=false}]

example.deletePost(posts.get(0).getId());

posts = example.queryByTitle("111");

System.out.println(posts); // [Post{id=41, title='111', content='111111', date=2015-01-25 13:00:59.0, visible=false}]

} catch (SQLException e) {

DBUtils.printSQLException(e);

} catch (Exception e) {

e.printStackTrace();

}

}

}

CallableStatement 例子.

public class CallableStatExample {

private Properties dbProps = new Properties();

public CallableStatExample() {}

public void setDBProperties(Properties dbProps) {

this.dbProps = dbProps;

}

public Connection getConnection() throws SQLException {

String url = dbProps.getProperty("url");

String user = dbProps.getProperty("user");

Connection conn = null;

if (user.length() == 0) {

conn = DriverManager.getConnection(url);

} else {

conn = DriverManager.getConnection(url, dbProps);

}

String dbName = dbProps.getProperty("dbName");

conn.setCatalog(dbName);

return conn;

}

public String getTitleById(int id) throws SQLException {

Connection conn = getConnection();

String sql = "{call getTitleById (?, ?)}";

CallableStatement stmt = conn.prepareCall(sql);

// 绑定传入参数

stmt.setInt(1, id);

// 对于传出参数, 要先注册

stmt.registerOutParameter(2, java.sql.Types.VARCHAR);

stmt.execute();

String title = stmt.getString(2);

stmt.close();

conn.close();

return title;

}

public static void main(String[] args) throws IOException, SQLException {

Properties props = new Properties();

props.load(ClassLoader.getSystemResourceAsStream("db.mysql.props"));

CallableStatExample example = new CallableStatExample();

example.setDBProperties(props);

int id = 35;

String title = example.getTitleById(id);

System.out.println("Find title : " + title + " by ID : " + id); // Find title : 222 by ID : 35

}

}

Note: 请先将以下存储过程存入 MySQL 数据库

DELIMITER $$

CREATE PROCEDURE `testdb`.`getTitleById`

(IN post_id INT, OUT post_name VARCHAR(255))

BEGIN

SELECT title INTO post_name

FROM posts

WHERE ID = post_id;

END $$

DELIMITER ;

SQL 的批处理操作

SQL 批处理能够允许添加多个 SQL 到 一个Statement对象, 并一并提交执行结果. 这减少了与 SQL 通信的频率. 但是, SQL 批处理不是 JDBC 要求一定要支持的. 使用前应该用 DatabaseMetaData.supportsBatchUpdates() 检查支持情况.

SQL 批处理相关的 API 有:

Statement.addBatch(): 往批处理中添加 SQL 语句

Statement.executeBatch(): 执行批处理, 并返回一个整型数组, 其中每个元素代表对应序号 SQL 的执行结果.

Statement.clearBatch(): 从批处理中删除已添加的所有 SQL 语句.

以下示例如何使用批处理往数据库添加数据:

public static void batchInsertPosts(ArrayList posts) throws SQLException {

Connection conn = getConnectionFromDS(dbProps);

conn.setAutoCommit(false); // 见 "事务" 一章

DatabaseMetaData md = conn.getMetaData();

System.out.println("If support batch updates: " + md.supportsBatchUpdates());

String sql = "INSERT INTO POSTS\n"

+ "VALUES(NULL, ?, ?, DEFAULT, ?)";

PreparedStatement stmt = conn.prepareCall(sql);

try {

for (Post post : posts) {

stmt.setString(1, post.getTitle());

stmt.setString(2, post.getContent());

stmt.setBoolean(3, post.isVisible());

stmt.addBatch();

}

stmt.executeBatch();

conn.commit();

} catch (SQLException e) {

DBUtils.printSQLException(e);

conn.rollback();

}

DBUtils.printWarnings(stmt.getWarnings());

stmt.close();

conn.close();

}

SQL 异常处理

JDBC 中最常用的异常就是 SQLException, 不管是在建立连接, 还是在执行 SQL 语句的时候, 都有可能抛出这个异常. SQLException 包含以下信息:

关于错误的描述. 通过调用getMessage() 获得.

一个 SQL 状态码. 通过调用 getSQLState( ) 获取. SQL 状态码由5位字母和数字组成, 符合 XOPEN 规范.

一个错误码. 这个错误码的含义由实现规定, 有可能是数据库的错误码. 通过调用 SQLException.getErrorCode() 获取.

错误缘由. 引发异常的缘由, 有可能是一个或者多个 Throwable 的对象组成的一条链. 要想检查这些缘由, 要递归遍历 SQLException.getCause() 直到返回一个 null.

异常链. 通过 getNextException() 获取下一个异常.

以下代码示例如何打印异常链中的每个SQLException异常, 并且打印每个异常的 cause 链.

public static void printSQLException(SQLException ex) {

for (Throwable e : ex) { // Iterator 会调用 getNextException()

if (e instanceof SQLException) {

e.printStackTrace(System.err);

System.err.println("SQLState: " +

((SQLException)e).getSQLState());

System.err.println("Error Code: " +

((SQLException)e).getErrorCode());

System.err.println("Message: " + e.getMessage());

Throwable t = ex.getCause();

while(t != null) { // 打印每个 cause

System.out.println("Cause: " + t);

t = t.getCause();

}

}

}

}

除了发生致命错误产生抛出 SQLException 之外, Connection, Statement, ResultSet 都有一个 getWarnings() 方法, 它返回一个 SQLWarning. SQLWarning 继承自 SQLException, 可以向遍历 SQLException 一样遍历它:

public static void printWarnings(SQLWarning warning)

throws SQLException {

while (warning != null) {

System.out.println("Message: " + warning.getMessage());

System.out.println("SQLState: " + warning.getSQLState());

System.out.print("Vendor error code: ");

System.out.println(warning.getErrorCode());

System.out.println("");

warning = warning.getNextWarning();

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在shell脚本执行sql语句操作MySQL一般有以下五种方法: 1. 使用mysql命令行工具执行sql语句 使用mysql命令行工具可以直接连接MySQL数据库,执行SQL语句。在shell脚本可以使用以下方式: ``` #!/bin/bash mysql -u user_name -pthe_password -h host_name -D database_name -e "sql_statement" ``` 其,-u表示指定连接的用户名称,-p表示连接使用密码,-h表示数据库连接地址,-D表示指定连接的数据库名称,-e表示执行的sql语句。 2. 使用mysql客户端执行sql文件 将需要执行的sql语句以文件的形式输入到mysql客户端执行。在shell脚本可以使用以下方式: ``` #!/bin/bash mysql -u user_name -pthe_password -h host_name -D database_name < sql_file ``` 其,<表示重定向标准输入,将sql_file的内容传入mysql客户端,-u表示指定连接的用户名称,-p表示连接使用密码,-h表示数据库连接地址,-D表示指定连接的数据库名称。 3. 使用mysqldump命令备份数据库 使用mysqldump命令备份MySQL数据库,也可以将备份的数据库数据导入到MySQL数据库。在shell脚本可以使用以下方式: ``` #!/bin/bash mysqldump -u user_name -pthe_password database_name > sql_file ``` 其,>表示重定向标准输出,将备份的数据写入sql_file,-u表示指定连接的用户名称,-p表示连接使用密码,database_name表示指定备份的数据库名称。 4. 使用Shell函数封装MySQL操作MySQL操作封装到Shell函数,可以提高数据库操作的灵活性和复用性。在shell脚本可以使用以下方式: ``` #!/bin/bash function execute_sql() { mysql -u user_name -pthe_password -h host_name -D database_name -e "$1" } ``` 其,$1表示传入的SQL语句参数。 5. 使用第三方脚本库或工具 可以使用第三方的脚本库或工具,实现对MySQL数据库的操作。例如,可以使用MyBatis、Flyway等库或工具来实现数据库操作。这些库或工具提供了更加方便的数据库操作方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值