2

我的数据库模型类中有许多方法可以执行参数化的 SQLSELECT语句。这些查询中的大多数都包含一个WHERE带有过滤结果的字段的子句。在默认情况下,我想忽略 where 子句中的比较以获取所有结果。一个例子:

def get_notes(self, pcb_serial_no, note_type=None):
    ''' Get notes recorded against a PCB unit, optionally filtered by note_type. '''
    cursor = self.db.execute('''
        SELECT pcb_serial_no, note_type, description, username, note_time
        FROM pcb_notes_view
        WHERE pcb_serial_no=?
            AND COALESCE(?, note_type)=note_type
        ''',
        (pcb_serial_no, note_type,)
    )
    rows = cursor.fetchall()
    return len(rows) > 0 and rows

我正在使用默认参数值None(映射到NULL)和COALESCE. 这是迄今为止我能想到的最好的可读性解决方案(当然是主观的),但我确信这个“默认参数”是一个常见的要求,并且想知道有哪些惯用的方法来实现它?我也不确定COALESCE在默认情况下是否会对性能产生重大影响,特别是如果该列没有被索引?

4

1 回答 1

2

不幸的是,评论系统不适合发布示例,但是 SQLAlchemy 与原始 SQL 的映射几乎是 1:1,我发现这种方法比从字符串操作中编写语句更好。所以这更像是一个评论而不是一个答案,我希望你能原谅我。

重写你的函数 ORM 风格会导致类似:

def get_notes(self, pcb_serial_no, note_type=None):
    ''' Get notes recorded against a PCB unit, optionally 
        filtered by note_type. '''
    q = sql.select([
            pcb_notes_view.pcb_serial_no, 
            pcb_notes_view.note_type, 
            pcb_notes_view.description, 
            pcb_notes_view.username, 
            pcb_notes_view.note_time
        ]).where(
            pcb_notes_view.pcb_serial_no==pcb_serial_no
        )
    if note_type is not None:
        q = q.where(pcb_notes_view.note_type==note_type)
    rows = q.execute().fetch_all()
    return len(rows) > 0 and rows

由于 ORM 使得重用查询变得如此简单,并且 ORM 可以猜测表之间的关系(对于具有引用完整性的数据库),我倾向于定义 ORM 查询而不是视图(从 SQLSoup 映射视图需要更多的工作)。结合来自优秀 IDE(我使用 PyCharm)的智能自动完成功能,我完全可以使用 ORM 提高工作效率。

但这是一个品味问题。也可以使用存储过程将所有逻辑移至数据库。

于 2013-06-14T01:58:59.790 回答