2017-12-21 3 views
-2

저는 Python과 SQL을 처음 사용하지만 원격 서버의 테이블에서 여러 항목을 삭제해야합니다. 또한 다른 동료의 코드에서 사용 되었기 때문에 주어진 함수의 입력 구조를 보존하는 것을 선호합니다.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() 

이 솔루션이 비효율적이며 대량의 데이터를 처리하는 데 어려움이 있습니까? 그렇다면보다 우아한 해결책은 무엇입니까?

+2

'DELETE' 문에서 여러 개의 열과 일치합니까? data = 1, columns ='[ 'id', 'street_num']'을 주면 어떻게 될까요? id = 1 및 street_num = 1 인 행을 모두 삭제합니까? 그게 니가 원하는거야? – hansaplast

+1

ORM을 사용하는 것이 더 좋지 않습니까? 예, 장고? – style

+2

@hansaplast, 내 문제의 일부 세부 사항이 부족한 경우 미안 해요. 항목을 삭제하려고합니다. 사용자가 제안한 입력을 시도하면 오류가 발생합니다. 만약 내가'data = [(1,2), (3,4)]'와'colnames = [ 'id', 'street']'와 같은 입력을 사용한다면, id = 1, street = 2) 및 (id = 3, street = 4). –

답변

1

속도에 대해서는 알지 못하지만, 우아함에 대해서는 don't use string formatting for passing values to SQL queries입니다. 이미 SQLAlchemy의를 사용하고 있기 때문에, 당신은 쿼리 작성 기능을 활용할 수 있습니다 : 사용하고있는 DB-API 드라이버에 따라 달라집니다

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() 속도가 느린 여부. pyodbcthis used to be true의 경우, there's been work to improve it.

관련 문제