如何在java中执行复合sql查询?
Posted
技术标签:
【中文标题】如何在java中执行复合sql查询?【英文标题】:How to execute composite sql queries in java? 【发布时间】:2011-10-10 01:05:12 【问题描述】:如何执行以下查询并通过准备好的语句检索结果:
INSERT INTO vcVisitors (sid) VALUES (?); SELECT LAST_INSERT_ID();
有没有办法同时执行两条语句?
我已尝试执行以下操作:
Connection con = DbManager.getConnection();
PreparedStatement ps = con.PrepareStatement(
"INSERT INTO vcVisitors (sid) VALUES (?); SELECT LAST_INSERT_ID();");
ps.setInt(1, 10);
ResultSet rs = ps.exequteQuery();
rs.next();
return rs.getInt("LAST_INSERT_ID()");
但它给了我一个错误,executeQuery 无法执行这样的查询, 我还尝试将 executeQuery 替换为以下内容:
ps.execute();
rs = ps.getResultSet();
但它给了我 SQL 语法错误:
You have an error in your SQL syntax;
check the manual that corresponds to your mysql server version
for the right syntax to use near 'SELECT LAST_INSERT_ID()' at line 1
但是执行查询没有问题 "INSERT INTO vcVisitors (sid) VALUES ('10'); SELECT LAST_INSERT_ID();" 直接从 mysql 控制台。
【问题讨论】:
我认为这不可能。尤其是INSERT
和SELECT
。
【参考方案1】:
更新(插入)数据时使用executeUpdate
而不是executeQuery
。尝试将SELECT LAST_INSERT_ID()
作为另一个查询执行。
但它不是可移植的查询。我建议改用Statement.getGeneratedKeys
。请看这里:JDBC (MySQL) Retrieving AUTO_INCREMENT Column Values。
以下是正确使用 LAST_INSERT_ID() 的示例:
Statement stmt = null;
ResultSet rs = null;
try
//
// Create a Statement instance that we can use for
// 'normal' result sets.
stmt = conn.createStatement();
//
// Issue the DDL queries for the table for this example
//
stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");
stmt.executeUpdate(
"CREATE TABLE autoIncTutorial ("
+ "priKey INT NOT NULL AUTO_INCREMENT, "
+ "dataField VARCHAR(64), PRIMARY KEY (priKey))");
//
// Insert one row that will generate an AUTO INCREMENT
// key in the 'priKey' field
//
stmt.executeUpdate(
"INSERT INTO autoIncTutorial (dataField) "
+ "values ('Can I Get the Auto Increment Field?')");
//
// Use the MySQL LAST_INSERT_ID()
// function to do the same thing as getGeneratedKeys()
//
int autoIncKeyFromFunc = -1;
rs = stmt.executeQuery("SELECT LAST_INSERT_ID()");
if (rs.next())
autoIncKeyFromFunc = rs.getInt(1);
else
// throw an exception from here
rs.close();
System.out.println("Key returned from " +
"'SELECT LAST_INSERT_ID()': " +
autoIncKeyFromFunc);
finally
if (rs != null)
try
rs.close();
catch (SQLException ex)
// ignore
if (stmt != null)
try
stmt.close();
catch (SQLException ex)
// ignore
这里与 getGeneratedKeys 相同:
Statement stmt = null;
ResultSet rs = null;
try
//
// Create a Statement instance that we can use for
// 'normal' result sets assuming you have a
// Connection 'conn' to a MySQL database already
// available
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_UPDATABLE);
//
// Issue the DDL queries for the table for this example
//
stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");
stmt.executeUpdate(
"CREATE TABLE autoIncTutorial ("
+ "priKey INT NOT NULL AUTO_INCREMENT, "
+ "dataField VARCHAR(64), PRIMARY KEY (priKey))");
//
// Insert one row that will generate an AUTO INCREMENT
// key in the 'priKey' field
//
stmt.executeUpdate(
"INSERT INTO autoIncTutorial (dataField) "
+ "values ('Can I Get the Auto Increment Field?')",
Statement.RETURN_GENERATED_KEYS);
//
// Example of using Statement.getGeneratedKeys()
// to retrieve the value of an auto-increment
// value
//
int autoIncKeyFromApi = -1;
rs = stmt.getGeneratedKeys();
if (rs.next())
autoIncKeyFromApi = rs.getInt(1);
else
// throw an exception from here
rs.close();
rs = null;
System.out.println("Key returned from getGeneratedKeys():"
+ autoIncKeyFromApi);
finally
if (rs != null)
try
rs.close();
catch (SQLException ex)
// ignore
if (stmt != null)
try
stmt.close();
catch (SQLException ex)
// ignore
【讨论】:
他特别想同时执行两个查询。【参考方案2】:尝试:
Connection con = DbManager.getConnection();
int lastid = 0;
PreparedStatement psInsert = con.PrepareStatement(
"INSERT INTO vcVisitors (sid) VALUES (?)");
psInsert.setInt(1, 10);
psInsert.executeUpdate();
PreparedStatement psSelect =
con.PrepareStatement("SELECT LAST_INSERT_ID() AS lastid");
ResultSet rs = psSelect.executeQuery();
rs.next();
lastid = rs.getInt("lastid");
rs.close();
psInsert.close();
psSelect.close();
con.close();
return lastid;
【讨论】:
是的,确实可行,但我的问题是如何一次执行多个查询 @tsds:但是两个查询总是作为两个查询运行。【参考方案3】:正如其他人已经说过的,这行不通。但看起来您只想获取最后插入的 ID。为此,您可以使用Statement
类的getGeneratedKeys()
方法。
【讨论】:
以上是关于如何在java中执行复合sql查询?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 java 中使用 jdbc 为 oracle 10g 执行 log miner PL/SQL 查询