SQL/JDBC 中的内联 BLOB/BINARY 数据类型

发布于 2025-01-06 09:04:03 字数 366 浏览 0 评论 0原文

假设我想避免在 JDBC 中使用绑定变量并使用“临时”语句运行 SQL,例如:

connection.createStatement().executeQuery("SELECT ...");

是否有任何约定/JDBC 转义语法来内联 BLOB 数据类型?我知道 H2 有这种语法

INSERT INTO lob_table VALUES (X'01FF');

但这不是标准。有通用的解决方案吗?请注意,我对通用方法感兴趣。我知道这可能会变得非常低效。

Let's say I want to avoid using bind variables in JDBC and run SQL using "ad-hoc" statements, e.g:

connection.createStatement().executeQuery("SELECT ...");

Is there any convention / JDBC escape syntax to inline BLOB data types? I know that H2 has this syntax:

INSERT INTO lob_table VALUES (X'01FF');

But that's not a standard. Any general solutions? Note, I'm interested in a general approach. I know that this can turn out to be terribly inefficient.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我一向站在原地 2025-01-13 09:04:03

可能没有 JDBC 转义语法,因此我进行了一些搜索,发现并成功测试了以下内容:

  • SQL Server、Sybase ASE、Sybase SQL Anywhere

    插入 lob_table 值 (0x01FF);
    
  • DB2

    -- 使用 blob 构造函数。 VARCHAR FOR BIT DATA 类型不需要这样做
    INSERT INTO lob_table VALUES (blob(X'01FF'));
    
  • Derby、H2、HSQLDB、Ingres、MySQL、SQLite

    INSERT INTO lob_table VALUES (X'01FF');
    
  • Oracle

    -- 正如 a_horse_with_no_name 所提到的,请记住相对较低的
    -- Oracle 的 VARCHAR 类型限制为只能容纳 4000 个字节!
    插入 lob_table 值 (hextoraw('01FF'));
    
  • Postgres

    -- 从 Postgres 9.0 开始还有十六进制编码
    ——不过,明确的演员阵容很重要
    INSERT INTO lob_table VALUES (E'\\001\\377'::bytea);
    

    有关更多详细信息,请参阅 AH 的回答 Postgres 的十六进制编码

  • SQL标准

    -- SQL 实际上定义了二进制文字 
    --(由 DB2、Derby、H2、HSQLDB、Ingres、MySQL、SQLite 实现):
    <二进制字符串文字> ::=
      X<引用> [<空格>...] 
      [ { <退出>; [ <空格>... ] <退出> [ <空格>... ] }... ] <引用>
    
    <退出> ::=
      <数字> |一个 |乙| C | d |电子| F |一个 |乙| c | d |电子| f
    

There probably isn't a JDBC escape syntax, so I searched around a bit and found and successfully tested the following:

  • SQL Server, Sybase ASE, Sybase SQL Anywhere

    INSERT INTO lob_table VALUES (0x01FF);
    
  • DB2

    -- Use a blob constructor. This is not needed for VARCHAR FOR BIT DATA types
    INSERT INTO lob_table VALUES (blob(X'01FF'));
    
  • Derby, H2, HSQLDB, Ingres, MySQL, SQLite

    INSERT INTO lob_table VALUES (X'01FF');
    
  • Oracle

    -- As mentioned by a_horse_with_no_name, keep in mind the relatively low
    -- limitation of Oracle's VARCHAR types to hold only 4000 bytes!
    INSERT INTO lob_table VALUES (hextoraw('01FF'));
    
  • Postgres

    -- There is also hex encoding as of Postgres 9.0
    -- The explicit cast is important, though
    INSERT INTO lob_table VALUES (E'\\001\\377'::bytea);
    

    See A.H.'s answer for more details about Postgres' hex encoding

  • SQL Standard

    -- SQL actually defines binary literals as such 
    -- (as implemented by DB2, Derby, H2, HSQLDB, Ingres, MySQL, SQLite):
    <binary string literal> ::=
      X <quote> [ <space>... ] 
      [ { <hexit> [ <space>... ] <hexit> [ <space>... ] }... ] <quote>
    
    <hexit> ::=
      <digit> | A | B | C | D | E | F | a | b | c | d | e | f
    
