我是apache derby
的新手,我似乎无法开展工作
CREATE TABLE IF NOT EXISTS table1 ...
可以在MySql
等中实现。当我尝试在'Syntax error: Encountered "NOT" at line 1, column 17.'
程序中运行此SQL
语句时,我收到了Java
。
我在Derby Db Create Statements的文档页面中查看了,但找不到这样的替代方法。
答案 0 :(得分:25)
创建表,捕获SQLException
并检查SQL状态代码。
可以找到here 的完整错误代码列表,但找不到您需要的代码是Table <value> already exists
;它可能是X0Y68
。X0Y32
。
只需运行一次代码并打印错误代码即可。不要忘记添加测试以确保代码有效;这样,您就可以捕获错误代码中的更改(不应该发生......)。
在我的项目中,我通常会添加一个带有静态方法的辅助类,所以我可以写:
} catch( SQLException e ) {
if( DerbyHelper.tableAlreadyExists( e ) ) {
return; // That's OK
}
throw e;
}
另一种选择是对表运行SELECT
并检查状态代码(应该是42X05
)。但这是您需要发送的第二个命令,它不提供任何其他信息。
更糟糕的是,由于“表不存在”之外的其他原因,它可能会失败,因此“创建并忽略错误”是更好的IMO。
答案 1 :(得分:12)
Derby不支持sql语句 在我的程序中,我将数据库中的所有表解析为一个集合,并检查该表是否存在。 像这样:
private Set<String> getDBTables(Connection targetDBConn) throws SQLException
{
Set<String> set = new HashSet<String>();
DatabaseMetaData dbmeta = targetDBConn.getMetaData();
readDBTable(set, dbmeta, "TABLE", null);
readDBTable(set, dbmeta, "VIEW", null);
return set;
}
private void readDBTable(Set<String> set, DatabaseMetaData dbmeta, String searchCriteria, String schema)
throws SQLException
{
ResultSet rs = dbmeta.getTables(null, schema, null, new String[]
{ searchCriteria });
while (rs.next())
{
set.add(rs.getString("TABLE_NAME").toLowerCase());
}
}
答案 2 :(得分:4)
检查表是否存在:
Connection con = DriverManager.getConnection(url);
ResultSet res = con.getMetaData().getTables(null, Schema_Name, table_name.toUpperCase(), null);//Default schema name is "APP"
if(res.next())
{
//do some thing;
}else{
JOptionPane.showMessageDialog(null, table_name +" not exist");
}
显示所有表名:
Connection con = DriverManager.getConnection(url);
ResultSet res = con.getMetaData().getTables(null, Schema_Name, "%", null);//Default schema name is "APP"
while(res.next())
{
JOptionPane.showMessageDialog(null, res.getString(3) + " is exist");//Show table name
}else{
JOptionPane.showMessageDialog(null, table_name +" not exist");
}
答案 3 :(得分:2)
Derby db不支持您正在执行的查询。相反,如果你知道表的名称,你可以找到表,或者不是很容易。
public boolean isTableExist(String sTablename) throws SQLException{
if(connection!=null)
{
DatabaseMetaData dbmd = connection.getMetaData();
ResultSet rs = dbmd.getTables(null, null, sTablename.toUpperCase(),null);
if(rs.next())
{
System.out.println("Table "+rs.getString("TABLE_NAME")+"already exists !!");
}
else
{
System.out.println("Write your create table function here !!!");
}
return true;
}
return false;
}
Catch是以大写字母指定表格的名称,否则您将无法在元数据中找到表格名称。
答案 4 :(得分:2)
按照 Aaron Digulla 带领DerbyUtils
班的主管来检查表格是否存在,这是我提出的解决方案:
致电课程
public void createTable(String name) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = daoFactory.getConnection();
String sql = String.format(SQL_CREATE_TABLE, name);
preparedStatement = connection.prepareStatement(sql, Statement.NO_GENERATED_KEYS);
preparedStatement.execute();
} catch (SQLException e) {
if(DerbyUtils.tableAlreadyExists(e)) { //check if the exception is because of pre-existing table.
logger.info("Talbe " + name + " already exists. No need to recreate");
} else {
logger.error(e.getMessage() + " : " + e.getStackTrace());
}
} finally {
close(connection, preparedStatement); //DAOUtils silently closes
}
}
<强> DerbyUtils 强>
public class DerbyUtils {
public DerbyUtils() {
//empty constructor -- helper class
}
public static boolean tableAlreadyExists(SQLException e) {
boolean exists;
if(e.getSQLState().equals("X0Y32")) {
exists = true;
} else {
exists = false;
}
return exists;
}
}
答案 5 :(得分:2)
我知道这标有答案但是如果有人想要另一种方式检查我想要发帖。在这里,我使用返回布尔值的方法检查表元数据,如果存在则返回true,否则返回false。如果他们正在寻找,希望它能帮助他人。
private static Connection conn = null;
private static Statement st = null;
private static ResultSet rs = null;
private static DatabaseMetaData dmd;
public Boolean firstTime()
{
try
{
dmd = conn.getMetaData();
rs = dmd.getTables(null, "APP", "LOGIN", null);
return !rs.next();
} catch (SQLException ex)
{
Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
}
答案 6 :(得分:1)
有两个条件的另一个解决方案:
在每次创建之前都愿意删除表,同时存在于.sql文件中
使用Spring并因此愿意使用 spring-test 作为Maven依赖项,使用 @Sql 可以简化您的生活注释
所以,首先将它作为依赖项添加到你的pom中:
DROP TABLE rectangles;
CREATE TABLE rectangles (
id INTEGER NOT NULL PRIMARY KEY,
width INTEGER NOT NULL,
height INTEGER NOT NULL
);
其次,假设你有一个丢弃的sql,在文件中创建表a rectangle.sql :
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.SqlConfig;
import org.springframework.test.context.jdbc.SqlConfig.ErrorMode;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=XyzClientConfig.class)
@Sql(scripts="/sql/ddl/rectangle.sql", config=@SqlConfig (errorMode=ErrorMode.IGNORE_FAILED_DROPS))
public class BlahTest {
...
}
你有一个测试类BlahTest应该运行这个sql,然后再进行任何测试运行,只需在你的类中添加以下 @Sql 注释:
import os
os.system("abaqus viewer nogui=test.py")
指定的 config 属性值 @SqlConfig 具有使其在表格不存在的情况下跳过drop语句错误的魔力。我相信它是专门针对这些类型的数据库编写的,这些数据库不支持 IF EXISTS 用于删除/创建表格(德比真的应该这样做,即使这样做也是如此)目前不属于SQL标准的一部分)
答案 7 :(得分:0)
这是一个可以在SQL中编写脚本的解决方案。
创建如下所示的类:
package user.fenris.spring.extensions;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
public class SqlCreateIfNotExists {
private static Log log = LogFactory.getLog(SqlCreateIfNotExists.class);
public static void createTableIfNotExists(String tablename, String ddl) throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:default:connection");
if (conn != null) {
JdbcTemplate template = new JdbcTemplate(new SingleConnectionDataSource(conn, true));
int count = template.queryForInt("select count(*) from SYS.SYSTABLES where TABLENAME = ?", tablename);
log.debug("Count: " + count);
if (count == 0) {
log.debug("Executing sql statement: " + ddl);
template.execute(sql);
} else {
log.debug("Table exists. Skipping sql execution...");
}
}
}
}
注意:您不必使用spring,您可以直接在JDBC中编写它,但是您必须知道如何正确地执行它。 (留给读者练习)。此外,您可以重写此操作以从ddl参数中解析出表名。另一件事是进行适当的错误处理。
确保编译该类并将其放置在将运行数据库的VM的类路径中。
编写SQL脚本:
-- 2K for ddl statement should be enough. You want more? Seriously?
create procedure CreateTableIfNotExists(in tablename varchar(128), in ddl varchar(2048))
PARAMETER STYLE JAVA
MODIFIES SQL DATA
language java
external name 'user.fenris.spring.extensions.SqlCreateIfNotExists.createTableIfNotExists';
call CreateTableIfNotExists('TABLE_NAME_MUST_BE_ALL_CAPS',
'create table TABLE_NAME_MUST_BE_ALL_CAPS
(entry_id int generated always as identity not null,
entry_timestamp timestamp,
username varchar(128) not null,
note varchar(1024) not null,
primary key (entry_id))');
-- you don't have to drop this, but you would have to create a similar
-- procedure to create the CreateTableIfNotExists procedure,
-- (i.e. CreateProcedureIfNotExists) but then it's turtles all the way down
drop procedure CreateIfNotExists;
???
答案 8 :(得分:0)
try {
connection.createStatement().execute("create table channels(channel varchar(20),topic varchar(20))");
} catch (Exception e) {
// TODO Auto-generated catch block
// e.printStackTrace();
}
通过try-catch覆盖create语句,并确保注释e.printstacktace(); 如果它已经存在则不会显示错误,否则会创建表.. !!
答案 9 :(得分:0)
这个答案太晚了,但是对某人可能会有帮助。
以下Java(标准JDBC)代码可用于检查表是否存在,如果存在,则可以创建该表;
String query = "SELECT TRUE FROM SYS.SYSTABLES WHERE TABLENAME = ? AND TABLETYPE = 'T'"; // Leave TABLETYPE out if you don't care about it
PreparedStatement ps = connection.prepareStatement(query);
ps.setString(1, "TABLE_NAME"); // Must be in capitals
ResultSet rs = ps.executeQuery();
if ( rs.next() && rs.getBoolean(1) )
{
// Table exists
}
else
{
// Table does NOT exist ... create it
}