Serie: Einführung in den Inhalt von cx_Oracle
Erstellen Sie die folgende Tabelle.
SQL> create table sample16(col1 number, col2 blob);
Wenn die Daten bis zu 1 GB groß sind, können sie ohne besondere Berücksichtigung wie VARCHAR2-Typ und RAW-Typ als str für den CLOB-Typ und als Byte für den BLOB behandelt werden. Wenn es 1 GB überschreitet, muss es in einem Stream-Verarbeitungsformat verarbeitet werden, das jeweils einen festen Betrag verarbeitet. Die Leistung ist besser, ohne einen Stream zu durchlaufen, aber selbst wenn eine Daten weniger als 1 GB groß sind, verbraucht fetchmany () schnell Speicher, sodass Speicherressourcen und die abzurufende Datenmenge (Durchschnitt) Berücksichtigen Sie je nach Gleichgewicht zwischen Größe und Anzahl der Datensätze die Stream-Verarbeitung auch für kleine LOBs.
Bereiten Sie in jedem Fall die Daten (Datei) vor, die separat verarbeitet werden sollen. Wenn Sie die Beispielquelle in Ihrer eigenen Umgebung ausführen möchten, korrigieren Sie entweder den Dateinamen in der Quelle oder den Namen der vorbereiteten Datei. Unten finden Sie ein Beispiel für den Typ INSERT to BLOB.
sample16a.py
import cx_Oracle
USERID = "admin"
PASSWORD = "FooBar"
DESTINATION = "atp1_low"
SQL = """
insert into sample16 values(1, :blobdata)
"""
with open('screenshot1.png', 'rb') as f:
image = f.read()
with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
with connection.cursor() as cursor:
cursor.execute(SQL, blobdata=image)
cursor.execute("commit")
Referenzen sind nicht so einfach wie das Aktualisieren, und Sie müssen den in 9th beschriebenen Ausgabetyp-Handler definieren. Das folgende Beispiel bezieht sich auf den zuvor registrierten Datensatz und speichert ihn in einer Datei mit einem anderen Namen.
sample16b.py
import cx_Oracle
def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
if defaultType == cx_Oracle.DB_TYPE_BLOB:
return cursor.var(cx_Oracle.DB_TYPE_LONG_RAW, arraysize=cursor.arraysize)
USERID = "admin"
PASSWORD = "FooBar"
DESTINATION = "atp1_low"
SQL = """
select col2 from sample16 where col1 = 1
"""
with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
connection.outputtypehandler = OutputTypeHandler
with connection.cursor() as cursor:
cursor.execute(SQL)
lobdata, = cursor.fetchone()
with open('screenshot2.png', 'wb') as f:
f.write(lobdata)
Natürlich ist der Inhalt beider Dateien gleich.
$ cmp screenshot1.png screenshot2.png
$
Ich werde anhand von BLOB erklären. Das Verfahren ist ungefähr wie folgt.
sample16c.py
import cx_Oracle
USERID = "admin"
PASSWORD = "FooBar"
DESTINATION = "atp1_low"
SQL = """
insert into sample16 values(2, empty_blob())
returning col2 into :blobdata
""" # [1.]
with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
with connection.cursor() as cursor:
blobdata = cursor.var(cx_Oracle.DB_TYPE_BLOB) # [2.]
cursor.execute(SQL, [blobdata])
blob, = blobdata.getvalue()
offset = 1
bufsize = 65536 # [3.]
with open('screenshot1.png', 'rb') as f: # [4.]
while True:
data = f.read(bufsize)
if data:
blob.write(data, offset)
if len(data) < bufsize:
break
offset += bufsize
connection.commit()
Unten entspricht es der Kommentarnummer.
Der Ablauf der UPDATE-Anweisung ist derselbe, nur die SQL-Anweisung ändert sich. Aktualisieren Sie die LOB-Spalte mit EMPTY_BLOB ().
Ich werde anhand von BLOB erklären. Das Verfahren ist ungefähr wie folgt. Es ist einfacher als zu aktualisieren.
sample16d.py
import cx_Oracle
USERID = "admin"
PASSWORD = "FooBar"
DESTINATION = "atp1_low"
SQL = """
select col2 from sample16 where col1 = 2
""" # [1.]
with cx_Oracle.connect(USERID, PASSWORD, DESTINATION) as connection:
with connection.cursor() as cursor:
cursor.execute(SQL)
blob, = cursor.fetchone()
offset = 1
bufsize = 65536 # [2.]
with open('screenshot3.png', 'wb') as f: # [3.]
while True:
data = blob.read(offset, bufsize)
if data:
f.write(data)
if len(data) < bufsize:
break
offset += bufsize
Unten entspricht es der Kommentarnummer.
Recommended Posts