根据 python 中的多个条件以及日期字段从访问 table 中删除行

Deleting rows from an access table based on multiple conditions in python along with a date field

我正在尝试从访问数据库 table 中删除行,基于两列,其中一列是 released_by 和 released_date。

Sudo code

WHERE released_by  = '27' and released_date would change based on the day of the month. 

Released_Date 如果日期 ==1 则删除上个月的数据,否则删除当前月份的数据。

import pandas as pd
import numpy as np
import datetime
from datetime import date
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
import pyodbc
import calendar
import xlrd
import defusedxml
from defusedxml.common import EntitiesForbidden
from xlrd import open_workbook
defusedxml.defuse_stdlib()

# connecting to access database
conn = pyodbc.connect(r'Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\Users\Desktop\Insights.accdb;')
insights_dbcurs = conn.cursor()

select_auto_releases = "SELECT * FROM RELEASES WHERE RELEASED_BY = '27'"
autoreleases = insights_dbcurs.execute(select_auto_releases).fetchall()
#display(autoreleases)

for row in autoreleases:
    previousmonth = datetime.now() - relativedelta(months=1)
    previousmonth = previousmonth.strftime("%m - %Y")
    currentmonth = datetime.now()
    currentmonth = currentmonth.strftime("%m - %Y")
    if ((row.autoreleases['RELEASED_DATE']).strftime) ==1:
        try:
            delete = 'DELETE * FROM RELEASES WHERE RELEASED_DATE = ? and RELEASED_BY = ?'
            insights_dbcurs.execute(delete,{'RELEASED_DATE':currentmonth},{'RELEASED_BY':'27'})
        except:
            delete = 'DELETE * FROM RELEASES WHERE RELEASED_DATE = ? and RELEASED_BY = ?'
            insights_dbcurs.execute(delete,{'RELEASED_DATE':previousmonth},{'RELEASED_BY':'27'})

insights_dbcurs.close()
conn.commit()
conn.close()

它不起作用。我得到:

AttributeError: 'pyodbc.Row' object has no attribute 'autoreleases'

如果我删除 Row.autorelease,我会得到

sql has 0 attributes, 2 being passed.

我该如何避免这种情况。任何建议都会很有帮助。

考虑重构您的代码以解决几个问题:

  1. try/except通常用于处理运行时间异常和错误,而不是应用程序逻辑。在这些情况下使用 if/else

  2. 删除不需要的 for 循环,因为您没有逐行删除,因为没有唯一标识符被传递到 DELETE 语句中。实际上,如果逻辑将未过滤的当前行传递给那一行,您将 运行 整个 table 删除过程。

  3. 使用带有一个 DELETE 语句的纯 SQL 并避免 Python 处理时间元素,如您所见,这会维护数据库的转换问题。 MS Access SQL 确实具有日期函数,例如 Date()(当前日期)和 DatePart() 用于 month/day 提取。此外,MS Access 可以 运行 DELETE.

  4. 中的复杂子查询逻辑

SQL

对两个日期条件使用 IN 子查询。注意:ID 应替换为 table 的唯一标识符。在 DELETE 版本之前检查 SELECT 版本的查询。

DELETE FROM RELEASES r
WHERE r.ID IN
  (SELECT sub.ID  
   FROM RELEASES sub
   WHERE sub.RELEASED_BY = ? 
     AND (
           (
            DatePart('m', sub.RELEASED_DATE) = DatePart('m', Date()) - 1
            AND DatePart('yyyy', sub.RELEASED_DATE) = DatePart('yyyy', Date())
            AND DatePart('d', sub.RELEASED_DATE) = 1
           )
          OR 
           (
            DatePart('m', sub.RELEASED_DATE) = DatePart('m', Date())
            AND DatePart('yyyy', sub.RELEASED_DATE) = DatePart('yyyy', Date())
            AND DatePart('d', sub.RELEASED_DATE) > 1
           )
        )
  )

Python

传递带有在 Access 引擎中处理的日期的参数。

conn = pyodbc.connect(r'...')
insights_dbcurs = conn.cursor()

sql = """DELETE FROM RELEASES r
         WHERE r.ID IN
           (SELECT sub.ID 
            FROM RELEASES sub
            WHERE sub.RELEASED_BY = ? 
              AND (
                    (
                     DatePart('m', sub.RELEASED_DATE) = DatePart('m', Date()) - 1
                     AND DatePart('yyyy', sub.RELEASED_DATE) = DatePart('yyyy', Date())
                     AND DatePart('d', sub.RELEASED_DATE) = 1
                    )
                   OR 
                    (
                     DatePart('m', sub.RELEASED_DATE) = DatePart('m', Date())
                     AND DatePart('yyyy', sub.RELEASED_DATE) = DatePart('yyyy', Date())
                     AND DatePart('d', sub.RELEASED_DATE) > 1
                    )
                  )
           )"""

insights_dbcurs.execute(sql, ('27',))
conn.commit()
conn.close()