自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳解 pypika 模塊:SQL 語(yǔ)句生成器,讓你再也不用為拼接 SQL 語(yǔ)句而發(fā)愁

數(shù)據(jù)庫(kù) 其他數(shù)據(jù)庫(kù)
不同數(shù)據(jù)庫(kù)的 SQL 語(yǔ)法會(huì)有略微不同,最大的一個(gè)不同就是包裹字段所用的符號(hào),MySQL 用的是反引號(hào)、PostgreSQL 用的是雙引號(hào)。而 pypika 不知道你的數(shù)據(jù)庫(kù)種類,所以默認(rèn)用的是雙引號(hào)。如果想適配 MySQL 的話,那么應(yīng)該告訴 pypika,我們要適配 MySQL。

楔子

作為一名后端開發(fā),日常工作中難免要和數(shù)據(jù)庫(kù)打交道,而想要操作數(shù)據(jù)庫(kù),必然要構(gòu)建 SQL 語(yǔ)句。你可以手動(dòng)編寫原生 SQL,也可以借助現(xiàn)有的第三方模塊,比如 pypika。

本篇文章就來(lái)介紹一下 pypika 的用法,由于是第三方庫(kù),需要先安裝,直接 pip install pypika 即可。

注:Python 還有一個(gè)第三庫(kù)叫 pika,是專門用來(lái)連接 RabbitMQ 的,這兩個(gè)名字雖然很像,但是之間沒(méi)有任何關(guān)系。

簡(jiǎn)單的 SELECT 查詢

構(gòu)建 SELECT 語(yǔ)句的入口點(diǎn)是 pypika.Query,而查詢數(shù)據(jù)的話必然要有兩個(gè)關(guān)鍵信息:表和字段。

from pypika import Query

query = Query.from_("people").select("id", "name", "age")
print(query)
"""
SELECT "id","name","age" FROM "people"
"""
# 返回的是一個(gè) QueryBuilder 對(duì)象
print(query.__class__)
"""
<class 'pypika.queries.QueryBuilder'>
"""
# 直接轉(zhuǎn)成字符串即可
print(str(query))
"""
SELECT "id","name","age" FROM "people"
"""
# 或者調(diào)用 get_sql 方法
print(query.get_sql())
"""
SELECT "id","name","age" FROM "people"
"""

以上我們就構(gòu)建了最簡(jiǎn)單的 SQL 語(yǔ)句,當(dāng)然表和字段都是以字符串形式指定的,我們還可以使用對(duì)象。

from pypika import Query, Table, Field

table = Table("people")
fields = [Field("id"), Field("name"), Field("age")]
query = Query.from_(table).select(*fields)
print(query)
"""
SELECT "id","name","age" FROM "people"
"""

# 有了對(duì)象之后,我們就可以指定別名了
table = Table("data").as_("d")
fields = [Field("max_count").as_("max_cnt")]
query = Query.from_(table).select(*fields)
print(query)
"""
SELECT "max_count" "max_cnt" FROM "data" "d"
"""

當(dāng)然目前只指定了表,如果希望在指定表的同時(shí)還指定數(shù)據(jù)庫(kù),要怎么做呢?

from pypika import Query, Table, Database

database = Database("fruits")
# 或者直接寫成 Table("apple", "fruits") 也可以
table = Table("apple", database)
query = Query.from_(table).select("name", "price")
print(query)
"""
SELECT "name","price" FROM "fruits"."apple"
"""

# 注意:我們不要寫成 Table("fruits.apple"),這是不對(duì)的
# 因?yàn)檫@表示從一張名為 "fruits.apple" 的表中獲取數(shù)據(jù)
# 顯然這是不符合規(guī)范的,表名不應(yīng)該包含 . 這種特殊字符
table = Table("fruits.apple")
query = Query.from_(table).select("name", "price")
print(query)
"""
SELECT "name","price" FROM "fruits.apple"
"""
# 注意 from 子句,結(jié)果是 "fruits.apple"
# 真正的格式應(yīng)該是 "fruits"."apple",而不是 "fruits.apple"

如果是 MySQL,那么層級(jí)是數(shù)據(jù)庫(kù)、表,但如果是 PostgreSQL,那么還會(huì)多一層 schema。如果想指定 schema,該怎么做呢?