冰雪梦之恋 2025-01-13 09:04:03

我想在 Lukas 的回答中添加一些 PostgreSQL 特定的内容:

最短和最简单的解决方案是(因为 PostgreSQL至少 9.0):

insert into lob_table (data) values( E'\\x0102030405FF' )

没有任何转换(如果该列已经是 bytea 之一),并且在开头只有 一个 \\x 标记。这是二进制数据类型。

关于 X'01FF' 语法:根据 字符串常量 文档 PostgreSQL 确实支持它 - 对于位字符串。而且似乎没有从位到字节的标准转换。

I'd like to add some PostgreSQL specific stuff to Lukas' answer:

The shortest and most easiest solution would be (since PostgreSQL 9.0 at least):

insert into lob_table (data) values( E'\\x0102030405FF' )

without any cast (if the column is already a bytea one) and only one \\x mark right at the beginning. This is the "hex format" documented in the section Binary Data Types.

Regarding the X'01FF' syntax: According to the string constant documentation PostgreSQL does support it - for bit strings. And it seems, that there is no standard conversion from bit to bytea.

森末i 2025-01-13 09:04:03
public String binaryLiteral(Connection con, byte[] bytes) {
    String databaseName = con.getMetaData().getDatabaseProductName();
    String binary = DatatypeConverter.printHexBinary(bytes);
    switch (databaseName) {
        case "Microsoft SQL Server":
        case "Sybase Anywhere": case "ASE": case "Adaptive Server Enterprise": // Sybase
            return "CONVERT(VARBINARY(MAX), '0x" + binary + "', 1)";
        case "Oracle":
            if (binary.length() <= 4000) {
                return "HEXTORAW('" + binary + "')";
            } else {
                // https://stackoverflow.com/questions/18116634/oracle-10-using-hextoraw-to-fill-in-blob-data/62162036#62162036
                return "CONCAT_RAWS(RAWS(" +
                        Streams.stream(Splitter.fixedLength(4000).split(binary))
                                .map(chunk -> "HEXTORAW('" + chunk + "')")
                                .collect(Collectors.joining(",")) +
                        "))";
            }
        case "PostgreSQL":
            return "E'\\\\x" + binary + "'";
        case "H2":
        // the following list is mostly untested
        case "HSQL Database Engine":
        case "Apache Derby":
        case "Ingres":
        case "MySQL":
        case "MariaDB":
        case "SQLite":
        case "Informix Dynamic Server":
        case "DB2":
        case "Firebird":
        default: // SQL Standard
            return "X'" + binary + "'";
    }

CONCAT_RAWSRAWS 的来源在 Oracle 10:使用 HEXTORAW 填充 blob 数据

public String binaryLiteral(Connection con, byte[] bytes) {
    String databaseName = con.getMetaData().getDatabaseProductName();
    String binary = DatatypeConverter.printHexBinary(bytes);
    switch (databaseName) {
        case "Microsoft SQL Server":
        case "Sybase Anywhere": case "ASE": case "Adaptive Server Enterprise": // Sybase
            return "CONVERT(VARBINARY(MAX), '0x" + binary + "', 1)";
        case "Oracle":
            if (binary.length() <= 4000) {
                return "HEXTORAW('" + binary + "')";
            } else {
                // https://stackoverflow.com/questions/18116634/oracle-10-using-hextoraw-to-fill-in-blob-data/62162036#62162036
                return "CONCAT_RAWS(RAWS(" +
                        Streams.stream(Splitter.fixedLength(4000).split(binary))
                                .map(chunk -> "HEXTORAW('" + chunk + "')")
                                .collect(Collectors.joining(",")) +
                        "))";
            }
        case "PostgreSQL":
            return "E'\\\\x" + binary + "'";
        case "H2":
        // the following list is mostly untested
        case "HSQL Database Engine":
        case "Apache Derby":
        case "Ingres":
        case "MySQL":
        case "MariaDB":
        case "SQLite":
        case "Informix Dynamic Server":
        case "DB2":
        case "Firebird":
        default: // SQL Standard
            return "X'" + binary + "'";
    }

The source for CONCAT_RAWS and RAWS is given in Oracle 10: Using HEXTORAW to fill in blob data.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文