【问题标题】:Get the LENGTH of a LONG RAW获取 LONG RAW 的长度
【发布时间】:2011-07-26 17:12:02
【问题描述】:

我有一个数据类型为LONG RAW 的表。如何确定此列中数据的大小(以字节为单位)?

如果我在其上调用LENGTH 函数,它会引发ORA-00932: inconsistent datatypes: expected NUMBER got LONG BINARY

以防万一:UTL_RAW.LENGTH raises ORA-00997: illegal use of LONG datatype :)

(是的,我知道 LONG RAW 已被弃用 - 由于某些旧软件可能需要它,所以提出了这个问题)

【问题讨论】:

    标签: oracle ora-00932 ora-00997


    【解决方案1】:

    我认为在 PLSQL 中处理长度超过 32k 的 LONG RAW 是不可能的。这是一个返回 LONG RAW 长度的 java 过程。

    首先,设置:

    SQL> CREATE TABLE my_table (ID NUMBER, my_long_raw_column LONG RAW);
    
    Table created
    
    SQL> INSERT INTO my_table VALUES (1, utl_raw.cast_to_raw('123456789'));
    
    1 row inserted
    

    java类(我的java有点生疏):

    SQL> CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "Raw" AS
      2  import java.io.*;
      3  import java.sql.*;
      4  import oracle.jdbc.driver.*;
      5  
      6  public class Raw {
      7  
      8     public static int getLength(int pk) throws SQLException,IOException {
      9  
     10        Connection conn = new OracleDriver().defaultConnection();
     11  
     12        PreparedStatement ps = conn.prepareStatement
     13           ( "SELECT my_long_raw_column FROM my_table WHERE id = ?" );
     14        ps.setInt( 1, pk);
     15        ResultSet rs = ps.executeQuery();
     16  
     17        int len = 0;
     18        if (rs.next()) {
     19           InputStream is = rs.getBinaryStream(1);
     20           int nb = is.read(new byte[1024]);
     21           while (nb>0) {
     22              len += nb;
     23              nb = is.read(new byte[1024]);
     24           }
     25        } else
     26           len = -1;
     27  
     28        rs.close();
     29        ps.close();
     30
     31        return len;
     32     }
     33  }
     34  /
    
    Java created
    

    我们称之为:

    SQL> CREATE OR REPLACE
      2  FUNCTION get_lr_length(p_id NUMBER) RETURN NUMBER
      3  AS LANGUAGE JAVA
      4  NAME 'Raw.getLength(int) return int';
      5  /
    
    Function created
    
    SQL> select get_lr_length(id) from my_table;
    
    GET_LR_LENGTH(ID)
    -----------------
                    9
    

    我已经测试了超过 32k 字段的函数,它似乎可以工作。

    【讨论】:

      【解决方案2】:

      只要列中的数据不超过16383字节,就可以用PL/SQL函数解决,例如

      CREATE OR REPLACE FUNCTION get_lr_length (id IN NUMBER)
        RETURN NUMBER IS
        raw_data LONG RAW;
        hex_data VARCHAR2(32767);
        len      NUMBER;
      BEGIN
        SELECT my_long_raw_column INTO raw_data
        FROM my_table
        WHERE my_table.id = get_lr_length.id;
        hex_data := RAWTOHEX(raw_data);
        len := LENGTH(hex_data) / 2;
        RETURN len;
      END get_lr_length;
      

      不幸的是,LONG RAW 最多可以容纳 2GB...

      【讨论】:

      • 您可以直接在 PLSQL LONG RAW 变量上使用 utl_raw.length(如果我没记错的话,LONG RAW 是 PLSQL 中的 RAW (32767) 的同义词)。因此,您可以测量高达 32767 字节的 RAW :)
      • 同样来自this thread on Asktom,在PLSQL 中操作长于32k 的LONG RAW 似乎是不可能的。您可能需要编写一个 java 函数来获取原始文件的长度。
      • @Vincent:你没有得到ORA-00997: illegal use of LONG datatype吗?这就是我在 LONG RAW (Oracle 11.2.0.1.0) 上调用 utl_raw.length 时得到的结果
      • 不在 PLSQL 中(因为 LONG RAW 被转换为 RAW(32767)):这是我的函数 CREATE OR REPLACE FUNCTION get_lr_length (p_id IN NUMBER) RETURN NUMBER IS raw_data LONG RAW; BEGIN SELECT my_long_raw_column INTO raw_data FROM my_table WHERE my_table.id = p_id; RETURN utl_raw.length(raw_data); END;
      • +1 文森特 - 如果你提供这个作为答案,我会再给它一个 +1 - 它比我的解决方案更好。
      【解决方案3】:

      一个肮脏的技巧,如果您正在使用小型测试数据库,这可能会有所帮助:使用BLOB 而不是LONG RAW 复制表中的所有数据。

      create table START(ID int not null, VAL long raw);
      ... inserts
      create table START_BLOB(ID int not null, VAL blob);
      insert into START_BLOB(ID,VAL) select ID,to_lob(VAL) from STAR;
      select ID,length(VAL) from START_BLOB;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-06
        • 1970-01-01
        • 2023-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-02
        • 1970-01-01
        相关资源
        最近更新 更多