from pypika import Query, Table, Database, Schema

# 數(shù)據(jù)庫(kù)
database = Database("fruits")
# schema,隸屬于指定的 database
schema = Schema("default", database)
# 表,隸屬于指定的 schema
table = Table("apple", schema)
# 構(gòu)建查詢
query = Query.from_(table).select("name", "price")
print(query)
"""
SELECT "name","price" FROM "fruits"."default"."apple"
"""

然后在篩選字段的時(shí)候,還可以對(duì)字段做操作。

from pypika import Query, Field

# 如果想對(duì)字段做操作,那么需要使用 Field 對(duì)象
query = Query.from_("t").select(
    Field("id") + 1,
    Field("first") + Field("last"),
    (Field("count") + 200) * Field("price")
)
print(query)
"""
SELECT "id"+1,"first"+"last",("count"+200)*"price" FROM "t"
"""

可以看到還是比較強(qiáng)大的,特別是會(huì)自動(dòng)給你加上引號(hào),這樣可以防止關(guān)鍵字沖突。

WHERE 條件過(guò)濾

在獲取數(shù)據(jù)的時(shí)候,很少會(huì)全量獲取,絕大多數(shù)都是獲取滿足指定條件的數(shù)據(jù),這個(gè)時(shí)候就需要使用 WHERE 語(yǔ)句。

from pypika import Query, Field

query = Query.from_("t").select("*").where(
    (Field("salary") >= 10000) &
    (Field("age").between(18, 30)) &
    (Field("name").like("張%")) &
    (Field("department").isin(["銷售", "財(cái)務(wù)"]))
)
print(query)
"""
SELECT * FROM "t" 
WHERE "salary">=10000 AND 
      "age" BETWEEN 18 AND 30 AND 
      "name" LIKE '張%' AND 
      "department" IN ('銷售','財(cái)務(wù)')
"""

你在數(shù)據(jù)庫(kù)中可以使用的語(yǔ)法,比如 IS NULL、NOT IN、IS NOT NULL 等等,在 Field 對(duì)象中都有指定的方法對(duì)應(yīng),并且這些方法都見名知意,可以自己試一下。

然后如果有多個(gè)條件,那么之間可以用 & 和 | 進(jìn)行組合,等價(jià)于 AND 和 OR。

分組和聚合

接下來(lái)說(shuō)一說(shuō) GROUP BY,既然提到它,那就必須要先了解如何在 pypika 中指定聚合函數(shù)。

from pypika import functions as fn, Field

fn.Count(Field("id"))
fn.Concat(Field("first_name"), "-", Field("last_name"))
fn.Substring(Field("name"), 3, 9)

所有的聚合函數(shù),都可以在 functions 模塊中找到。

from pypika import Field, Query
from pypika import functions as fn

query = Query.from_("people").select(
    "age", fn.Count(Field("id"))
).where(
    Field("age")[18: 30] & (Field("length") < 160)
).groupby("age")
print(query)
"""
SELECT "age",COUNT("id") FROM "people" 
WHERE "age" BETWEEN 18 AND 30 AND "length"<160 
GROUP BY "age"
"""

在指定字段的時(shí)候,可以直接傳一個(gè)字符串,也可以傳一個(gè) Field 對(duì)象。有時(shí)候?yàn)榱朔奖?,?dāng)不需要對(duì)字段做操作的時(shí)候,我們會(huì)直接傳一個(gè)字符串。

但對(duì)于 fn.Count 等聚合函數(shù)來(lái)說(shuō),里面一定要傳 Field 對(duì)象,至于原因我們測(cè)試一下就知道了。

from pypika import Field, Query
from pypika import functions as fn

query1 = Query.from_("t").select(fn.Substring("name", 1, 5))
query2 = Query.from_("t").select(fn.Substring(Field("name"), 1, 5))
# SUBSTRING 里面的第一個(gè)參數(shù)表示長(zhǎng)度為 4 的字符串
print(query1)
"""
SELECT SUBSTRING('name',1,5) FROM "t"
"""
# SUBSTRING 里面的第一個(gè)參數(shù)表示字段 name
print(query2)
"""
SELECT SUBSTRING("name",1,5) FROM "t"
"""

