Python的ORM架構中SQLAlchemy庫的查詢操作的教程_python

來源:互聯網
上載者:User

1. 返回列表和標量(Scalar)

前面我們注意到Query對象可以返回可迭代的值(iterator value),然後我們可以通過for in來查詢。不過Query對象的all()、one()以及first()方法將返回非迭代值(non-iterator value),比如說all()返回的是一個列表:

>>> query = session.query(User).\>>>     filter(User.name.like('%ed')).order_by(User.id)>>> query.all() SELECT users.id AS users_id,    users.name AS users_name,    users.fullname AS users_fullname,    users.password AS users_passwordFROM usersWHERE users.name LIKE ? ORDER BY users.id('%ed',) [User('ed','Ed Jones', 'f8s7ccs'), User('fred','Fred Flinstone', 'blah')]

first()方法限制並僅作為標量返回結果集的第一條記錄:

>>> query.first() SELECT users.id AS users_id,    users.name AS users_name,    users.fullname AS users_fullname,    users.password AS users_passwordFROM usersWHERE users.name LIKE ? ORDER BY users.id LIMIT ? OFFSET ?('%ed', 1, 0) <User('ed','Ed Jones', 'f8s7ccs')>

one()方法,完整的提取所有的記錄行,並且如果沒有明確的一條記錄行(沒有找到這條記錄)或者結果中存在多條記錄行,將會引發錯誤異常NoResultFound或者MultipleResultsFound:

>>> from sqlalchemy.orm.exc import MultipleResultsFound>>> try: ...   user = query.one()... except MultipleResultsFound, e:...   print eSELECT users.id AS users_id,    users.name AS users_name,    users.fullname AS users_fullname,    users.password AS users_passwordFROM usersWHERE users.name LIKE ? ORDER BY users.id('%ed',) Multiple rows were found for one()>>> from sqlalchemy.orm.exc import NoResultFound>>> try: ...   user = query.filter(User.id == 99).one()... except NoResultFound, e:...   print eSELECT users.id AS users_id,    users.name AS users_name,    users.fullname AS users_fullname,    users.password AS users_passwordFROM usersWHERE users.name LIKE ? AND users.id = ? ORDER BY users.id('%ed', 99) No row was found for one()

2. 使用原義SQL (Literal SQL)

Query對象能夠靈活的使用原義SQL查詢字串作為查詢參數,比如我們之前用過的filter()和order_by()方法:

>>> for user in session.query(User).\...       filter("id<224").\...       order_by("id").all(): ...   print user.nameSELECT users.id AS users_id,    users.name AS users_name,    users.fullname AS users_fullname,    users.password AS users_passwordFROM usersWHERE id<224 ORDER BY id() edwendymaryfred

當然很多人可能會和我感覺一樣,會有些不適應,因為使用ORM就是為了擺脫SQL語句的,沒想到現在又看到SQL的影子了。呵呵,SQLAlchemy也要照顧到使用上的靈活性嘛,畢竟有些查詢語句直接編入要容易得多。

當然綁定參數也可以用基於字串的SQL指派,使用冒號來標記替代參數,然後再使用params()方法指定相應的值:

>>> session.query(User).filter("id<:value and name=:name").\...   params(value=224, name='fred').order_by(User.id).one() SELECT users.id AS users_id,    users.name AS users_name,    users.fullname AS users_fullname,    users.password AS users_passwordFROM usersWHERE id<User('fred','Fred Flinstone', 'blah')>

到這裡,SQL語句的樣子已經初見端倪了,其實我們可以更極端一點,直接使用SQL語句,什嗎?這樣就失去ORM的價值了!別急,這裡只是介紹一下支援這種用法,當然我建議不到萬不得已,盡量不要這樣寫,因為可能會有相容的問題,畢竟各個資料庫的SQL方言不一樣。不過有一點需要注意的是,如果要直接使用原生SQL語句,在被query()所查詢的映射類中,你必須保證語句所指代的列仍然被映射類所管理,比如接下來的例子:

>>> session.query(User).from_statement(...           "SELECT * FROM users where name=:name").\...           params(name='ed').all()SELECT * FROM users where name=?('ed',) [<User('ed','Ed Jones', 'f8s7ccs')>]

我們還可以在query()中直接使用列名來指派我們想要的列而擺脫映射類的束縛:

>>> session.query("id", "name", "thenumber12").\...     from_statement("SELECT id, name, 12 as "...         "thenumber12 FROM users where name=:name").\...         params(name='ed').all()SELECT id, name, 12 as thenumber12 FROM users where name=?('ed',) [(1, u'ed', 12)]

3. 計數 (Counting)

對於Query來說,計數功能也有個單獨的方法稱為count():

>>> session.query(User).filter(User.name.like('%ed')).count() SELECT count(*) AS count_1FROM (SELECT users.id AS users_id,        users.name AS users_name,        users.fullname AS users_fullname,        users.password AS users_passwordFROM usersWHERE users.name LIKE ?) AS anon_1('%ed',) 2

count()方法被用於確定返回的結果集中有多少行,讓我們觀察一下產生的SQL語句,SQLAlchemy先是取出合格所有行集合,然後再通過SELECT count(*)來統計有多少行。當然有點SQL知識的同學可能知道這條語句可以以更精簡的方式寫出來,比如SELECT count(*) FROM table,當然現代版本的SQLAlchemy不會去揣摩這樣的想法。

假使我們要讓查詢語句更加精鍊或者要明確要統計的列,我們可以通過運算式func.count()直接使用count函數,比如下面的例子介紹統計並返回每個唯一的使用者名稱字:

>>> from sqlalchemy import func>>> session.query(func.count(User.name), User.name).group_by(User.name).all() SELECT count(users.name) AS count_1, users.name AS users_nameFROM users GROUP BY users.name() [(1, u'ed'), (1, u'fred'), (1, u'mary'), (1, u'wendy')]

對於剛才提到的簡單SELECT count(*) FROM table語句,我們可以通過下面的例子來實現:

>>> session.query(func.count('*')).select_from(User).scalar()SELECT count(?) AS count_1FROM users('*',) 4

當然如果我們直接統計User的主鍵,上面的語句可以更加簡練,我們可以省去select_from()方法:

>>> session.query(func.count(User.id)).scalar() SELECT count(users.id) AS count_1FROM users() 4

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.