Pobieramy dane z bazy danych Oracle przy użyciu Jython i JDBC, ale pole BLOB nie zwraca danych blob. Zamiast rzeczywistych danych typu blob widzimy pola, które wyglądają następująco:

oracle.sql.BLOB@10e8881

Jeśli wykonamy to samo zapytanie w Razor SQL przy użyciu połączenia JDBC, możemy zobaczyć obiekty blob w tekście wynikowym i wyglądają dobrze. (W ogóle nie widzimy „oracle.sql.Blob” w polach).

Oto kod Pythona i SQL wykonujący zapytanie:

cur = connect_to_database()
query = "SELECT * FROM {} WHERE ROWNUM = 1".format(table_name)
cur.execute(query)
results = cur.fetchall()
print results

Kiedy drukujemy wyniki, jedna z kolumn ma wartość pokazaną powyżej. Nie widzimy binarnego obiektu blob.

Oto jak wykonujemy nasz skrypt w Pythonie:

C:\jython2.7.0\bin\jython.exe C:\path_to_our_script.py

Jak uzyskać rzeczywiste dane binarne zwróconego obiektu blob zamiast tekstu „oracle.sql.blob@”, który widzimy?

1
Praxiteles 20 grudzień 2019, 06:50

2 odpowiedzi

Musisz przeczytać dane binarne, aby pobrać tekst z obiektu BLOB.

Poniższy fragment kodu jest mniej więcej tym, czego potrzebujesz.

import java.io

# Some code

bs = theBlob.getBinaryStream()
ir = java.io.InputStreamReader(bs)
br = java.io.BufferedReader(ir)

total = ''
st = br.readLine()
while st != None:
   total = total + st
   st = br.readLine()

W powyższym fragmencie kodu obiekt blob zostaje zrzucony do ciągu total.

Poniżej znajduje się podobny działający przykład odczytu z pliku.

import java.io

f = java.io.File('test.txt')
fr = java.io.FileReader(f)
br = java.io.BufferedReader(fr)

st = br.readLine()
while st != None:
    print st
    st = br.readLine()
0
Bilesh Ganguly 21 grudzień 2019, 03:28
Nie jest dla nas jasne, w jaki sposób integrujemy Twój kod z tym, co robimy powyżej. Nie mamy strumienia binarnego ani pliku. Próbujemy uzyskać strumień binarny przez SQL. Jakie są zaczepy, które łączą zmienne i metody, których używamy, z sugerowanym przez Ciebie kodem?
 – 
Praxiteles
8 styczeń 2020, 01:23
- Pierwsza próbka powinna działać. Niestety nie miałem pod ręką działającego bloba do testowania kodu. Dlatego udostępniłem równoważny przykład odczytu pliku, aby zademonstrować, co z grubsza należy zrobić. bs = theBlob.getBinaryStream() powinien działać, ponieważ jest to obiekt oracle.sql.BLOB.
 – 
Bilesh Ganguly
8 styczeń 2020, 01:32

Jeśli masz opcję uaktualnienia do zxJDBC zamiast czystego JDBC, otrzymasz wsparcie dla konwersji blob na tablicę po wyjęciu z pudełka.

create table T_BLOB (b BLOB,c INTEGER);
insert into t_blob(b,c) values ( utl_raw.cast_to_raw('test1'),1);
insert into t_blob(b,c) values ( utl_raw.cast_to_raw('test2'),1);
commit;

Pobierz wartości blob i int:

from com.ziclix.python.sql import zxJDBC

def connect():
    p = {}
    p['URL'] = 'jdbc:oracle:thin:user/password@192.168.0.5:1521:dev'
    db = apply(zxJDBC.connectx, ("oracle.jdbc.pool.OracleDataSource",), p)    
    return db.cursor()

cur = connect()
query = "SELECT * FROM t_blob"
cur.execute(query)
print cur.fetchall()

Drukuje:

[(array('b', [116, 101, 115, 116, 49]), 1.0), (array('b', [116, 101, 115, 116, 50]), 1.0)]

Działa w następujących wersjach:

  • Oracle: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 — produkcja 64-bitowa na Sun Solaris
  • java: [Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] na java1.8.0_231
  • jython: Jython 2.7.0 (domyślnie: 9987c746f838, 29 kwietnia 2015, 02:25:11)
  • jdbc: jdbc7.jar (Wdrożenie-Wersja: 12.1.0.2.0)
1
Dmitry.M 10 styczeń 2020, 18:39