【问题标题】:Error with SQL string: "Error while connecting to PostgreSQL operator does not exist: date = integer"SQL 字符串出错:“连接到 PostgreSQL 运算符时出错:日期 = 整数”
【发布时间】:2020-05-08 18:02:24
【问题描述】:

我有一个 Python(3) 脚本,应该每天早上运行。在其中,我调用了一些 SQL。但是我收到一条错误消息:

连接到 PostgreSQL 运算符时出错:日期 = 整数

SQL 是基于字符串的串联:

ecom_dashboard_query = """
with 
days_data as (
select 
    s.date,
    s.user_type,
    s.channel_grouping,
    s.device_category,
    sum(s.sessions) as sessions,
    count(distinct s.dimension2) as daily_users,
    sum(s.transactions) as transactions,
    sum(s.transaction_revenue) as revenue
from ga_flagship_ecom.sessions s
where date = """ + run.start_date + """
group by 1,2,3,4
)

insert into flagship_reporting.ecom_dashboard
select *
from days_data;
"""

这是完整的错误:

09:31:25  Error while connecting to PostgreSQL  operator does not exist: date = integer
09:31:25  LINE 14: where date = 2020-01-19
09:31:25                      ^
09:31:25  HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.

我尝试将 run.start_date 包装在 str 中,如下所示:str(run.start_date) 但我收到了相同的错误消息。

我怀疑这可能与我连接 SQL 查询字符串的方式有关,但我不确定。

查询直接在 SQL 中运行良好,带有硬编码日期且没有连接:

where date = '2020-01-19'

如何让查询字符串正常工作?

【问题讨论】:

  • 不要使用字符串连接,这就是导致问题的原因。再多的引用或转义都无法解决根本问题。改用参数

标签: python postgresql


【解决方案1】:

最好将查询参数传递给cursor.execute 方法。来自docs

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

所以不是字符串连接传递run.start_date 作为cursor.execute 的第二个参数。

在您的查询中使用%s

where date = %s
group by 1,2,3,4

在您的 python 代码中,将第二个参数添加到 execute 方法:

cur.execute(ecom_dashboard_query , (run.start_date,))

【讨论】:

  • 谢谢你告诉我这个!只是一个跟进。 run.start_date 后面有一个逗号...是错字吗?另外,为什么 run.start_date 在括号中?也可以cur.execute(ecom_dashboard_query , run.start_date)吗?只是好奇
  • @DougFir 不,这不是错字,execute 需要序列或映射,因此如果我们需要提供一个参数,我们需要将其转换为序列(元组),这就是逗号所做的。您可以在此处阅读有关此方法的信息:initd.org/psycopg/docs/cursor.html#cursor.execute
【解决方案2】:

你的句子错了:

其中 date = """ + run.start_date + """

尝试比较日期和字符串,这是不可能的,您需要将“run.start_date”转换为日期时间并简单比较:

date_format = datetime.strptime(your_date_string, '%y-%m-%d')

将此日期转换为日期时间:

where date = date_format

最终代码:

date_format = datetime.strptime(your_date_string, '%y-%m-%d')
ecom_dashboard_query = """
with 
days_data as (
select 
    s.date,
    s.user_type,
    s.channel_grouping,
    s.device_category,
    sum(s.sessions) as sessions,
    count(distinct s.dimension2) as daily_users,
    sum(s.transactions) as transactions,
    sum(s.transaction_revenue) as revenue
from ga_flagship_ecom.sessions s
where date = {}
group by 1,2,3,4
)

insert into flagship_reporting.ecom_dashboard
select *
from days_data;
""".format(date_format)

【讨论】:

  • 感谢您解决了我的第一个问题,即了解如何比较字符串和日期。我认为我倾向于使用 neverwalkerloners 解决方案,因为通常连接 SQL 字符串存在一些问题,我不知道
  • "format" 是将变量设置为查询的最佳方法,您可以将变量或任何您想要的内容放在“,”后面。那么,您的查询运行了吗?
  • 这是一个将在一个小时内运行的管道的一部分......很快就会发现!
猜你喜欢
  • 2020-07-15
  • 2012-06-03
  • 1970-01-01
  • 2014-10-16
  • 2019-08-13
  • 1970-01-01
  • 2023-03-18
  • 2021-08-27
  • 1970-01-01
相关资源
最近更新 更多