如何使用_conform_ asis和fstring在psycopg2中插入NULL?

时间:2019-05-22 16:10:58

标签: python-3.x postgresql psycopg2

我是Python和Psycopg2的新手。我花了最后几个小时在该区域的各个页面上进行了搜索,但找不到与我的确切问题完全匹配的内容。还有其他类似的Stackoverflow问题,但它们对我的工作采用不同的方法。

问题是我无法在数据库中获取有效的NULL。它一直将其转换为对于定义为char(1)的数据库列而言太长的字符串。

以下示例代码可用于测试/重新创建:

import psycopg2
import psycopg2.extras
from psycopg2.extensions import AsIs, ISQLQuote
import configparser

config = configparser.RawConfigParser()
config.read('config.cfg')

host     = config.get('postgresql', 'host')
port     = config.get('postgresql', 'port')
dbname   = config.get('postgresql', 'dbname')
user     = config.get('postgresql', 'user')
password = config.get('postgresql', 'password')

pg_connection = "host='{0}' dbname='{1}' user='{2}' 
password='{3}'".format(host, dbname, user, password)

INSERT_SQL = "INSERT INTO test_table(region, country_code, comms_type, frequency_units) values %s"

class Myclass():
    def __init__(self):
        self.region = 'ABC'
        self.country_code = 'XX'
        self.comms_type = 'MST'
        # This works and is a valid value...
        self.frequency = 'V'
        # The following does not work
        # BUT None is also valid value for frequency and should
        # be translated to a NULL value in the database
        # This is the part I cant get this part to work        
        self.frequency = None

    def __str__(self):
        return f'Region: {self.region} Country: {self.country_code} Airport: {self.airport_icao}'

    def __len__(self):
        return 1

    def __getitem__(self, key):
        return self

    def __conform__(self, protocol):
        if protocol is ISQLQuote:
            return AsIs(f"'{self.region}', '{self.country_code}', '{self.comms_type}', '{self.frequency}'")


def initDBTable():
    conn = None
    try:
        conn = psycopg2.connect(pg_connection)
        cur = conn.cursor()

        cur.execute("""
                    DROP TABLE IF EXISTS test_table;

                    CREATE TABLE test_table( 
                        id SERIAL PRIMARY KEY,   
                        region varchar(3) NOT NULL,
                        country_code varchar(2) NOT NULL,
                        comms_type varchar(3),
                        frequency_units char(1)
                    );

        """.format())
        conn.commit()

        cur.close()
    except (Exception, psycopg2.DatabaseError) as error:
        print(error)
    finally:
        if conn is not None:
            conn.close()


def store_data(alist):
    conn = None
    sql = INSERT_SQL
    try:
        conn = psycopg2.connect(pg_connection)

        id = 1
        with conn.cursor() as cursor:
            psycopg2.extras.execute_values(cursor, sql, alist, template=None, page_size=200)
        conn.commit()
        conn.close()

    except (Exception, psycopg2.DatabaseError) as error:
        print(error)   
    finally:
        if conn is not None:
            conn.close() 


def main():
    print('Preparing the database')
    initDBTable()
    objlist = []
    mydata = Myclass()
    if mydata:
        # in the real code the list is several thousand items
        objlist.append(mydata)
        store_data(objlist)

if __name__ == "__main__":
    main()

代码中的注释解释了预期的结果

感谢所有帮助!

0 个答案:

没有答案