java - 如果某些值不存在则插入到表中

标签 java sql database jdbc h2

我有一个H2名为 PRODUCTS 的数据库,包含 5000 行,每行 55 列。我当前正在使用 PreparedStatement 将值行添加到数据库,但它不会检查该行是否已存在。相反,我只需要在列名“id”(VARCHAR 类型)包含某个字母数字字符串,并且列名“id2”(VARCHAR 类型)< em>不某个字母数字字符串,并且列名“raw_yn”(BOOLEAN 类型)包含 false。我在准备好的语句中输入的值是通过方法提供的。

问题here与我要问的非常接近,区别在于它是 solution基于向空数据库添加行,并确保数据库为空。 H2 的创建者评论道:

Then the "where not exists" ensures this rows are only inserted if the table [TABLE] is empty.

如何调整此代码,使其仅在满足上述 3 个要求(无论 DB 是否为空)的情况下执行 INSERT 查询?

目前我有:

 import java.sql. *;
       static final String JDBC_DRIVER = "org.h2.Driver";
       static final String DB_URL = "jdbc:h2:~/myDB";
       static final String USER = "test";
       static final String PASS = "test";
       static final Connection conn = null;
       static final Statement stmt = null;

       public class DataBaseManager {

           public void insertIntoDB(String id1val, String id2val, Boolean raw_yn_val, ...,...) {

               try {
                   Class.forName(JDBC_DRIVER);
                   conn = DriverManager.getConnection(DB_URL, USER, PASS);
                   myStatement = "INSERT INTO PRODUCTS VALUES(?,?,?,..,...)";
                   stmt = conn.prepareStatement(myStatement);
                   stmt.setString(1, id1val);
                   stmt.setString(2, id2val);
                   stmt.setBoolean(3, raw_yn_val);
                   stmt.setString(4,....);
                // Continue up to 55
                   stmt.executeUpdate();
               }

                 [catch&finally blocks]
           }
       }

myStatement 应该更改为什么?我很困惑,因为如果我像下面一样使用 select 0, 'id1' union ,它如何适合我的 stmt.setString(1, id1val) 的 PreparedStatement ); ??.感谢您的帮助。

INSERT INTO PRODUCTS SELECT * FROM(
select 0, 'id1' union                         // <--- How does this fit into Prepared Statement?
select 1, 'id2' union
select 2, 'raw_yn' union
) x where not exists(SELECT * FROM PRODUCTS);  // <--- Ensures only works when empty
<小时/>

更新:

根据 Gord 的建议,我编写了以下代码。如果数据库为空,n 将返回 0。向空数据库添加 5000 行大约需要 1 分钟。但是,如果存在匹配项,即使我只是使用 return 而不是使用额外的 INSERT 代码,它也会花费近 5 倍的时间。那么不是应该更快吗?

try {
   Class.forName(JDBC_DRIVER);
   conn = DriverManager.getConnection(DB_URL, USER, PASS);
   statement = conn.createStatement();

   String sql = "SELECT COUNT(*) AS n FROM PROPERTIES WHERE id1='" + id1 + "' AND id2='" + id2 + "' AND raw_yn='true'";
   rs = statement.executeQuery(sql);
   rs.next();
   if (rs.getInt("n") == 0) {
    Class.forName(JDBC_DRIVER);
    conn = DriverManager.getConnection(DB_URL, USER, PASS);
    myStatement = "INSERT INTO PROPERTIES VALUES(?,?,?,...)";
    stmt = conn.prepareStatement(myStatement);
    stmt.setString(1, id1);
    stmt.setString(2, id2);
    stmt.setBoolean(3, raw_yn);
    stmt.executeUpdate();
   } else {
    return; // <-- Takes 5x longer to go through ???
   }

  }

    [catch & finally blocks]

最佳答案

考虑使用暂存临时表,将所有数据按原样附加到类似的结构化表ProductsTemp中,然后迁移到最终表Products,并筛选出独特的行。下面是按顺序合并到 Java 代码中的 SQL 语句:

暂存附加(两个语句)

DELETE FROM ProductsTemp;

INSERT INTO ProductsTemp VALUES (?,?,?,..,...);

最终迁移

INSERT INTO Products (id, id2, raw_yn, ...)
SELECT id, id2, raw_yn, ...
FROM ProductsTemp temp
WHERE NOT EXISTS (SELECT 1 FROM Products sub
                   WHERE sub.id = temp.id
                     AND sub.id2 = temp.id2
                     AND sub.raw_yn = temp.raw_yn);

关于java - 如果某些值不存在则插入到表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38544120/

相关文章:

java - 如何从互联网将文件写入SD卡?

java - 为什么按位置读取 JDBC 结果集比按名称读取 JDBC 结果集快多少?

mysql - 如何为搜索项开头只有一个通配符(('%TERM')的文本搜索建立索引?

mysql - 如何从巨大的表中加速 JOIN 和 GROUP BY - 100 亿行

php - 创建动态页面主体的最有效方法是什么?

java - 在构造函数中初始化值之前检查条件

java - 带 GSI 的 dynamodb 过滤器

mysql - 将时间戳从 mysql 格式更改为 unix - MYSQL

sql - 按贷款数量分组(50)

php - 多个 MySQL 查询集中在一个中,同时忽略重复的匹配 ID