【问题标题】:Generate ansi sql INSERT INTO生成ansi sql INSERT INTO
【发布时间】:2018-06-15 04:57:02
【问题描述】:

我有 10 个表的 Oracle 数据库。一些表具有 CLOB 数据文本。我需要使用 java 以编程方式从这些表中导出数据。导出数据应为 ANSI INSERT INTO SQL 格式,例如:

INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);

主要思想是我需要将这些数据导入三个不同的数据库: ORACLEMSSQLMySQL。据我所知,所有这些数据库都支持 ANSI INSERT INTO。但我还没有找到任何用于生成数据 SQL 脚本的 java API/框架。而且我不知道如何处理 CLOB 数据,如何导出它。
用java从数据库中导出数据的最佳方法是什么?

更新: (01.07.2018)
我想根据this answer插入超过4000字节的文本数据是不可能的。如何以编程方式使用 java 生成 PL\SQL 脚本?或者有没有其他支持ORACLE、MSSQL等的导出格式?

【问题讨论】:

  • 有可能在 Java 中完成整个事情,例如打开与 Oracle(源)和 SQL Server(目标)的连接,并从 Oracle 迭代一个表,将每条记录写入 SQL Server。
  • 您是否绝对需要一组 ANSI SQL 文件,或者您能负担得起写入分隔文本文件然后从中加载的费用吗?如果您转储到文本然后导入而不是执行 SQL 进行加载,这会更容易和更快。
  • 不,我绝对不需要 ANSI SQL 文件(但它会很完美)。现在我决定将所有数据导入 XML 文件。并用hibernate编写一个小java工具,将这个文件中的所有数据插入到数据库中。然后我可以更改驱动程序并将其应用于不同的 SQL 供应商。
  • 我认为您使用 DB-to-file-to-DB 管道比使用 SQL 脚本要好得多,即使以自定义转储/加载为代价,因为您很难获得任何简单的 -适合所有的 SQL 脚本集。
  • 最佳做法是将 Clob 导出为外部文件并通过文件加载。我建议你阅读dba-oracle.com/t_insert_clob_table_column.htm

标签: java sql oracle


【解决方案1】:

如果您正在寻找 SQL 生成,那么您可以使用许多 sqlbuilder 库。

您可以使用元数据从 select * 查询中获取列名和类型,并在插入查询中使用它。

https://github.com/jkrasnay/sqlbuilder

更多信息请访问http://john.krasnay.ca/2010/02/15/building-sql-in-java.html

【讨论】:

  • 这不是一个完整的答案。
【解决方案2】:

你有没有想过合适的 ORM-Api?我首先想到的是 Hibernate 或更抽象的 JPA/JPQL。该框架确实知道所有主要的 sql 方言。您需要做的就是定义您与方言的联系。比您从数据库中检索数据并将其映射到 POJO,然后将数据推送(插入)到您的不同(其他方言)连接。我认为应该工作得很好,即使我从来没有这样做过。但我知道 JPA 并不是新的并且被广泛用于更改数据库,即使该软件已经投入生产。这种方法性能有点低,因为每一行都被转换为 POJO,而且,afaik,没有可用的批量插入。

【讨论】:

  • 同意你的看法。现在我正在使用休眠实现这样的导出工具。
【解决方案3】:

如果您需要从 Oracle 数据库中导出表以将其插入到不同类型的数据库中,我建议采用不同的方法。

这是 JPA(Java Persistence API)的完美用例,它允许您创建一个模型来表示您的数据库结构。这是Java当前管理不同类型数据库的解决方案。

从您的模型中,您将能够生成与所有流行数据库兼容的请求。

所以我的建议是,使用 Spring Boot + Spring Data + Spring Batch :

  1. 从您的模型创建第一个应用程序,将表格内容导出为 CSV 格式。
  2. 从导入 CSV 文件的同一模型创建第二个应用程序。根据您的 jdbc url,Spring Boot 将自动为您的目标数据库触发适当的方言并生成正确的查询(导出也是如此)。

这可以在合理的时间内完成,并且性能良好。

