PL/Python 語言模組會自動匯入一個名為 plpy
的 Python 模組。此模組中的函式和常量可以在 Python 程式碼中以 plpy.
的形式使用。foo
plpy
模組提供了一些函式來執行資料庫命令。
plpy.execute
(query
[, limit
])
呼叫帶有查詢字串和可選行限制引數的 plpy.execute
會執行該查詢,並將結果返回給結果物件。
如果指定了 limit
並且大於零,則 plpy.execute
最多檢索 limit
行,這很像查詢中包含 LIMIT
子句。省略 limit
或將其指定為零將不會限制行數。
結果物件模擬列表或字典物件。結果物件可以透過行號和列名訪問。例如
rv = plpy.execute("SELECT * FROM my_table", 5)
從 my_table
中返回最多 5 行。如果 my_table
有一個名為 my_column
的列,則可以透過以下方式訪問它:
foo = rv[i]["my_column"]
可以使用內建的 len
函式獲取返回的行數。
結果物件還有以下附加方法:
nrows
()
返回命令處理的行數。請注意,這不一定與返回的行數相同。例如,UPDATE
命令將設定此值,但不會返回任何行(除非使用了 RETURNING
)。
status
()
SPI_execute()
的返回值。
colnames
()
coltypes
()
coltypmods
()
分別返回列名列表、列型別 OID 列表和列的型別特定的型別修飾符列表。
當在不產生結果集的命令(例如,不帶 RETURNING
的 UPDATE
或 DROP TABLE
)的結果物件上呼叫這些方法時,它們會引發異常。但是,在包含零行的結果集上使用這些方法是可以的。
__str__
()
定義了標準的 __str__
方法,以便可以例如使用 plpy.debug(rv)
來除錯查詢執行結果。
結果物件可以被修改。
請注意,呼叫 plpy.execute
將導致整個結果集被讀入記憶體。僅當您確定結果集相對較小時才使用此函式。如果您不想在獲取大型結果時冒著過度使用記憶體的風險,請使用 plpy.cursor
而不是 plpy.execute
。
plpy.prepare
(query
[, argtypes
])
plpy.execute
(plan
[, arguments
[, limit
]])
plpy.prepare
準備查詢的執行計劃。如果查詢中有引數引用,則使用查詢字串和引數型別列表進行呼叫。例如:
plan = plpy.prepare("SELECT last_name FROM my_users WHERE first_name = $1", ["text"])
text
是您將為 $1
傳遞的變數的型別。如果您不想將任何引數傳遞給查詢,則第二個引數是可選的。
準備好語句後,您可以使用 plpy.execute
函式的變體來執行它:
rv = plpy.execute(plan, ["name"], 5)
將計劃作為第一個引數(而不是查詢字串),並將要替換到查詢中的值列表作為第二個引數傳遞。如果查詢不接受任何引數,則第二個引數是可選的。第三個引數是可選的行限制,與之前相同。
或者,您可以呼叫計劃物件上的 execute
方法:
rv = plan.execute(["name"], 5)
查詢引數和結果行欄位在 PostgreSQL 和 Python 資料型別之間進行轉換,如 第 44.2 節中所述。
當您使用 PL/Python 模組準備計劃時,它會自動儲存。閱讀 SPI 文件(第 45 節)以瞭解其含義。為了在函式呼叫之間有效利用這一點,需要使用持久化儲存字典 SD
或 GD
(請參閱 第 44.3 節)。例如:
CREATE FUNCTION usesavedplan() RETURNS trigger AS $$ if "plan" in SD: plan = SD["plan"] else: plan = plpy.prepare("SELECT 1") SD["plan"] = plan # rest of function $$ LANGUAGE plpython3u;
plpy.cursor
(query
)
plpy.cursor
(plan
[, arguments
])
plpy.cursor
函式接受與 plpy.execute
相同的引數(行限制除外),並返回一個遊標物件,該物件允許您分塊處理大型結果集。與 plpy.execute
一樣,可以使用查詢字串或計劃物件以及引數列表,也可以將 cursor
函式作為計劃物件的方法進行呼叫。
遊標物件提供一個 fetch
方法,該方法接受一個整數引數並返回一個結果物件。每次呼叫 fetch
時,返回的物件將包含下一批行,其大小不超過引數值。一旦所有行都已提取完畢,fetch
將開始返回一個空的結果物件。遊標物件還提供一個 迭代器介面,每次生成一行,直到所有行都已提取完畢。以這種方式獲取的資料不會作為結果物件返回,而是作為字典返回,每個字典對應一行結果。
處理大型表資料的兩種方法的示例是:
CREATE FUNCTION count_odd_iterator() RETURNS integer AS $$ odd = 0 for row in plpy.cursor("select num from largetable"): if row['num'] % 2: odd += 1 return odd $$ LANGUAGE plpython3u; CREATE FUNCTION count_odd_fetch(batch_size integer) RETURNS integer AS $$ odd = 0 cursor = plpy.cursor("select num from largetable") while True: rows = cursor.fetch(batch_size) if not rows: break for row in rows: if row['num'] % 2: odd += 1 return odd $$ LANGUAGE plpython3u; CREATE FUNCTION count_odd_prepared() RETURNS integer AS $$ odd = 0 plan = plpy.prepare("select num from largetable where num % $1 <> 0", ["integer"]) rows = list(plpy.cursor(plan, [2])) # or: = list(plan.cursor([2])) return len(rows) $$ LANGUAGE plpython3u;
遊標會自動處理。但如果您想顯式釋放遊標持有的所有資源,請使用 close
方法。一旦關閉,就不能再從遊標中獲取資料了。
請不要將 plpy.cursor
建立的物件與 Python 資料庫 API 規範定義的 DB-API 遊標混淆。它們除了名稱之外沒有任何共同之處。
訪問資料庫的函式可能會遇到錯誤,這些錯誤會導致它們中止並引發異常。 plpy.execute
和 plpy.prepare
都可以引發 plpy.SPIError
的子類例項,該例項預設會終止函式。此錯誤可以像任何其他 Python 異常一樣處理,方法是使用 try/except
構造。例如:
CREATE FUNCTION try_adding_joe() RETURNS text AS $$ try: plpy.execute("INSERT INTO users(username) VALUES ('joe')") except plpy.SPIError: return "something went wrong" else: return "Joe added" $$ LANGUAGE plpython3u;
引發異常的實際類對應於導致錯誤的特定條件。有關可能條件的列表,請參閱 表 A.1。plpy.spiexceptions
模組為每個 PostgreSQL 條件定義一個異常類,其名稱從條件名稱派生。例如,division_by_zero
變為 DivisionByZero
,unique_violation
變為 UniqueViolation
,fdw_error
變為 FdwError
,依此類推。這些異常類都繼承自 SPIError
。這種分離使得處理特定錯誤更加容易,例如:
CREATE FUNCTION insert_fraction(numerator int, denominator int) RETURNS text AS $$ from plpy import spiexceptions try: plan = plpy.prepare("INSERT INTO fractions (frac) VALUES ($1 / $2)", ["int", "int"]) plpy.execute(plan, [numerator, denominator]) except spiexceptions.DivisionByZero: return "denominator cannot equal zero" except spiexceptions.UniqueViolation: return "already have that fraction" except plpy.SPIError as e: return "other error, SQLSTATE %s" % e.sqlstate else: return "fraction inserted" $$ LANGUAGE plpython3u;
請注意,由於 plpy.spiexceptions
模組中的所有異常都繼承自 SPIError
,因此處理它的 except
子句將捕獲任何資料庫訪問錯誤。
作為處理不同錯誤條件的替代方法,您可以捕獲 SPIError
異常,並在 except
塊中透過檢視異常物件的 sqlstate
屬性來確定特定的錯誤條件。此屬性是一個字串值,包含“SQLSTATE”錯誤程式碼。此方法提供了大致相同的功能:
如果您在文件中發現任何不正確的內容、與您對特定功能的體驗不符的內容或需要進一步說明的內容,請使用 此表單報告文件問題。