【问题标题】:pyodbc: ORACLE SQL Statement with WHERE Clause that incorporates date rangepyodbc:带有包含日期​​范围的 WHERE 子句的 ORACLE SQL 语句
【发布时间】:2019-10-21 00:14:30
【问题描述】:

我正在使用 pyodbc 从数据库表中提取数据。现在,我想将查询限制为仅包含在过去 24 小时内添加的记录。有关添加记录时间的信息包含在 DATE_ADDED 列中。

这就是我正在尝试的:

pyodbc.pooling = False
conn_str = (
    r'DRIVER={Oracle in OraClient12Home1};'
   .....
   .....
   .....)

conn = pyodbc.connect(conn_str)
curs = conn.cursor()


date_today = datetime.datetime.today()
date_yesterday = date_today - datetime.timedelta(days=1)

sql = f"SELECT PROD_ID, ID, COUNT, DATE_ADDED FROM LZE.APODAT WHERE DATE_ADDED < {date_today} AND DATE_ADDED  > {date_yesterday}"

my_df = pd.DataFrame(pd.read_sql(sql, conn))

我得到的错误信息是:

UnicodeDecodeError: 'utf-16-le' 编解码器无法在适当位置解码字节 218-219:非法编码

我确定这与 DATE_ADDED 列的不同格式/数据类型有关,但我不确定如何处理。在数据库中如下所示:2019-04-24 10:21:05 AM

任何帮助将不胜感激。

【问题讨论】:

  • 尝试用引号括住您的日期:'{date_today}'
  • 我以前试过。它给了我同样的错误
  • 这对您有帮助吗? stackoverflow.com/questions/17478476/…
  • 如果我试试这个:... WHERE TRUNC(DATE_ADDED) &lt; TO_DATE('{date_today}','YYYY/MM/DD HH:MI:SS') AND TRUNC(DATE_ADDED) &gt; TO_DATE('{date_yesterday}','YYYY/MM/DD HH:MI:SS')" 我得到同样的错误
  • 是的,如果我删除 where 子句,我可以提取整个表。你会在哪里怀疑这个特殊角色?在数据库列中?

标签: python oracle datetime where-clause pyodbc


【解决方案1】:

考虑参数化(在应用层使用 SQL 时的行业标准),因为 Python 的 datetime 对象可能会转换为 Oracle 的 date 类型。

是的,您可以使用 params 参数(不需要 pd.DataFrame() 包装器)在 Pandas 中使用 read_sql() 参数化。另外,你不需要 F 字符串,所以这个版本可以在任何 Python 版本中工作。

sql = """SELECT PROD_ID, ID, COUNT, DATE_ADDED 
         FROM LZE.APODAT 
         WHERE DATE_ADDED < ? AND DATE_ADDED  > ?
      """

my_df = pd.read_sql(sql, conn, params=[date_today, date_yesterday])

否则转成字符串(去掉十进制微秒)并使用Oracle的TO_DATE():

sql = """SELECT PROD_ID, ID, COUNT, DATE_ADDED 
         FROM LZE.APODAT 
         WHERE DATE_ADDED < TO_DATE(?, 'YYYY-MM-DD HH:MI:SS')
           AND DATE_ADDED > TO_DATE(?, 'YYYY-MM-DD HH:MI:SS')?
      """

my_df = pd.read_sql(sql, conn, params=[date_today.strftime("%Y-%m-%d %H:%M:%S"), 
                                       date_yesterday.strftime("%Y-%m-%d %H:%M:%S")]
                   )

【讨论】:

    【解决方案2】:

    你说你想要最后 24 小时……

    你可以在 where 子句中说 DATE_ADDED &gt;= SYSDATE() - 1.0 来得到它。 SYSDATE() 让您了解当下。 oracle 中的日期行为类似于浮点数,其中 1.0 是 24 小时。所以从现在减去 1.0 得到昨天的相同时间。

    如果您想要从昨天午夜开始的所有内容,您可以truncate 日期。使用

    DATE_ADDED >= TRUNC(SYSDATE() - 1.0)
    

    【讨论】:

    • 这使查询更加整洁 - 但我得到了同样的错误。
    猜你喜欢
    • 2019-07-15
    • 1970-01-01
    • 1970-01-01
    • 2018-11-29
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 2021-10-30
    • 2020-09-30
    相关资源
    最近更新 更多