【讨论】:

    【解决方案4】:

    我需要使用 java 以编程方式从这些表中导出数据

    来吧,伙计!什么是事? Java是操作数据的工具,不是迁移的工具。如果是关于 ETL - 请使用目标 DBMS 的 ETL 环境或自己编写 ETL 代码。

    【讨论】:

      【解决方案5】:

      对于 MSSQLORACLE,您可以将 MERGE Tool syntax (and USING clause for Data) 用于 ANSI 标准:

      MERGE INTO tablename USING table_reference ON (condition)
         WHEN MATCHED THEN
         UPDATE SET column1 = value1 [, column2 = value2 ...]
         WHEN NOT MATCHED THEN
         INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...]);
      

      对于 MySQL 有不同的syntax (On Duplicate Key Update Statement)

      -- Insert new or merge into existing row.
      MERGE INTO system_user target
      USING (SELECT   1 AS system_user_id
             ,       'SYSADMIN' AS system_user_name
             ,        1 AS system_user_group_id
             ,        1 AS system_user_type
             ,       'Samuel' AS first_name
             ,        'the' AS middle_name
             ,       'Lamanite' AS last_name
             ,        1 AS created_by
             ,        SYSDATE AS creation_date
             ,        1 AS last_updated_by
             ,        SYSDATE AS last_update_date
             FROM     dual) SOURCE
      ON (target.system_user_id = SOURCE.system_user_id)
      WHEN MATCHED THEN
        UPDATE SET first_name = 'Samuel'
        ,          middle_name = 'the'
        ,          last_name = 'Lamanite'
        ,          last_updated_by = 1
        ,          last_update_date = SYSDATE
      WHEN NOT MATCHED THEN
        INSERT
        ( target.system_user_id
        , target.system_user_name
        , target.system_user_group_id
        , target.system_user_type
        , target.first_name
        , target.middle_name
        , target.last_name
        , target.created_by
        , target.creation_date
        , target.last_updated_by
        , target.last_update_date )  
        VALUES
        ( SOURCE.system_user_id
        , SOURCE.system_user_name
        , SOURCE.system_user_group_id
        , SOURCE.system_user_type
        , SOURCE.first_name
        , SOURCE.middle_name
        , SOURCE.last_name
        , SOURCE.created_by
        , SOURCE.creation_date
        , SOURCE.last_updated_by
        , SOURCE.last_update_date );
      

      与:

      -- Insert new or merge into existing row.
      INSERT INTO system_user
      ( system_user_name
      , system_user_group_id
      , system_user_type
      , first_name
      , middle_name
      , last_name
      , created_by
      , creation_date
      , last_updated_by
      , last_update_date )
      VALUES
      ('SYSADMIN'
      , 1
      , 1
      ,'Samuel'
      ,'the'
      ,'Lamanite'
      , 1
      , NOW()
      , 1
      , NOW())
      ON DUPLICATE KEY 
      UPDATE first_name = 'Samuel'
      ,      middle_name = 'the'
      ,      last_name = 'Lamanite'
      ,      last_updated_by = 1
      ,      last_update_date = UTC_DATE();
      

      【讨论】:

        【解决方案6】:

        我会尝试Scriptella。 是一个用 Java 编写的开源 ETL 和脚本执行工具,如果需要,您可以在 xml 文件中定义源和目标连接和转换。连接可以是 JDBC,甚至可以是文本文件,并且有批处理支持的功能。可以使用 java、ant 或命令行以编程方式处理生成的 xml 文件。

        在他们的two minute tutorial 中有将表复制到另一个数据库并使用 BLOB 的示例。

        【讨论】:

          【解决方案7】:

          我非常喜欢“程序化”。 :)

          导出该数据的最佳方式是遍历表,然后查询每个表并使用insert into 语句输出纯文本。如果那里有二进制数据可能会出现问题,因为不同的 RDBS 可以以稍微不同的方式处理它。

          在Java端读取blob/clob意味着读取流。它可以是二进制或字符流。对于 Oracle,来自 the doc - 你可以这样做:

                  ResultSet rs = s.executeQuery(
                      "SELECT text FROM documents WHERE id = 1477");
                  while (rs.next()) {
                      java.sql.Clob aclob = rs.getClob(1);
                      java.io.InputStream ip = rs.getAsciiStream(1);
                      int c = ip.read();
                      while (c > 0) {
                          System.out.print((char)c);
                          c = ip.read();
                      }
                      System.out.print("\n");
                  }
          

          来自this的回答,你可以让它更短:

          Clob clob = resultSet.getClob("CLOB_COLUMN")
          String clob_content = clob.getSubString(1, (int) clob.length());
          

          编写输出可能需要处理:\t\n\r。看你的需求,内容。 The docs 有完整的例子 - 阅读,写作。他们使用准备好的语句,这就是为什么两端都需要流。如果您的 clob 不大 - 例如 32k/64k - 可能会有其他限制。如果您有任何示例 - 例如 create table 有 2-3 行,那么任何人都可以更轻松地编写代码并提供有效的东西......

          【讨论】:

            猜你喜欢
            • 2012-06-20
            • 2023-02-09
            • 2012-01-23
            • 2012-06-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-11-07
            • 1970-01-01
            相关资源
            最近更新 更多