使用 CLOB 和 BLOB 数据

神通 数据库使用 LOB 对象来存储文本、图像、视频和其他多媒体格式等大型数据。LOB 的最大大小限制为存储它的表空间的大小。 LOB 可以流式传输到 神通 数据库,也可以从 神通 数据库流式传输。 长度不超过 1 GB 的 LOB 也可以直接作为字符串或字节处理,STPython。这使得 LOB 易于使用,并且与流式处理相比具有显著的性能优势。但是,它要求整个LOB数据存在于Python内存中,这可能是不可能的。

LOB 绑定变量

例:

with open('example.txt', 'r') as f:
    text_data = f.read()
with open('image.png', 'rb') as f:
    img_data = f.read()

cursor.execute("insert into lob_tb (id, c, b) values (:id, :clobdata, :blobdata)",
              id=1, clobdata=text_data, blobdata=img_data)

请注意,使用此方法时,LOB 数据的大小限制为 1 GB。

将 LOB 提取为字符串和字节

将数据量不大的CLOB 和 BLOB 可以直接从数据库中查询字符串和字节。这可能比流式传输快得多。

需要使用 Connection.outputtypehandler 或 Cursor.outputtypehandler,如以下示例所示:

cursor = connection.cursor()

createsql = """
CREATE TABLE lob_tb (
    id NUMBER,
    c CLOB,
    b BLOB
);
"""
cursor.execute(createsql)

def output_type_handler(cursor, name, default_type, size, precision, scale):
    if default_type == STPython.CLOB:
        return cursor.var(STPython.STRING, arraysize=cursor.arraysize)
    if default_type == STPython.BLOB:
        return cursor.var(STPython.BINARY, arraysize=cursor.arraysize)

id = 1
clobData = "The quick brown fox jumps over the lazy dog"
blobData = b"Some binary data"
cursor.execute("insert into lob_tb (id, c, b) values (:1, :2, :3)",
               [id, clobData, blobData])

connection.outputtypehandler = output_type_handler
cursor.execute("select c, b from lob_tb where id = :1", [id])
clob_data, blob_data = cursor.fetchone()
print("CLOB length:", len(clob_data))
print("CLOB data:", clob_data)
print("BLOB length:", len(blob_data))
print("BLOB data:", blob_data)

流式处理 LOB(读取)

如果没有输出类型处理程序,CLOB 和 BLOB 值将作为 LOB 对象提取。LOB 对象的大小可以通过调用 LOB.size() 获得,数据可以通过调用 LOB.read() 来读取。此方法的执行速度比一次性读取会更慢,因为它需要更多到 神通 数据库的往返行程,并且开销更高。但是,如果无法从服务器获取 LOB 数据作为一个数据块,则需要这样做。 若要对 BLOB 列进行流式处理,可以重复调用 LOB.read() 方法,直到读取完所有数据,如下所示:

cursor.execute("select b from lob_tb where id = :1", [10])
blob, = cursor.fetchone()
offset = 1
num_bytes_in_chunk = 65536
with open("image.png", "wb") as f:
    while True:
        data = blob.read(offset, num_bytes_in_chunk)
        if data:
            f.write(data)
        if len(data) < num_bytes_in_chunk:
            break
        offset += len(data)

流式处理 LOB(写入)

如果要插入或更新包含 LOB 的行,并且要插入或更新的数据量无法放入单个数据块中,则可以使用方法 LOB.write() 对数据进行流式处理,如下面的代码所示:

createsql = """
CREATE TABLE lob_tb (
    id NUMBER,
    c CLOB,
    b BLOB
);
"""
cursor.execute(createsql)

id_val = 1
lob_var = cursor.var(STPython.BLOB)
cursor.execute("""
        insert into lob_tb (id, b)
        values (:1, EMPTY_BLOB())
        returning b into :2""", [id_val, lob_var])
lob = lob_var.getvalue()
offset = 1
num_bytes_in_chunk = 65536
with open("./FeiQ.exe", "rb") as f:
    while True:
        data = f.read(num_bytes_in_chunk)
        if data:
            lob.write(data, offset)
        if len(data) < num_bytes_in_chunk:
            break
        offset += len(data)
connection.commit()