GVKun编程网logo

在SQLAlchemy中查询属性列表而不是元组(sqlalchemy查询指定字段)

9

对于想了解在SQLAlchemy中查询属性列表而不是元组的读者,本文将提供新的信息,我们将详细介绍sqlalchemy查询指定字段,并且为您提供关于python–在SQLAlchemy中,如何查询复合

对于想了解在SQLAlchemy中查询属性列表而不是元组的读者,本文将提供新的信息,我们将详细介绍sqlalchemy查询指定字段,并且为您提供关于python – 在SQLAlchemy中,如何查询复合主键?、SqlAlchemy:筛选以匹配所有而不是列表中的任何值?、为什么查询在SQLAlchemy中调用自动刷新?、删除未在sqlalchemy中级联到表的有价值信息。

本文目录一览:

在SQLAlchemy中查询属性列表而不是元组(sqlalchemy查询指定字段)

在SQLAlchemy中查询属性列表而不是元组(sqlalchemy查询指定字段)

我正在查询模型的ID,并获得一个(int,)元组列表,而不是ID列表。有没有一种直接查询属性的方法?

result = session.query(MyModel.id).all()

我知道有可能做

results = [r for (r,) in results]

查询是否可以直接返回该表单,而不必自己处理呢?

python – 在SQLAlchemy中,如何查询复合主键?

python – 在SQLAlchemy中,如何查询复合主键?

我正在使用sqlAlchemy以编程方式查询具有复合外键的表.例如.:

CREATE TABLE example (
id INT NOT NULL,date TIMESTAMP NOT NULL,data VARCHAR(128)
PRIMARY KEY (id,date)
)

我想拿一个值列表并获取行例如:

