Apache Derby:我怎么能“插入,如果不存在”?

时间:2009-01-02 18:46:22

标签: java sql derby

我正在给Apache Derby,又名JavaDB旋转。在插入可能已存在的记录时,我似乎无法解决重复的关键问题。 Derby是否等同于“insert if not exists”或“merge”?

同样,有没有办法做“drop table foo if exists”这样的事情?

7 个答案:

答案 0 :(得分:16)

我从未使用过apache derby,但是一个与数据库无关的通用解决方案如下:

要将值'a'和'b'插入到表foo中(使用名为A,B的列),但仅在值尚未存在的位置插入,请尝试类似

的内容
INSERT INTO foo (  
  SELECT 'a' as A, 'b' as B
  FROM foo  
  WHERE  
    A = 'a' AND B = 'b'  
  HAVING count(*)=0  
 )

这可能需要针对特定​​的dbms进行调整,但我们的想法是插入一个select的结果,该结果仅在非non时返回值。

这是创建一个幂等sql脚本(第二次运行时不执行任何操作)的有用技巧。但是,在生产代码中使用它时要小心,因为HAVING count(*)=0在大型表上可能会非常慢。

答案 1 :(得分:4)

支持SQL:2003 MERGE语句的请求以https://issues.apache.org/jira/browse/DERBY-3155

的形式记录在Derby错误跟踪器中

你可以为这个问题投票,或者更好的是,贡献一个实现!

否则,我所知道的唯一解决方案要么首先选择行以查看它是否存在,要么插入并捕获异常,正如其他人所指出的那样。

您可以将此逻辑打包在数据库过程中,以使其更容易执行。

答案 2 :(得分:3)

我与PostgreSQL DB一起使用的标准方法如下:

INSERT INTO foo ( col1, col2, col3, ... )
SELECT 'col1 value', 'col2 value', 'colc value', ...
WHERE NOT EXISTS (
  SELECT 0
  FROM foo
  WHERE col1 = 'col1 value'
  ...
)

不确定它是多么便携或严格符合ANSI标准。外部SELECT语句中缺少的FROM子句特别可能是非标准的。试一试。

答案 3 :(得分:2)

德比在10.11中实施了MERGE:https://db.apache.org/derby/docs/10.11/ref/rrefsqljmerge.html
请注意,在使用数据库之前,您需要将数据库升级到10.11:https://db.apache.org/derby/docs/10.11/devguide/cdevupgrades.html

答案 4 :(得分:1)

我遇到了同样的问题,我在Derby上只有一个值/列的插入工作。 (我从来没有用更多来测试它,但我没有理由认为它不应该):

INSERT INTO my_table (my_column)
    (SELECT 'new_value_to_insert'
    FROM my_table
    WHERE my_column = 'new_value_to_insert' 
    HAVING count(*)=0)

答案 5 :(得分:0)

没有本机支持,为了解决这个问题,我正在使用eclipse-link,eclipse-link将尝试创建表并忽略因尝试创建已存在的表而产生的任何错误。

如果您进行架构更改,您可以告诉eclipse链接在创建表之前删除它们。

答案 6 :(得分:0)

我正在使用此解决方案,但只有在您了解数据库视图中的重复来自用户视图的重复之间的差异时,才必须使用此解决方案

  • 数据库视图中的重复项是两个具有相同主键的记录
  • 用户视图中的重复项是两条记录,其中所有fiels相同

        while (ResultSet.next()) {
        try {
        PreparedStatement insertion = myConn.prepareStatement("insert into table values (?)");
        insertion .setString(1, "test");
        insertion .executeUpdate();           
        } catch (SQLException e) {
            if(e.getSQLState().equals("23505"))//Found duplicate from database view
             {continue;}//ignore duplicate and continue with the insert statement
            else{try {                           
                  throw e;
            } catch (Exception ex) {  
                }
              }
            }
          }