【问题标题】:Passing a datetime into psycopg2将日期时间传递给 psycopg2
【发布时间】:2017-10-08 11:36:43
【问题描述】:

我正在尝试使用 Psycopg2 将日期时间值插入到我的 postgres 数据库中。

我的代码以前可以工作,但我从 %s 表示法切换到 {} 表示法,我的代码坏了。

这是我的代码

for j in eveLists.itemList:
    tempPrice = fetchSellPrice(i, j)
    database_name = eveLists.DatabaseDict[i]
    now = datetime.datetime.utcnow()

    cur.execute("INSERT INTO {0} VALUES ({1}, {2}, {3}, NULL, {4}, {5}, NULL);".format(
                                                                                       database_name,
                                                                                       str(i),
                                                                                       str(j),
                                                                                       float(tempPrice),
                                                                                       datetime.date.today(),
                                                                                       now))

我收到以下错误:

psycopg2.ProgrammingError: syntax error at or near "00"
LINE 1: ...0000142, 2268, 3.11, NULL, 2017-05-09, 2017-05-10 00:40:03.3...
                                                             ^

它将日期和时间视为两个独立的对象。

我尝试了几种不同的方法,这些方法都被注释掉了,并且都抛出了各种错误消息。我尝试将日期时间用引号括起来,

now = ("'%s'") % str(datetime.datetime.utcnow())

报错

psycopg2.ProgrammingError: column "mydate" is of type date but expression is of type integer
LINE 1: ...NTO temp_jita VALUES (30000142, 2268, 3.11, NULL, 2017-05-09...
                                                             ^
HINT:  You will need to rewrite or cast the expression.

它认为我的日期是一个整数,即使我用引号括起来。

我也尝试过手动制作 psycopg2 时间戳:

now = psycopg2.Timestamp(now.strftime("%Y"),
                                     now.strftime("%m"),
                                     now.strftime("%d"),
                                     now.strftime("%h"),
                                     now.strftime("%M"),
                                     int(now.strftime("%-S")))

这给出了以下错误:

    int(now.strftime("%-S")))
TypeError: an integer is required (got type str)

我不知道它怎么认为这是一个字符串,尤其是因为我将它转换为 int!

任何帮助将不胜感激。

编辑:我使用 {} 表示法而不是 %s 表示法传递变量的原因是因为我收到以下代码的错误:

  for j in eveLists.itemList:
            tempPrice = fetchSellPrice(i, j)
            database_name = eveLists.DatabaseDict[i]
            now = datetime.datetime.utcnow()
            now = str(now)

            cur.execute("INSERT INTO %s VALUES (%s, %s, %s, NULL, %s, %s, NULL);", [database_name,
                                                                                    str(i),
                                                                                    str(j),
                                                                                    float(tempPrice),
                                                                                    datetime.date.today(),
                                                                                    now
                                                                                    ])

psycopg2.ProgrammingError: syntax error at or near "'temp_jita'"
LINE 1: INSERT INTO 'temp_jita' VALUES ('30000142', '2268', 3.03, NU...
                    ^

请参考我之前的帖子:How to remove the quotes from a string for SQL query in Python?

编辑:遵循此链接 (http://initd.org/psycopg/docs/sql.html) 中 @Zorg 的建议,此代码对我有用:

cur.execute(sql.SQL("INSERT INTO {} VALUES (%s, %s, %s, NULL, %s, %s, NULL);").format(sql.Identifier(database_name)),[
                                                                                    str(i),
                                                                                    str(j),
                                                                                    float(tempPrice),
                                                                                    datetime.date.today(),
                                                                                    now
                                                                                    ])

【问题讨论】:

  • 数据库中的这些列是什么类型?这篇文章令人困惑,因为在一种情况下错误是针对字段 4,而在另一种情况下是针对字段 5?
  • 如果你只是把日期换成str(now)?..
  • 如果你像 str(now) 一样包装它,你会在小时内得到第一个错误。

标签: python postgresql datetime psycopg2


【解决方案1】:

你读过"Psycopg2 usage"吗?

如果没有,请不要犹豫。

警告 NEVER、NEVER、NEVER 使用 Python 字符串连接 (+) 或字符串参数插值 (%) 将变量传递给 SQL 查询字符串。甚至在枪口下也没有。

将参数传递给查询的正确方法如下所示:

 SQL = "INSERT INTO authors (name) VALUES (%s);" # Note: no quotes
 data = ("O'Reilly", )
 cur.execute(SQL, data) # Note: no % operator

【讨论】:

  • 我尝试使用 %s,但是如果您将变量传递到 (name) 字段中,它会添加引号,这会破坏 SQL 代码。这就是我使用 {} 表示法的原因。
  • 知道了。在 psycopg2 中模板化 SQL 标识符的犹太方法是 initd.org/psycopg/docs/sql.html
  • 谢谢佐格。这看起来是适合我的文章。
  • 谁懒得看文档:SQL 注入(攻击)是只使用框架的查询字符串处理的主要原因(即未引用的%s
【解决方案2】:

AsIsquote_ident

from psycopg2.extensions import AsIs, quote_ident

cur.execute("""
    INSERT INTO %s
    VALUES (%s, %s, %s, NULL, %s, %s, NULL);
""", (
    AsIs(quote_ident(database_name, cur)),
    str(i),
    str(j),
    float(tempPrice),
    datetime.date.today(),
    now
))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-30
    • 2011-07-28
    • 1970-01-01
    • 1970-01-01
    • 2022-09-24
    相关资源
    最近更新 更多