這就是兩者的區(qū)別,當(dāng)然有人會(huì)覺得這是 PostgreSQL 的語(yǔ)法吧,MySQL 應(yīng)該是反引號(hào)才對(duì),沒(méi)錯(cuò),后面的話我們會(huì)說(shuō)如何適配數(shù)據(jù)庫(kù)。因?yàn)閿?shù)據(jù)庫(kù)的種類不同,語(yǔ)法也會(huì)稍有不同,而目前沒(méi)有任何信息表明我們使用的到底是哪一種數(shù)據(jù)庫(kù)。

當(dāng)執(zhí)行了 GROUP BY 之后,還可以繼續(xù)執(zhí)行 HAVING。

from pypika import Field, Query
from pypika import functions as fn

query = Query.from_("people").select(
    "age", fn.Count(Field("id"))
).groupby("age").having(fn.Count(Field("id")) > 30)
print(query)
"""
SELECT "age",COUNT("id") FROM "people" 
GROUP BY "age" HAVING COUNT("id")>30
"""

以上就是分組和聚合。

兩表 JOIN

如果是兩張表需要 JOIN 的話,該怎么做呢?

from pypika import Query, Table

t1 = Table("t1")
t2 = Table("t2")

query = Query.from_(t1).select(
    t1.name, t2.age
).left_join(t2).using("id")
print(query)
"""
SELECT "t1"."name","t2"."age" FROM "t1" 
LEFT JOIN "t2" USING ("id")
"""

由于涉及到多張表,那么當(dāng)字段出現(xiàn)重疊的時(shí)候,需要同時(shí)指定表名,可以直接通過(guò)獲取 Table 對(duì)象屬性的方式指定。但如果表的字段名恰好和 Table 對(duì)象的某個(gè)屬性名沖突,就不行了,我們舉個(gè)例子。

from pypika import Query, Table

t1 = Table("t1")
t2 = Table("t2")
# 比如 Table 對(duì)象有一個(gè)屬性叫 field
# 而表中也有一個(gè)字段叫 field
query = Query.from_(t1).select(
    t2.field
).left_join(t2).using("id")
print(query)
"""
SELECT <bound method Selectable.field of Table('t2')> 
FROM "t1" LEFT JOIN "t2" USING ("id")
"""
print(t2.field)
"""
<bound method Selectable.field of Table('t2')>
"""

顯然這個(gè)時(shí)候就比較尷尬了,那我們應(yīng)該怎么做呢?

from pypika import Query, Table, Field

t1 = Table("t1")
t2 = Table("t2")
query = Query.from_(t1).select(
    Field("field", table=t2)
).left_join(t2).using("id")
print(query)
"""
SELECT "t2"."field" FROM "t1" LEFT JOIN "t2" USING ("id")
"""

這樣就沒(méi)問(wèn)題了,F(xiàn)ield 類還可以接收一個(gè) table 參數(shù),指定字段來(lái)自于哪張表,當(dāng)然如果是單表,那么該字段就無(wú)需指定了。

當(dāng)然除了 LEFT JOIN 之外,其它 JOIN 也是支持的。

這些方法內(nèi)部都調(diào)用了 join 方法。

如果兩張表要連接的字段的名字相同、并且是等值連接,那么可以使用 using。但還有一種情況是:兩個(gè)名字不同的字段進(jìn)行等值連接,比如一張表的 uid 等于另一張表的 tid 等等。

from pypika import Query, Table

t1 = Table("t1")
t2 = Table("t2")

# Field("uid", table=t1) 還可以寫成 t1.field("uid")
# 這兩者是完全等價(jià)的,但 t1.field("uid") 寫起來(lái)更方便
query = Query.from_(t1).select(t2.age, t1.name) \
    .left_join(t2) \
    .on(t1.field("uid") == t2.field("tid")) \
    .where(t1.age > 18)
print(query)
"""
SELECT "t2"."age","t1"."name" FROM "t1" 
LEFT JOIN "t2" ON "t1"."uid"="t2"."tid"
WHERE "t1"."age">18
"""

以上就是 JOIN 相關(guān)的內(nèi)容,至于三表連接,你可以自己試一下。

嵌套子查詢

再來(lái)看看嵌套子查詢:

