将datetime传递到psycopg2

12

我正在尝试使用Psycopg2将datetime值插入到我的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...
                                                             ^

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

我尝试了几种不同的方法,但所有的方法都被注释掉并抛出各种错误消息。我尝试了在datetime中加引号的方式,

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)

我不知道它为什么认为这是一个字符串,尤其是因为我将它转换成了整数!

任何帮助都将不胜感激。

编辑:我使用 {} 符号而不是 %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...
                    ^

请参考我之前发布的关于此主题的帖子:如何在Python中从字符串中删除引号以供SQL查询? 编辑:根据@Zorg在此链接(https://www.psycopg.org/docs/usage.html)中的建议,以下代码对我有效:
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个字段的? - Stephen Rauch
如果你只是将日期包装成“str(now)”呢? - Vao Tsun
如果你像 str(now) 这样包装它,你会在整点时得到第一个错误。 - Steve Scott
2个回答

12

你读过"Psycopg2 usage"吗?

如果没有,不要犹豫。

警告:千万不要使用Python字符串拼接(+)或字符串参数插值(%)将变量传递给SQL查询字符串,即使在枪口下也不行。

正确的传递参数方式如下所示:

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

2
我尝试使用%s,但如果你将一个变量传递到(name)字段中,它会添加引号,从而破坏SQL代码。这就是为什么我使用{}符号的原因。 - Steve Scott
谢谢Zorg。这篇文章看起来很适合我。 - Steve Scott
对于那些懒得阅读文档的人:SQL注入(攻击)是仅使用框架的查询字符串处理(即未引用的%s)的主要原因。 - pico_prob

8

AsIs andquote_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
))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接