Inline BLOB / BINARY data types in SQL / JDBC

后端 未结 3 664
遇见更好的自我
遇见更好的自我 2020-12-15 10:52

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 ...\         


        
相关标签:
3条回答
  • 2020-12-15 11:09

    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
      
    0 讨论(0)
  • 2020-12-15 11:18
    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":
            // 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.

    0 讨论(0)
  • 2020-12-15 11:28

    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.

    0 讨论(0)
提交回复
热议问题