from pypika import Query, Table, functions as fn

t1 = Table("t1")
t2 = Table("t2")

sub_query = Query.from_(t1).select(fn.Avg(t2.age).as_("avg")) \
    .left_join(t2).using("id").where(t1.age > 18)
print(sub_query)
"""
SELECT AVG("t2"."age") "avg" FROM "t1"
LEFT JOIN "t2" USING ("id") WHERE "t1"."age">18
"""

# 子查詢完全可以當(dāng)成一張表來(lái)操作
query = Query.from_(t1).select("age", "name").where(
    t1.field("age") > Query.from_(sub_query).select("avg")
)
print(query)
"""
SELECT "age","name" FROM "t1" 
WHERE "age">(
    SELECT "sq0"."avg" FROM (
        SELECT AVG("t2"."age") "avg" 
        FROM "t1" LEFT JOIN "t2" USING ("id") WHERE "t1"."age">18
    ) "sq0"
)
"""

集合運(yùn)算

兩個(gè)結(jié)果集之間是可以合并的,比如 UNION 和 UNION ALL,至于 UNION DISTINCE 是 UNION 的同義詞,所以 pypika 沒(méi)有設(shè)置專門的函數(shù)。另外 UNION 雖然可以用來(lái)合并多個(gè)結(jié)果集,但前提是它們要有相同的列。

from pypika import Query, Table

t1 = Table("t1")
t2 = Table("t2")

query1 = Query.from_(t1).select("name", "salary")
query2 = Query.from_(t2).select("name", "salary")

print(query1.union(query2))
print(query2.union(query1))
"""
(SELECT "name","salary" FROM "t1") UNION (SELECT "name","salary" FROM "t2")
(SELECT "name","salary" FROM "t2") UNION (SELECT "name","salary" FROM "t1")
"""
# union 可以使用 + 代替
print(str(query1 + query2) == str(query1.union(query2)))  # True
print(str(query2 + query1) == str(query2.union(query1)))  # True

# union_all 可以使用 * 代替
print(query1.union_all(query2))
print(query2.union_all(query1))
"""
(SELECT "name","salary" FROM "t1") UNION ALL (SELECT "name","salary" FROM "t2")
(SELECT "name","salary" FROM "t2") UNION ALL (SELECT "name","salary" FROM "t1")
"""
print(str(query1 * query2) == str(query1.union_all(query2)))  # True
print(str(query2 * query1) == str(query2.union_all(query1)))  # True

此外還有交集、差集、對(duì)稱差集。

from pypika import Query, Table

t1 = Table("t1")
t2 = Table("t2")

query1 = Query.from_(t1).select("name", "salary")
query2 = Query.from_(t2).select("name", "salary")

# 交集,沒(méi)有提供專門的操作符
print(query1.intersect(query2))
"""
(SELECT "name","salary" FROM "t1") 
INTERSECT 
(SELECT "name","salary" FROM "t2")
"""
# 差集,可以使用減號(hào)替代
print(query1.minus(query2))
"""
(SELECT "name","salary" FROM "t1") 
MINUS 
(SELECT "name","salary" FROM "t2")
"""
# 對(duì)稱差集,沒(méi)有提供專門的操作符
print(query1.except_of(query2))
"""
(SELECT "name","salary" FROM "t1") 
EXCEPT 
(SELECT "name","salary" FROM "t2")
"""

時(shí)間間隔

有時(shí)我們查找數(shù)據(jù)需要查找 7 天以內(nèi)的,或者 1 個(gè)月以內(nèi)的,這時(shí)候該怎么做呢?

from pypika import Query, Table, functions as fn, Interval

t = Table('fruits')

query = Query.from_(t).select(t.id, t.name) \
    .where(t.harvest_date + Interval(mnotallow=1) < fn.Now())
print(query)
"""
SELECT "id","name" FROM "fruits" 
WHERE "harvest_date"+INTERVAL '1 MONTH'<NOW()
"""

多值比較

SQL 有一個(gè)非常有用的特性,假設(shè)一張表中有 year、month 這兩個(gè)字段,然后我想找出 year、month 組合起來(lái)之后大于 2020 年 7 月的記錄。比如 year = 2021、month = 2 這條記錄就是合法的,因?yàn)?year 是大于 2020 的。而 year = 2020、month = 8 也是合法的。

