oracle - comandos - clusvcadm
Obtener la LONGITUD de un LARGO SIN PROCESAR (3)
No creo que sea posible manipular LONG RAW por más de 32k en PLSQL. Aquí hay un procedimiento de Java que devuelve la longitud de un LONG RAW.
Primero, la configuración:
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
La clase Java (mi Java está un poco oxidado):
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
Llamémoslo:
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
He probado la función con campos de más de 32k y parece que funciona.
Tengo una tabla con una columna de tipo de datos LONG RAW
. ¿Cómo determino el tamaño (en bytes) de los datos en esta columna?
Si llamo a la función LENGTH
en él, aumenta ORA-00932: inconsistent datatypes: expected NUMBER got LONG BINARY
.
En caso de que lo piense: UTL_RAW.LENGTH
plantea ORA-00997: illegal use of LONG datatype
:)
(Sí, sé que LONG RAW
está en desuso - surgió la pregunta debido a algún viejo software que podría requerirlo)
Siempre que los datos en la columna no excedan los 16,383 bytes, puede resolver esto con una función PL / SQL, por ej.
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;
Desafortunadamente, un LONG RAW puede contener hasta 2GB ...
Un truco sucio, que podría ser útil si juegas con una pequeña base de datos de prueba: copia todos los datos en una tabla con un BLOB
lugar de un 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;