首頁 > 後端開發 > Python教學 > 在 PostgreSQL 中建立自訂函數

在 PostgreSQL 中建立自訂函數

PHPz
發布: 2024-07-26 10:23:51
原創
720 人瀏覽過

Creating Custom Functions In PostgreSQL

在 PostgreSQL 中,可以建立自訂函數來解決複雜問題。

這些可以使用預設的 PL/pgSQL 腳本語言編寫,也可以使用其他腳本語言編寫。

Python、Perl、Tcl 和 R 是支援的一些腳本語言。

雖然 PL/pgSQL 隨任何 Postgres 安裝一起提供,但要使用其他語言需要進行一些設定。

安裝擴充

在使用擴充功能之前,需要安裝擴充包。

在 Ubuntu 上你將運行:

Perl

sudo apt-get -y install postgresql-plperl-14
登入後複製

軟體包名稱「postgresql-plperl-14」特定於 PostgreSQL 版本 14。如果您使用的是不同版本的 PostgreSQL,則需要變更軟體包名稱中的版本號碼以符合您安裝的 PostgreSQL 版本。

Python 3

sudo apt-get install postgresql-plpython3-14
登入後複製

啟動擴充

要在 PostgreSQL 中啟動擴展,必須使用 CREATE EXTENSION 語句定義擴展。

Perl

CREATE EXTENSION plperl;
登入後複製

Python

CREATE EXTENSION plpython3;
登入後複製

你好世界範例

建立擴充後,可以使用該擴充功能建立自訂函數。

Perl

CREATE OR REPLACE FUNCTION hello(name text) 
RETURNS text AS $$
    my ($name) = @_;
    return "Hello, $name!";
$$ LANGUAGE plperl;
登入後複製

Python

CREATE OR REPLACE FUNCTION hello(name text)
RETURNS text AS $$
    return "Hello, " + name + "!"
$$ LANGUAGE plpython3;
登入後複製

逐行分解

CREATE OR REPLACE FUNCTION hello(name text)
登入後複製

這一行是在 Postgres 中建立函數的方式。透過使用 CREATE 或 REPLACE,它將用新函數覆寫任何已定義的名為 hello 的函數。

使用 CREATE FUNCTION hello(name text) 將阻止函數覆寫現有函數,如果函數已存在,則會發生錯誤。


RETURNS text AS $$
登入後複製

這定義了 Postgres 將傳回什麼資料類型,重要的是指定的資料類型是 Postgres 識別的類型。如果已經定義了自訂資料類型,則可以指定自訂資料類型。

$$ 是一個分隔符,用來標記程式碼區塊的開始和結束。在這一行中,它標記了程式碼區塊的開始。

開始和結束 $$ 之間的所有程式碼將由 Postgres 執行


$$ LANGUAGE plperl;
登入後複製

$$ 表示腳本的結尾,並告訴 Postgres 腳本應該解析為哪種語言。

使用功能

函數可以像任何內建 Postgres 函數一樣使用

SELECT hello('world');
登入後複製

這將傳回一個值為 Hello world!

的列

函數可以是更複雜查詢的一部分:

SELECT id, title, hello('world') greeting FROM table;
登入後複製

更複雜的例子

這是一個範例函數,它接受來自欄位的文字並傳回字數。

CREATE OR REPLACE FUNCTION word_count(paragraph text)
RETURNS json AS $$
use strict;
use warnings;

my ($text) = @_;

my @words = $text =~ /\w+/g;
my $word_count = scalar @words;

my $result = '{' .
    '"word_count":' . $word_count .
'}';
return $result;
$$ LANGUAGE plperl;
登入後複製

這將傳回帶有字數統計的 JSON 格式結果。


我們可以為該函數添加更詳細的統計資料。

CREATE OR REPLACE FUNCTION word_count(paragraph text)
RETURNS json AS $$
use strict;
use warnings;

my ($text) = @_;

my @words = $text =~ /\w+/g;

my $word_count = scalar @words;

my $sentence_count = ( $text =~ tr/!?./!?./ ) || 0;

my $average_words_per_sentence =
  $sentence_count > 0 ? $word_count / $sentence_count : 0;

my $result = '{' .
    '"word_count":' . $word_count . ',' .
    '"sentence_count":' . $sentence_count . ',' .
    '"average_words_per_sentence":"' . sprintf("%.2f", $average_words_per_sentence) . '"' .
'}';

return $result;
$$ LANGUAGE plperl SECURITY DEFINER;

登入後複製

現在當我們在查詢中使用它時

SELECT word_count(text_field) word_count FROM table

登入後複製

它將回傳 JSON

{"word_count":116,"sentence_count":15,"average_words_per_sentence":"7.73"}
登入後複製

安全考慮

使用自訂函數或外部腳本語言時,需要考慮其他安全注意事項。在可用性和安全性之間取得適當的平衡可能是一種兼顧的行為。

安全定義者與安全性呼叫者

在上一個函數中,建立函數語句中新增了 SECURITY DEFINER 選項。

從安全角度考慮您希望函數如何運作非常重要。

預設行為是使用 SECURITY INVOKER。這將以運行該函數的使用者的權限運行該函數。

SECURITY DEFINER 提供了對授予函數的權限的更多控制。使用此模式,該函數將以建立該函數的使用者的權限運行。

這可能是好事,也可能是壞事,如果一個函數是由權限有限的使用者建立的,那麼對資料庫造成的損害就很小。

如果函數是由具有高存取權限的使用者建立的,則該函數將以相同的權限運行。根據函數的類型,這可能允許使用者以比授予的更多開放權限運行該函數。

有時這很有用,例如,如果使用者沒有表的讀取權限,但在函數內需要讀取,則使用 SECURITY DEFINER 可以允許函數運行所需的讀取權限。


受信任且不受信任的擴展

建立上面的擴充功能時,使用了 plperl 和 plpython3。在大多數情況下,這些是正確使用的擴充。

這些擴充功能對伺服器檔案系統和系統呼叫的存取受到限制。

擴充功能也可以使用 u (plpython3u, plperlu)

來建立

這些是不受信任的擴展,允許對伺服器檔案系統進行更多存取。

在某些情況下可能需要這樣做,例如,如果您想使用 Perl 模組、Python 函式庫或使用系統呼叫。

在上面的範例中,JSON 輸出產生為字串,如果需要,可以使用 perl JSON 模組將資料編碼為 JSON。為此,需要使用不受信任的擴充功能來存取 JSON 模組。

建議不要使用不受信任的擴展,但如有必要,請謹慎使用並了解潛在風險。

如果正在使用 Perl,當使用不受信任的擴充時,Perl 將在污點模式下運作。

最後的想法

能夠利用 Perls 高階文字處理和記憶體管理,或是 PostgreSQL 中的 Python 資料分析函式庫可以成為一個非常強大的工具。

將複雜的任務交給更適合處理任務的工具可以減少資料庫的開銷。

一如既往,在使用自訂函數和外部腳本語言時,請採取預防措施以確保安全使用。

以上是在 PostgreSQL 中建立自訂函數的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板