顯然這個(gè)時(shí)候就有些不好搞了,我們無(wú)法通過(guò) year > 2020 and month > 7 這種形式,但是數(shù)據(jù)庫(kù)提供了多值比較:

select * from t where (year, month) > (2020, 7)

是不是很像元組呢?會(huì)先比較 year,如果滿足 year > 2020,直接成立。year < 2020,直接不成立,后面就不用比了。如果 year = 2020,那么再比較 month。

from pypika import Query, Table, Tuple

t = Table("t")

query = Query.from_(t).select(t.salary).where(
    Tuple(t.year, t.month) >= (2020, 7))
print(query)
"""
SELECT "salary" FROM "t" WHERE ("year","month")>=(2020,7)
"""

對(duì)于 in 字句也是同樣的道理:

from pypika import Query, Table, Tuple

t = Table("t")

query = Query.from_(t).select(t.salary).where(
    Tuple(t.year, t.month
          ).isin([(2020, 7), (2020, 8), (2020, 9)]))
print(query)
"""
SELECT "salary" FROM "t" 
WHERE ("year","month") IN ((2020,7),(2020,8),(2020,9))
"""

CASE WHEN

然后看看 CASE WHEN,SQL 層面上的就不說(shuō)了,我們只看怎么用 pypika 實(shí)現(xiàn)。

from pypika import Table, Query, Case

t = Table("t")

query = Query.from_(t).select(
    t.name,
    Case().when(t.age < 18, "未成年").when(t.age < 30, "成年")
    .when(t.age < 50, "中年").else_("老年").as_("age")
)
print(query)
"""
SELECT "name",
CASE WHEN "age"<18 THEN '未成年' 
     WHEN "age"<30 THEN '成年' 
     WHEN "age"<50 THEN '中年' 
     ELSE '老年' END "age" 
FROM "t"
"""

WITH 語(yǔ)句

WITH 語(yǔ)句就是給子查詢指定一個(gè)名字,然后在其它地方可以直接使用該名字,就像訪問(wèn)一張已存在的表一樣。

from pypika import Table, Query, AliasedQuery

t = Table("t")

sub_query = Query.from_(t).select("*")
query = Query.with_(sub_query, "alias").from_(
    AliasedQuery("alias")).select("*")
print(query)
"""
WITH alias AS (SELECT * FROM "t") SELECT * FROM alias
"""

DISTINCT

如果我們想對(duì)結(jié)果集進(jìn)行去重的話,要怎么做呢?

from pypika import Query, Table

t = Table("t")
# 只需要在 select 之前調(diào)用一次 distinct 即可
query = Query.from_(t).distinct().select(t.id, t.age)
print(query) 
"""
SELECT DISTINCT "id","age" FROM "t"
"""

ORDER BY 排序

在查詢到結(jié)果集之后,也可以進(jìn)行排序。

from pypika import Query, Order

query = Query.from_("t").select("id", "name") \
    .orderby("id", order=Order.desc)
print(query)
"""
SELECT "id","name" FROM "t" ORDER BY "id" DESC
"""

# 如果是多個(gè)字段的話
query = Query.from_("t").select("id", "name") \
    .orderby("age", "id")
print(query)
"""
SELECT "id","name" FROM "t" ORDER BY "age","id"
"""

query = Query.from_("t").select("id", "name") \
    .orderby("age", "id", order=Order.desc)
print(query)
"""
SELECT "id","name" FROM "t" ORDER BY "age" DESC,"id" DESC
"""

# 如果是一個(gè)字段升序、一個(gè)字段降序怎么辦?很簡(jiǎn)單,調(diào)用兩次 orderby 即可
query = Query.from_("t").select("id", "name") \
    .orderby("age", order=Order.desc).orderby("id")
print(query)
"""
SELECT "id","name" FROM "t" ORDER BY "age" DESC,"id"
"""

LIMIT 和 OFFSET

獲取到結(jié)果集之后,可以選擇指定的條數(shù),比如實(shí)現(xiàn)分頁(yè)功能。

from pypika import Table, Query, Field
from pypika import functions as fn, Order

