使用Python脚本删除SQL数据库中的多个条目

问题描述 投票:-2回答:1

我是Python和SQL的新手,但我需要删除远程服务器上的表中的多个条目。我还希望保留我给出的函数的输入结构,因为它在其他同事的代码中使用。

我提出了一个解决方案,可以完成类似于下面提到的工作。我故意避免使用任何类型的executemany()方法,因为(如果我没有记错的话),它们可能非常慢。

import sqlalchemy as sa
import urllib

def delete_rows(tablename, colnames, data):
    """
    tablename - name of db table with dbname. like RiskData..factors
    colnames - column names to use as keys in deletion
    data - a list of tuples, a tuple per row, number of elements in each
           tuple must is the same as number of column names
    """

    # Connection details
    engine = sa.create_engine("mssql+pyodbc://some_server")
    connection = self.engine.connect()

    # Data has to be a list - throw an exception if it is not
    if (not (type(data) is list)):
        raise Exception('Data must be a list');

    #  assemble one long query statement
    query = "DELETE " + tablename + " WHERE "
    query_dp = "or (" + " = '{}' and ".join(colnames) + "= '{}') "
    query_tail = ""
    for record_entries in data:
        query_tail += query_dp.format(*record_entries)
    query += query_tail[3:-1]
    connection.execute(query)

    connection.close()

我想问一下这个解决方案是否效率低,而且对于大量数据来说会很慢?如果是这样,那么更优雅的解决方案是什么?

python sqlalchemy sql-delete
1个回答
1
投票

不知道速度,但就优雅而言,don't use string formatting for passing values to SQL queries。由于您已经在使用SQLAlchemy,因此可以利用其查询构建功能:

def delete_rows(tablename, colnames, data):
    """
    tablename - name of db table with dbname. like RiskData..factors
    colnames - column names to use as keys in deletion
    data - a list of tuples, a tuple per row, number of elements in each
           tuple must is the same as number of column names
    """
    # Data has to be a list - throw an exception if it is not
    if not isinstance(data, list):
        raise Exception('Data must be a list');

    # Connection details
    engine = sa.create_engine("mssql+pyodbc://some_server")

    # Create `column()` objects for producing bindparams
    cols = [sa.column(name) for name in colnames]
    # Create a list of predicates, to be joined with OR
    preds = []
    for record_entries in data:
        pred = sa.and_(*[c == e for c, e in zip(cols, record_entries)])
        preds.append(pred)
    # assemble one long query statement
    query = sa.table(tablename).delete().where(sa.or_(*preds))

    with engine.begin() as connection:
        connection.execute(query)

executemany()是否很慢取决于使用的DB-API驱动程序。在pyodbc this used to be true的情况下,但there's been work to improve it

© www.soinside.com 2019 - 2024. All rights reserved.