使用PygreSQL v5.0.6将None值插入python到PostgreSQL数据库的日期列中

使用PygreSQL v5.0.6将None值插入python到PostgreSQL数据库的日期列中,python,postgresql,pygresql,Python,Postgresql,Pygresql,我正在努力使用pygresqlv5.0.6从python向PostgreSQL数据库的date列中插入None值 一些代码: def _update_traits_db(self, code, date_start, date_end, unit): sql = ("Insert into traits (code, date_start, date_end, unit) " "VALUES ('%s', '%s', '%s', '%s') "

我正在努力使用pygresqlv5.0.6从python向PostgreSQL数据库的date列中插入
None

一些代码:

def _update_traits_db(self, code, date_start, date_end, unit):
    sql = ("Insert into traits (code, date_start, date_end, unit) "
           "VALUES ('%s', '%s', '%s', '%s') "
           "ON CONFLICT (code) DO UPDATE "
           "SET date_start = excluded.date_start, date_end = excluded.date_end, unit = excluded.unit "
           % (code, date_start, date_end, unit))
    try:
        self._connect()
        self._cur.execute(sql)
        self._con.commit()
        self._close()
    except Exception as e:
        self._close()
        raise e
我面临几个问题,最大的问题是
date\u end
unit
None
值的可能性,第一个问题是导致SQL错误的日期,如:

错误:日期类型的输入语法无效:“无”
第1行:…d,单位)值('AWGHT','2003-01-29T23:00:00Z','None','N。。。 ^ 如果我用一个硬编码的NULL替换none值,那么它可以工作,但是从阅读中我发现它应该由py-PyGreSQL自动处理,将
none
转换为NULL,但是我无法让它工作

第二个问题是
None
列中的
unit
值,这应该是一个字符串,但
None
现在存储在数据库中,理想情况下为空值。我已尝试从查询vut中的单位“%s”周围删除引号,这只会导致None值出现SQL错误


我是Python和PostgreSQL的新手,因此我可能会弄乱许多潜在的地方,所以所有建议都非常受欢迎。

只需使用参数化,即将SQL代码与数据值分开的行业标准,而不是字符串插值,因为这两种方法中都使用了占位符
%s
这种方法,
None
应该解析为
NULL
。事实上,甚至在实践中警告用户:

警告
请记住切勿将参数直接插入查询中 使用%运算符。始终单独传递参数

考虑使用未加引号的
%s
占位符(请参阅)进行以下调整,这些占位符的值稍后绑定在
游标中。execute()
调用:

def _update_traits_db(self, code, date_start, date_end, unit):
    # PREPARED STATEMENT (NO DATA VALUES INTERPOLATED)
    sql =  """INSERT INTO traits (code, date_start, date_end, unit)
              VALUES (%s, %s, %s, %s)
              ON CONFLICT (code) DO UPDATE
              SET date_start = excluded.date_start, 
                  date_end = excluded.date_end, 
                  unit = excluded.unit
           """
    try:
        self._connect()
        # BIND PARAMETERS WITH TUPLE OF VALUES
        self._cur.execute(sql, (code, date_start, date_end, unit))
        self._con.commit()

    except Exception as e:
        raise e

    finally:
        self._close()

您不需要在占位符周围使用
s…只需使用
%s
本身…例如:
值(%s,%s,%s)
-引擎将已正确转义字符串,没有字符串将转换为null等…现在尝试此操作,但由于日期格式的原因,我相信日期输入是这样的“2003-01-29T23:00:00Z”所以我得到了错误:语法错误在或接近“T23”所以你的日期是一个字符串那么?如果你把它改成一个
datetime
对象-它会工作得很好。已经将日期字符串转换成datetime对象并且可以插入数据库,我找不到转换“无”的方法“虽然变量是datetime,但由于某些原因,在我尝试将其插入数据库时,它仍然没有转换为NULL。对于“Unit”值也是如此。在删除@JonClements sugested等值周围的引号后,我在代码列上也会出错。“错误:列”testCode“不存在”因此,它似乎并没有逃脱字符串本身。就是这样!非常感谢你们两位!似乎我对python中的参数化是如何真正工作的有一个误解,这更有意义。很高兴澄清了这一点,谢谢!很高兴听到。是的,这
cursor.execute(query,params)
这种方法在大多数Python DB API(cxOracle、ibmdb、pymssql、pyodbc、pymysql、psycopg2、sqlite3)中都是一致的,符合Python的SQL标准。此外,参数化是业界的最佳实践,不仅在Python中,而且在运行SQL的任何应用层语言(Java、C#、PHP、Perl等)中都是如此。祝您编码愉快!