interesting_data = (
    (1,'2016-5-1'),(1,'2016-6-1'),(2,(3,)
select(
    [example.c.id,example.c.date,example.c.data],).where(example.primary_key.in_(interesting_data)

如果每列都是独立的,我可以做到

interesting_ids = [1,2,3]
interesting_dates = ['2016-5-1','2016-6-1']
select(
    [example.c.id,).where(
    example.c.id.in_(interesting_ids)
).where(
    example.c.date.in_(interesting_dates)
)

但这显然无法仅带来唯一匹配(id,date)元组.我怀疑有一种方法可以指定要查询的复合主键,但搜索后找不到任何文档.

最佳答案
在where子句中使用list comprehension:

from sqlalchemy import and_,or_,select

stmt = select(
    [example.c.id,example.c.data]
).where(or_(and_(example.c.id==data[0],example.c.date==data[1])
            for data in interesting_data))

但是,我注意到的另一个问题是您将日期列与字符串数据类型进行比较. interesting_data列表应该是

import datetime as dt

interesting_data = (
    (1,dt.date(2016,5,1)),6,)

另请注意,可以创建基本语句,然后逐步向其添加子句,从而导致(希望)更好的易读性和代码重用.

因此,可以将上面的内容写成

base_stmt = select([example.c.id,example.c.data])
wheres = or_(and_(example.c.id==data[0],example.c.date==data[1])
             for data in interesting_data))
stmt = base_stmt.where(wheres)

这会生成以下sql(由我添加的新行和空格):

SELECT example.id,example.date,example.data 
FROM example 
WHERE 
   example.id = :id_1 AND example.date = :date_1 
OR example.id = :id_2 AND example.date = :date_2
OR example.id = :id_3 AND example.date = :date_3 
OR example.id = :id_4 AND example.date = :date_4 
OR example.id = :id_5 AND example.date = :date_5

注意:如果要像这样过滤很多行,那么创建临时表,从interesting_data向此临时表插入行,然后将内部连接插入此表可能更有效,而不是如图所示添加where子句以上.

SqlAlchemy:筛选以匹配所有而不是列表中的任何值?

SqlAlchemy:筛选以匹配所有而不是列表中的任何值?

我想查询一个结表列的值aID匹配ID列表的所有值ids=[3,5]bID

这是我的联结表(JT):

 aID    bID
   1      1
   1      2
   2      5
   2      3
   1      3
   3      5

我有这个查询: session.query(JT.aID).filter(JT.bID.in_(ids)).all()

该查询返回的aID12并且3因为它们都与行的任一35bID列。我希望查询返回的内容是2因为这是唯一在其列aID中具有ids列表所有值的值bID

不知道如何更好地解释问题,但是我如何得出结果呢?

为什么查询在SQLAlchemy中调用自动刷新?

为什么查询在SQLAlchemy中调用自动刷新?

您在上面看到的代码只是一个示例,但是可以重现此错误:

sqlalchemy.exc.IntegrityError: (raised as a result of Query-invoked autoflush; consider using a session.no_autoflush block if this flush is occurring prematurely)(sqlite3.IntegrityError) NOT NULL constraint failed: X.nn [SQL: ''INSERT INTO "X" (nn, val) VALUES (?, ?)''] [parameters: (None, 1)]

映射的实例仍添加到会话中。该实例想知道(这意味着在数据库上查询)是否存在其他自己实例类型具有相同值的实例。还有第二个属性/列(_nn)。它指定为NOTNULL。但默认情况下为NULL

当实例(如示例中)仍添加到会话中时,将query.one()调用一个调用以自动刷新。刷新创建一个INSERT尝试存储实例的。之所以失败,_nn是因为它仍然为null并违反了NOTNULL约束。

这就是我目前所了解的。但是问题是为什么它要调用自动冲洗?我可以阻止吗?

#!/usr/bin/env python3import os.pathimport osimport sqlalchemy as sa import sqlalchemy.orm as saoimport sqlalchemy.ext.declarative as sadfrom sqlalchemy_utils import create_database_Base = sad.declarative_base()session = Noneclass X(_Base):    __tablename__ = ''X''    _oid = sa.Column(''oid'', sa.Integer, primary_key=True)    _nn = sa.Column(''nn'', sa.Integer, nullable=False) # NOT NULL!    _val = sa.Column(''val'', sa.Integer)    def __init__(self, val):        self._val = val    def test(self, session):        q = session.query(X).filter(X._val == self._val)        x = q.one()        print(''x={}''.format(x))dbfile = ''x.db''def _create_database():    if os.path.exists(dbfile):        os.remove(dbfile)    engine = sa.create_engine(''sqlite:///{}''.format(dbfile), echo=True)    create_database(engine.url)    _Base.metadata.create_all(engine)    return sao.sessionmaker(bind=engine)()if __name__ == ''__main__'':    session = _create_database()    for val in range(3):        x = X(val)        x._nn = 0        session.add(x)    session.commit()    x = X(1)    session.add(x)    x.test(session)

当然,解决方案是在调用之前
将实例添加到会话query.one()中。这项工作。但是在我的实际(但是对于这个问题来说很复杂)的用例中,这不是一个很好的解决方案。

答案1

小编典典

如何关闭自动冲洗功能:

  • 临时的:您可以在查询数据库的代码段中使用no_autoflush上下文管理器,即在X.test方法中:

    def test(self, session):with session.no_autoflush:    q = session.query(X).filter(X._val == self._val)    x = q.one()    print(''x={}''.format(x))
  • autoflush=False全会期:只需传递给您的会议主持人即可:

    return sao.sessionmaker(bind=engine, autoflush=False)()

删除未在sqlalchemy中级联到表

删除未在sqlalchemy中级联到表

我正在开发使用sqlalchemy 0.6的现有应用程序的扩展。

该应用程序具有以非声明方式创建的sqlalchemy表。我正在尝试在扩展程序中创建一个新表,该表的外键列指向应用程序数据库中主表的主键,并且以声明方式创建它。

这一切都很好,加载扩展程序后就创建了表,一点也没有抱怨。我的表将打印出来,并演示已经添加了新行。我想要并认为可能的(但不知道,因为我从未使用过sql或任何其他数据库)是在删除应用程序主表中具有相应外键的行时删除表中的相应行。

到目前为止,已经尝试了许多排列,但没有任何效果。我认为设置了backref并定义了具有级联的delete的关系,应该不会有问题。因为新表是在扩展名中定义的,扩展名应该只是插件,所以我根本不想编辑主应用程序中的代码,至少这是我的目标。但是,我遇到的问题之一是我要引用的主应用程序表,在其类中没有定义成员变量,未在其映射器中声明其主键并且仅在表中声明了主键。
。这使得很难创建一个Relation(ship)子句,该子句的第一个自变量必须是类或映射器(在这种情况下,都没有声明主键)。有什么办法可以做到这一点?

ps-这是我正在使用的一些代码。LocalFile是声明性类。所有连接细节均由主应用程序处理。

    if not self.LocalFile.__table__.exists(bind=Engine):        self.LocalFile__table__.create(bind=Engine)

这是LocalFile类-基类是声明性基类,在构造函数中传递了bind = Engine:

   class LocalFile(Base):    __tablename__ = ''local_file''    _id = Column(Integer, Sequence(''local_file_sequence'', start=1, increment=1), primary_key=True)    _filename = Column(String(50), nullable=False)    _filepath = Column(String(128), nullable=False)    _movieid = Column(Integer, ForeignKey(db.tables.movies.c.movie_id, onupdate=''CASCADE'', ondelete=''CASCADE''))    #movies = relation(db.Movie, backref="local_file", cascade="all")    @property    def filename(self):        return self._filename    @filename.setter    def filename(self, filename):        self._filename = filename    @property    def filepath(self):        return self._filepath    @filepath.setter    def filepath(self, filepath):        self._filepath = filepath    @property    def movieid(self):        return self._movieid    @movieid.setter    def movieid(self, movieid):        self._movieid = movieid    @property    def id(self):        return self._id    @id.setter    def id(self, id):        self._id = id    filename = synonym(''_filename'', descriptor=filename)    movieid = synonym(''_movieid'', descriptor=movieid)    filepath = synonym(''_filepath'', descriptor=filepath)    id = synonym(''_id'', descriptor=id)    def __init__(self, filename, filepath, movieid):        self._filename = filename        self._filepath = filepath        self._movieid = movieid    def __repr__(self):        return "<User(''%s'',''%s'', ''%s'')>" % (self.filename, self.filepath, self.movieid)

编辑:

后端是sqlite3。下面是使用echo命令生成的表的创建代码(感谢您指出这一点,它非常有用-
我已经怀疑现有应用程序生成的SQL远远超出了必要)。报告的sql表创建之后是删除行时生成的代码。我个人看不到任何引用本地文件表中可能删除行的语句,但是我目前几乎不了解sql。谢谢。

     2011-12-29 16:29:18,530 INFO sqlalchemy.engine.base.Engine.0x...0650      CREATE TABLE local_file (_id INTEGER NOT NULL, _filename VARCHAR(50) NOT NULL, _filepath VARCHAR(128) NOT NULL, _movieid INTEGER, PRIMARY KEY (_id), FOREIGN KEY(_movieid) REFERENCES movies (movie_id) ON DELETE CASCADE ON UPDATE CASCADE

    2011-12-29T16:29:18: I: sqlalchemy.engine.base.Engine.0x...0650(base:1387):     CREATE TABLE local_file (_id INTEGER NOT NULL, _filename VARCHAR(50) NOT NULL, _filepath VARCHAR(128) NOT NULL, _movieid INTEGER, PRIMARY KEY (_id), FOREIGN KEY(_movieid) REFERENCES movies (movie_id) ON DELETE CASCADE ON UPDATE CASCADE

2011-12-29 16:29:18,534 INFO sqlalchemy.engine.base.Engine.0x...0650 ()2011-12-29T16:29:18: I: sqlalchemy.engine.base.Engine.0x...0650(base:1388): ()2011-12-29 16:29:18,643 INFO sqlalchemy.engine.base.Engine.0x...0650 COMMIT2011-12-29T16:29:18: I: sqlalchemy.engine.base.Engine.0x...0650(base:1095): COMMIT

表中的行会为两个表生成以下内容:

本地文件表:(,u‘310 To Yuma’)(,u’Ravenous’)

现有应用中的电影表:(,u’IMDb-3:10 to Yuma’)(,u’Ravenous’)

删除行时的代码太长,以至于我无法在此处包括它(大约200行-删除一行不是太多吗?),但是它没有引用删除localfile表中的行。有如下语句:

   2011-12-29 17:09:17,141 INFO sqlalchemy.engine.base.Engine.0x...0650 UPDATE movies SET   poster_md5=?, updated=? WHERE movies.movie_id = ?   2011-12-29T17:09:17: I: sqlalchemy.engine.base.Engine.0x...0650(base:1387): UPDATE movies SET poster_md5=?, updated=? WHERE movies.movie_id = ?   2011-12-29 17:09:17,142 INFO sqlalchemy.engine.base.Engine.0x...0650 (None, ''2011-12-29 17:09:17.141019'', 2)   2011-12-29T17:09:17: I: sqlalchemy.engine.base.Engine.0x...0650(base:1388): (None, ''2011-12-29 17:09:17.141019'', 2)   2011-12-29 17:09:17,150 INFO sqlalchemy.engine.base.Engine.0x...0650 DELETE FROM posters WHERE posters.md5sum = ?   2011-12-29T17:09:17: I: sqlalchemy.engine.base.Engine.0x...0650(base:1387): DELETE FROM posters WHERE posters.md5sum = ?   2011-12-29 17:09:17,157 INFO sqlalchemy.engine.base.Engine.0x...0650 (u''083841e14b8bb9ea166ea4b2b976f03d'',)

答案1

小编典典

在SQLite中,您必须显式打开对外键的支持,否则它将忽略任何与外键相关的SQL。

engine = create_engine(database_url)def on_connect(conn, record):    conn.execute(''pragma foreign_keys=ON'')from sqlalchemy import eventevent.listen(engine, ''connect'', on_connect)

关于在SQLAlchemy中查询属性列表而不是元组sqlalchemy查询指定字段的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于python – 在SQLAlchemy中,如何查询复合主键?、SqlAlchemy:筛选以匹配所有而不是列表中的任何值?、为什么查询在SQLAlchemy中调用自动刷新?、删除未在sqlalchemy中级联到表的相关知识,请在本站寻找。

本文标签: