1

我正在努力None使用 PygreSQL v5.0.6 从 python 将值插入到 PostgreSQL 数据库的日期列中。

一些代码:

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

我面临几个问题,最大的问题是 and 的值的可能性,None第一个是导致 SQL 错误的日期,例如:date_endunit

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

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

我对 Python 和 PostgreSQL 还很陌生,所以有很多潜在的地方我可能搞砸了,所以所有建议都非常受欢迎。

4

1 回答 1

1

只需使用参数化,这是将 SQL 代码与数据值分开的行业标准,而不是看起来相似的字符串插值,因为%s两者都使用了占位符。使用这种方法,None应该解析为NULL. 事实上,PygreSQL 文档甚至警告用户这种做法:

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

考虑使用未加引号的%s占位符(请参阅文档)进行以下调整,并在cursor.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()
于 2018-11-13T15:59:54.000 回答