如何使用psycopg2读取和插入bytea列?

时间:2016-10-14 17:41:18

标签: python-3.x psycopg2 postgresql-9.3

我正在使用Python脚本将一些Postgresql表从一个环境复制到另一个环境(比pg_dump稍微多一点)。除非我复制具有bytea数据类型的表格,否则它的工作原理。

我在内存中读取源表数据,然后使用连接插入将内存转储到目标数据库中。

这是我生成insert语句的方法:

def generateInsert(self, argCachedRow):

    colOrd = 0;

    valClauseList = []

    hasBinary = False

    for colData in argCachedRow:
        colOrd += 1
        colName = self.colOrdLookup.get(colOrd)
        col = self.colLookup.get(colName)
        dataType = col.dataType

        insVal = None

        if colData is not None:

            strVal = str(colData)
            if dataType.useQuote:

                if "'" in strVal:
                    strVal = strVal.replace("'", "''")
                insVal = "'%s'" % strVal
            else:
                if dataType.binary:
                    hasBinary = True
                    #insVal = psycopg2.Binary(colData)
                #else:

                insVal = strVal
        else:
            insVal = "NULL"

        valClauseList.append(insVal)

    valClause = ", ".join(valClauseList)

    if hasBinary:
        valClause = psycopg2.Binary(valClause)

    result = "INSERT INTO %s VALUES (%s)" % (self.name, valClause)

    return result

适用于没有二进制数据的每个表。

我还尝试(直观地)在psycopg2.Binary中包装二进制列数据,这是注释掉的行,然后不对整个行值列表执行,但这也不起作用。

这是我的简单DataType包装器,通过阅读Postgres的information_schema表来加载:

class DataType(object):
    def __init__(self, argDispName, argSqlName, argUseQuote, argBin):
        self.dispName = argDispName
        self.sqlName = argSqlName
        self.useQuote = argUseQuote
        self.binary = argBin

如何使用psycopg2读取和插入bytea列?

1 个答案:

答案 0 :(得分:7)

如果您有这个数据库结构:

CREATE TABLE test (a bytea,
                   b int,
                   c text)

然后将二进制数据插入到请求中就可以这样做,而不需要任何包装器:

bin_data = b'bytes object'
db = psycopg2.connect(*args)  # DB-API 2.0
c = db.cursor()
c.execute('''INSERT INTO test VALUES (%s, %s, %s)''', (bin_data, 1337, 'foo'))
c.execute('''UPDATE test SET a = %s''', (bin_data + b'1',))

然后,当你查询它时:

c.execute('''SELECT a FROM test''')

你会收到一个memoryview,它很容易转换回bytes

mview = c.fetchone()
new_bin_data = bytes(mview)
print(new_bin_data)

输出:b'bytes object1'

另外,我建议你不要通过字符串格式化来组装查询。 psycopg2的内置参数替换更加方便,您不必担心验证数据以防止SQL注入。