table = Table("t")
query = Query.from_(table) \
    .select(fn.Count(Field("id")).as_("count"), "age", "length") \
    .where(table.field("age") > 18) \
    .groupby("age", "length") \
    .having(fn.Count("id") > 10) \
    .orderby("count", order=Order.desc) \
    .orderby("age", order=Order.asc) \
    .limit(10).offset(5)
print(query)
"""
SELECT COUNT("id") "count","age","length" 
FROM "t" WHERE "age">18 
GROUP BY "age","length" 
HAVING COUNT('id')>10 
ORDER BY "count" DESC,"age" ASC 
LIMIT 10 OFFSET 5
"""

這里我們將所有子句都演示了一遍,算是做一個(gè)總結(jié)。

插入數(shù)據(jù)

以上說(shuō)的都是查詢數(shù)據(jù),那么插入數(shù)據(jù)要怎么實(shí)現(xiàn)呢?

from pypika import Table, Query

t = Table("t")
# 查詢是 Query.from_,插入數(shù)據(jù)是 Query.into
query = Query.into(t).insert(1, "古明地覺", 16, "東方地靈殿")
print(query)
"""
INSERT INTO "t" VALUES (1,'古明地覺',16,'東方地靈殿')
"""

# 如果存在 None 值,會(huì)自動(dòng)處理
query = Query.into(t).insert(1, "古明地覺", None, "東方地靈殿")
print(query)
"""
INSERT INTO "t" VALUES (1,'古明地覺',NULL,'東方地靈殿')
"""

如果表中存在 JSON,那么直接對(duì)字典 dumps 一下傳進(jìn)去即可。

當(dāng)然上面是單條插入,如果我想同時(shí)插入多條數(shù)據(jù),該怎么做呢?

from pypika import Table, Query

table = Table("t")

query = Query.into(table) \
    .insert(1, "古明地覺", 16, "東方地靈殿") \
    .insert(2, "古明地戀", 15, "東方地靈殿")
print(query)
"""
INSERT INTO "t" 
VALUES (1,'古明地覺',16,'東方地靈殿'),
       (2,'古明地戀',15,'東方地靈殿')
"""

# 或者
query = Query.into(table).insert((1, "古明地覺", 16, "東方地靈殿"), 
                                 (2, "古明地戀", 15, "東方地靈殿"))
print(query)
"""
INSERT INTO "t" 
VALUES (1,'古明地覺',16,'東方地靈殿'),
       (2,'古明地戀',15,'東方地靈殿')
"""

在插入數(shù)據(jù)的時(shí)候,也可以選擇指定的部分字段。

from pypika import Table, Query, Field

table = Table("t")

query = Query.into(table).columns(
    "id", table.field("name"), table.age, Field("place")
).insert(1, "古明地覺", 16, "東方地靈殿")
print(query)
"""
INSERT INTO "t" ("id","name","age","place") 
VALUES (1,'古明地覺',16,'東方地靈殿')
"""

當(dāng)然也可以將一張表的記錄插入到另一張表中。

from pypika import Table, Query, Field

t1 = Table("t1")
t2 = Table("t2")

query = Query.into(t1).columns("id", "name", "age") \
    .from_(t2).select("id", "name", "age") \
    .where(Field("age") > 18)
print(query)
"""
INSERT INTO "t1" ("id","name","age") 
SELECT "id","name","age" FROM "t2" WHERE "age">18
"""

兩個(gè)表 JOIN 之后的結(jié)果也可以插入到新表中,不過(guò)在 Python 中拼接 SQL 語(yǔ)句的時(shí)候,很少會(huì)遇到這種需求。

更新數(shù)據(jù)

再來(lái)看看更新數(shù)據(jù)怎么做?

from pypika import Table, Query

t = Table("t")
# 更新是 update
query = Query.update(t).set(t.name, "古明地戀")
print(query)
"""
UPDATE "t" SET "name"='古明地戀'
"""
query = Query.update(t).set(t.name, "古明地戀").where(t.id == 1)
print(query)
"""
UPDATE "t" SET "name"='古明地戀' WHERE "id"=1
"""

query = Query.update(t).set(t.name, "古明地戀").set(t.age, 16)
print(query)
"""
UPDATE "t" SET "name"='古明地戀',"age"=16
"""

