1

ORMなしでSQLAlchemyコア機能を使用しており、リストを引数として渡す主キーを使用して、任意のテーブルからレコードをロードする必要があります。

現在、私はそれを次のようにやっています:

records = select([arbitrary_table], list(arbitrary_table.primary_key.columns._all_cols)[0].in_([1, 2, 3]))

arbitrary_tableはパラメータとして渡され、主キーが整数で複合ではないという制限のある任意のテーブルにすることができますが、主キーの名前は異なる可能性があります。

私はそれについていくつか質問があります:

Q1: それを最適化する方法はありますか?list(self.arbitrary_table.primary_key.columns._all_cols)[0]これが主キー列を取得するための最良の方法ではないと確信しています。

Q2: ORMクエリで同じことを行う方法は?SAサイトの例my_user = session.query(User).get(5)にはありますが、引数としてIDを1つだけ取り、IDのリストを取得するためのオーバーライドはありません。

私はあなたの提案に非常に感謝します。

4

1 に答える 1

2

「primary_key」属性はのインスタンスでありPrimaryKeyConstraint、その場で反復可能であるlist(table.primary_key)[0]ため、その列で取得する必要があるのはこれだけです。

以下の例は、2つの複合互換技術を示しています(編集:「複合ではない」と言いました。とにかくクールなコードです... select_by_single_pk()を使用してください)。1つはタプルサポート(postgresql、おそらくmysql)が必要で、もう1つは文字列です。 AND / OR、および単一のPKアプローチ。次に、タプルを受け入れるquery.get()を表示します。

from sqlalchemy import tuple_, or_, and_

def select_by_composite_pk(table, values):
    "works only in a high-capability database like postgresql"
    return table.select().where(tuple_(*table.primary_key).in_(values))

def select_by_composite_pk_no_tuples(table, values):
    "works in any database"

    return table.select().where(
            or_(
                *[
                    and_(*[col == val for col, val in zip(table.primary_key, val)])
                    for val in values
                ]
            ))

def select_by_single_pk(table, values):
    "works in any database"
    return table.select().where(list(table.primary_key)[0].in_(values))

if __name__ == '__main__':
    from sqlalchemy import create_engine, Table, Column, Integer, MetaData

    eng = create_engine("postgresql://scott:tiger@localhost/test", echo=True)

    conn = eng.connect()
    trans = conn.begin()

    m = MetaData()

    # single PK column
    a = Table('a', m, Column('x', Integer, primary_key=True),
                            Column('y', Integer))

    # composite PK column
    b = Table('b', m, Column('x', Integer, primary_key=True),
                    Column('y', Integer, primary_key=True))

    m.create_all(conn)

    conn.execute(a.insert(), [
            {'x': i, 'y': i * 2} for i in xrange(10)
        ])
    conn.execute(b.insert(), [
            {'x': i, 'y': i * 2} for i in xrange(10)
        ])

    print conn.execute(
                select_by_composite_pk(a,
                    [tuple_(3, ), tuple_(5, ), tuple_(9, )])).fetchall()

    print conn.execute(
                select_by_composite_pk(b,
                    [tuple_(3, 6), tuple_(5, 10), tuple_(9, 18)])).fetchall()

    print conn.execute(
                select_by_composite_pk_no_tuples(b,
                    [(3, 6), (5, 10), (9, 18)])).fetchall()

    print conn.execute(
                select_by_single_pk(b, [3, 5, 9])).fetchall()

    # ORM query version
    from sqlalchemy.orm import Session
    from sqlalchemy.ext.declarative import declarative_base

    Base = declarative_base()

    class MyCompositeClass(Base):
        __table__ = b

    # get accepts a tuple
    print Session(conn).query(MyCompositeClass).get((5, 10))
于 2013-03-12T01:58:28.163 に答える