Удаление строк из таблицы доступа на основе нескольких условий в Python вместе с полем даты - PullRequest
0 голосов
/ 14 сентября 2018

Я пытаюсь удалить строки из таблицы базы данных доступа, основанной на двух столбцах, один из которых Release_by и release_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' не имеет атрибута 'autoreleases'

если я уберу Row.autorelease, я получу

sql имеет 0 атрибутов, 2 передается.

Как мне этого избежать. Любые предложения будут очень полезны.

1 Ответ

0 голосов
/ 14 сентября 2018

Рассмотрите возможность перефакторинга вашего кода по нескольким причинам:

  1. try/except обычно используется для обработки исключений и ошибок времени выполнения, а не для логики приложения.Используйте if/else для этих ситуаций.

  2. Удалите ненужный цикл for, так как вы не удаляете строку за строкой, поскольку в операторы DELETE не передается уникальный идентификатор.В действительности вы выполняете процесс удаления по всей таблице, если логика передает текущую строку, не отфильтрованную, в эту строку.

  3. Используйте чистый SQL с одним оператором DELETE и избегайтеОбработка Python элементов времени, которая, как вы видите, поддерживает проблемы конвертации из базы данных.MS Access SQL имеет функции даты, такие как Date() (текущая дата) и DatePart() для извлечения месяца / дня.Кроме того, MS Access может выполнять сложную логику подзапроса в DELETE.

SQL

с использованием подзапроса INдля обоих условий даты.ПРИМЕЧАНИЕ: ID следует заменить уникальным идентификатором таблицы.Проверьте SELECT версию запроса до DELETE версии.

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()
...