用另一張表的數(shù)據(jù)更新當(dāng)前也是一種比較常見的操作,比如 t1 有 uid、name 兩個(gè)字段,t2 有 tid、name 兩個(gè)字段。如果 t1 的 uid 在 t2 的 tid 中存在,那么就用 t2 的 name 更新掉 t1 的 name。

from pypika import Table, Query

t1 = Table("t1")
t2 = Table("t2")

query = Query.update(t1).join(t2).on(
    t1.uid == t2.tid
).set(t1.name, t2.name).where(t1.uid > 10)
print(query)
"""
UPDATE "t1" JOIN "t2" ON "t1"."uid"="t2"."tid" 
SET "name"="t2"."name" WHERE "t1"."uid">10
"""

數(shù)據(jù)庫(kù)適配

不同數(shù)據(jù)庫(kù)的 SQL 語(yǔ)法會(huì)有略微不同,最大的一個(gè)不同就是包裹字段所用的符號(hào),MySQL 用的是反引號(hào)、PostgreSQL 用的是雙引號(hào)。而 pypika 不知道你的數(shù)據(jù)庫(kù)種類,所以默認(rèn)用的是雙引號(hào)。如果想適配 MySQL 的話,那么應(yīng)該告訴 pypika,我們要適配 MySQL。

from pypika import (
    MySQLQuery,
    PostgreSQLQuery,
    OracleQuery,
    MSSQLQuery,
    SQLLiteQuery,
    ClickHouseQuery,
    VerticaQuery
)
# pypika 提供多種數(shù)據(jù)庫(kù)的適配,我們以 MySQL 為例
# 之前用的是 Query 這個(gè)類,而以上這些類都繼承 Query
# 所以語(yǔ)法和之前是一樣的
from pypika import Table, MySQLQuery, PostgreSQLQuery

t = Table("t")
print(
    MySQLQuery.from_(t).select(t.id, t.age)
)  # SELECT `id`,`age` FROM `t`

print(
    PostgreSQLQuery.from_(t).select(t.id, t.age)
)  # SELECT "id","age" FROM "t"

要操作哪一種數(shù)據(jù)庫(kù),直接選擇對(duì)應(yīng)的 Query 即可。

小結(jié)

以上就是 pypika 的相關(guān)內(nèi)容,總的來(lái)說(shuō)還是很方便的,在面對(duì)一些不復(fù)雜的 SQL 時(shí),使用該模塊會(huì)非常方便。

當(dāng)然 pypika 還支持更多高級(jí)用法,比如窗口函數(shù),有興趣可以查看官網(wǎng)。

https://pypika.readthedocs.io

責(zé)任編輯:武曉燕 來(lái)源: 古明地覺的編程教室
相關(guān)推薦

2010-09-07 16:31:17

SQL語(yǔ)句insert

2024-08-26 00:01:00

前端性能優(yōu)化

2019-10-22 13:34:06

SQL數(shù)據(jù)庫(kù)語(yǔ)句解讀

2022-11-07 08:58:41

搜索數(shù)據(jù)索引

2020-05-25 16:18:33

SpringBoot代碼生成器

2011-03-31 11:40:13

SQL

2021-12-14 07:05:00

SQL語(yǔ)句數(shù)據(jù)庫(kù)

2021-07-08 10:36:09

云計(jì)算數(shù)據(jù)李飛飛

2010-04-13 14:36:17

Oracle性能檢測(cè)

2010-09-07 11:53:00

SQL語(yǔ)句

2017-03-14 14:38:21

數(shù)據(jù)庫(kù)SQL語(yǔ)句集合運(yùn)算

2023-12-21 09:00:00

開發(fā)并發(fā)編程

2021-12-21 09:05:46

命令Linux敲錯(cuò)

2010-04-29 14:06:40

Oracle SQL

2024-04-15 00:08:00

MySQLInnoDB數(shù)據(jù)庫(kù)

2010-07-19 16:54:21

SQL

2010-09-07 10:56:58

SQL語(yǔ)句

2009-09-07 16:25:14

Linq To SQL

2010-10-14 09:32:52

SQL Server

2009-07-16 11:35:57

自動(dòng)生成ibatis改造
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)