PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Tổng quan về Lập trình phía máy chủ trong PostgreSQL

Có rất nhiều cách để bạn có thể yêu cầu máy chủ Postgres chạy mã được xác định trước. Dưới đây là danh sách đầy đủ, với các ví dụ, về các cách mà bạn có thể để máy chủ Postgres lưu trữ logic được xác định trước, mà bạn có thể sử dụng từ ứng dụng của mình.

Hàm SQL

Postgres cho phép bạn tạo “các hàm do người dùng xác định”, trong đó nội dung hàm có thể được viết bằng ngôn ngữ được hỗ trợ. “Hàm SQL” là các hàm do người dùng định nghĩa được viết bằng SQL thông thường, là cách đơn giản nhất để đóng gói các truy vấn phức tạp và chuỗi các câu lệnh SQL.

Dưới đây là một số ví dụ:

-- update item price and record the change
CREATE FUNCTION update_price(item text, newprice numeric) RETURNS void AS $$
    UPDATE items SET price=$2 WHERE name=$1;
    INSERT INTO audit (event, new_price, at, item)
      VALUES ('price changed', $2, now(), $1);
$$ LANGUAGE SQL;

-- a function from uuid-osp
CREATE FUNCTION uuid_timestamp_bits(uuid) RETURNS varbit AS
$$ SELECT ('x' || substr($1::text, 15, 4) || substr($1::text, 10, 4) ||
           substr($1::text, 1, 8) || substr($1::text, 20, 4))::bit(80)
          & x'0FFFFFFFFFFFFFFF3FFF' $$
LANGUAGE SQL STRICT IMMUTABLE;

Các hàm SQL có thể chấp nhận và trả về các kiểu cơ sở, kiểu kết hợp và hàng. Chúng cũng hỗ trợ số lượng biến đối số, giá trị mặc định cho đối số và đối số đa hình. Chúng thậm chí có thể trả về nhiều hàng, bắt chước một CHỌN từ một bảng. Họ cũng không cần thiết phải trả lại bất cứ thứ gì.

Tuy nhiên, thân hàm chỉ có thể chứa các câu lệnh SQL. Điều này có nghĩa là không có câu lệnh điều khiển luồng (if, while,…), biến và những thứ tương tự.

Lệnh CREATE FUNCTION được sử dụng để tạo hàm. Như thường lệ, bạn có thể ALTER và DROPthem.

Đây là một nơi tuyệt vời để bắt đầu đào sâu hơn:https://www.postgresql.org/docs/current/xfunc-sql.html

C Hàm

Mặc dù các hàm SQL là dễ viết nhất và ít mạnh mẽ nhất, nhưng xét về mặt phổ biến, các hàm có thể được viết bằng C và có thể làm được khá nhiều thứ. Các hàm như vậy cần được mã hóa bằng C và được xây dựng dưới dạng thư viện dùng chung để Postgres có thể tải động.

Bạn cần cho Postgres biết nơi tải thư viện được chia sẻ, tên và chữ ký của hàm:

CREATE FUNCTION sum(integer, integer) RETURNS integer
    AS 'myfuncs', 'sum'
    LANGUAGE C STRICT;

Điều này nói rằng thư viện được chia sẻ myfuncs.so , hiện diện trong một đường dẫn tìm kiếm được xác định trước, chứa các điểm nhập có thể được gọi bởi Postgres, với một trong các điểm nhập là 'sum' có thể được gọi như một hàm.

Mã thực tế trong C sẽ quá dài để đưa vào đây, nhưng bạn có thể đọc toàn bộ mã trong tài liệu. Được kết hợp với Giao diện lập trình máy chủ (SPI), bạn có thể thực hiện hầu hết mọi thao tác mà bạn có thể làm theo bất kỳ cách nào khác.

Ví dụ:với các hàm C được xác định ở đây, bạn có thể thực hiện các yêu cầu HTTP:

SELECT status, content_type FROM http_get('https://postgresql.org/');

Cũng có thể viết các thư viện được chia sẻ như vậy bằng các ngôn ngữ khác nhưC ++ hoặc Go, có thể xây dựng các thư viện được chia sẻ với các liên kết “C”.

PL / pgSQL Functions

Ngoài SQL và C, bạn có thể viết các hàm bằng ngôn ngữ thủ tục . Các ngôn ngữ bốn ngôn ngữ được hỗ trợ bởi PostgreSQL cốt lõi - pgSQL, Python, Perl và Tcl. Hỗ trợ cho bất kỳ ngôn ngữ thủ tục nào bản thân nó đến từ thư viện chia sẻ C và hoạt động giống như mod_perl hoặc mod_python từ thời Apache.

pgSQL là ngôn ngữ giống SQL chuẩn, được sử dụng nhiều nhất, trong đó các hàm được lưu trữ cho PostgreSQL được viết. Nó có sẵn theo mặc định, nhờ nó được cài đặt trong template1 .

PL / pgSQL là một ngôn ngữ chính thức với các biến, biểu thức và câu lệnh điều khiển; và bao gồm các tính năng như con trỏ để làm việc với dữ liệu SQL trong ngôn ngữ. Nó được ghi lại rất nhiều ở đây.

Đây là một ví dụ:

CREATE FUNCTION repeat(times integer, s text)
    RETURNS text
    AS $$
DECLARE
    result text;
BEGIN
    result := '';
    FOR i IN 1..times LOOP
        result := result || s;
    END LOOP;
    RETURN result;
END;
$$
LANGUAGE plpgsql
IMMUTABLE;

-- psql> SELECT repeat(10, '*');
--    repeat
-- ------------
--  **********
-- (1 row)

Các ngôn ngữ thủ tục cốt lõi khác

Các ngôn ngữ thủ tục khác - Python, Perl, Tcl - cho phép các nhà phát triển sử dụng ngôn ngữ mà họ đã cảm thấy thoải mái. Ví dụ, trong Debian, bạn có thể phải làm:

sudo apt install postgresql-plpython-11

để cài đặt hỗ trợ PL / Python cho PostgreSQL 11.

Dù bạn đang sử dụng ngôn ngữ nào để viết một hàm, người gọi không nhận thấy bất kỳ sự khác biệt nào trong cách sử dụng hàm đó.

Python

Phần mở rộng PL / Python hỗ trợ viết các hàm bằng Python 2 và Python 3. Để cài đặt nó, hãy thực hiện:

CREATE EXTENSION plpythonu;

Đây là một hàm được viết bằng PL / Python:

CREATE FUNCTION pymax (a integer, b integer)
  RETURNS integer
AS $$
  if a > b:
    return a
  return b
$$ LANGUAGE plpythonu;

Môi trường Python mà thân hàm chạy trong có một mô-đun được gọi là plpy tự động nhập vào nó. Mô-đun này chứa các phương thức cho phép bạn cung cấp và chạy các truy vấn, xử lý các giao dịch và làm việc với con trỏ.

Bạn có thể tìm thêm thông tin trong chương 46 của tài liệu Postgres.

Perl

Vâng, vâng, Perl. Các quy trình phát triển, kiểm tra và xây dựng Postgres sử dụng Perlextensently, và nó cũng được hỗ trợ như một ngôn ngữ thủ tục. Để bắt đầu sử dụng nó, hãy đảm bảo rằng mọi gói nhị phân có liên quan cho bản phân phối của bạn đã được cài đặt (ví dụ “postgresql-plperl-nn” cho Debian) và cài đặt phần mở rộng “plperl”.

Đây là một hàm được viết bằng PL / Perl:

CREATE FUNCTION perl_max (integer, integer) RETURNS integer AS $$
    my ($x, $y) = @_;
    if (not defined $x) {
        return undef if not defined $y;
        return $y;
    }
    return $x if not defined $y;
    return $x if $x > $y;
    return $y;
$$ LANGUAGE plperl;

Tài liệu đầy đủ tại đây.

Tcl

Tcl là một PL khác được hỗ trợ bởi Postgres cốt lõi. Đây là một ví dụ:

CREATE FUNCTION tcl_max(integer, integer) RETURNS integer AS $$
    if {[argisnull 1]} {
        if {[argisnull 2]} { return_null }
        return $2
    }
    if {[argisnull 2]} { return $1 }
    if {$1 > $2} {return $1}
    return $2
$$ LANGUAGE pltcl;

Để biết thêm thông tin, hãy xem tài liệu tại đây.

Ngôn ngữ theo thủ tục không cốt lõi

Ngoài các ngôn ngữ này, còn có các dự án mã nguồn mở phát triển và duy trì sự hỗ trợ cho các ngôn ngữ khác như Java, Lua, R, v.v.

Có một danh sách ở đây:https://www.postgresql.org/docs/current/external-pl.html

Hàm tổng hợp

Các hàm tổng hợp hoạt động trên một tập hợp các giá trị và trả về một kết quả duy nhất. có thể:

SELECT stddev_pop(grade) FROM students;

Bạn có thể xác định các hàm tổng hợp của riêng mình hoạt động theo kiểu tương tự. Tổng hợp do người dùng xác định được tập hợp từ một vài hàm độc lập riêng lẻ hoạt động ở trạng thái bên trong (ví dụ:trạng thái bên trong của một tập hợp tính trung bình có thể là các biến "tổng" và "đếm").

Đây là tổng hợp do người dùng xác định sẽ tính giá trị trung bình của một tập hợp các giá trị:

-- from https://wiki.postgresql.org/wiki/Aggregate_Median
CREATE OR REPLACE FUNCTION _final_median(NUMERIC[])
   RETURNS NUMERIC AS
$$
   SELECT AVG(val)
   FROM (
     SELECT val
     FROM unnest($1) val
     ORDER BY 1
     LIMIT  2 - MOD(array_upper($1, 1), 2)
     OFFSET CEIL(array_upper($1, 1) / 2.0) - 1
   ) sub;
$$
LANGUAGE 'sql' IMMUTABLE;
 
CREATE AGGREGATE median(NUMERIC) (
  SFUNC=array_append,
  STYPE=NUMERIC[],
  FINALFUNC=_final_median,
  INITCOND='{}'
);

có thể được gọi là:

SELECT median(grade) FROM students;

Để biết thêm thông tin, hãy xem tài liệu về tổng hợp và câu lệnh TẠO TỔNG HỢP.

Các loại do người dùng xác định

Các thư viện chia sẻ được viết bằng C mà chúng ta đã thấy trước đó không chỉ có thể định nghĩa các hàm mà còn cả các kiểu dữ liệu. Những kiểu do người dùng xác định này có thể được sử dụng như kiểu dữ liệu cho các cột giống như kiểu dựng sẵn. Bạn có thể xác định các hàm để hoạt động với các giá trị của kiểu do người dùng xác định.

Cần một chút mã để xác định một kiểu mới. Xem tài liệu ở đây sẽ hướng dẫn bạn cách tạo một kiểu mới để biểu diễn các số phức. Nguồn ThePostgres cũng chứa mã hướng dẫn cho việc này.

Operator

Các toán tử làm cho các hàm dễ sử dụng hơn (ví dụ:viết 1 + 2 thay vì sum(1, 2) ), và bạn có thể xác định toán tử cho các kiểu do người dùng xác định bằng cách sử dụng câu lệnh CREATE OPERATORATOR.

Đây là một ví dụ để tạo một + toán tử ánh xạ tới hàm complex_add điều đó thêm hai complex số:

CREATE OPERATOR + (
    leftarg = complex,
    rightarg = complex,
    function = complex_add,
    commutator = +
);

Thông tin thêm tại đây và tại đây.

Lớp toán tử và họ nhà điều hành

Các lớp toán tử cho phép kiểu dữ liệu của bạn hoạt động với các phương thức B-Tree và otherindexing tích hợp sẵn. Ví dụ:nếu bạn muốn tạo chỉ mục B-Tree trên loại cột “phức hợp”, bạn sẽ cần cho Postgres biết cách so sánh hai giá trị của loại này để xác định xem một giá trị nhỏ hơn, bằng hay lớn hơn giá trị kia.

Sẽ rất tốt cho các kiểu phức hợp được so sánh với số nguyên hoặc giá trị dấu phẩy động, đây là nơi xuất hiện của các họ toán tử.

Bạn có thể đọc tất cả về các lớp và họ toán tử tại đây.

Trình kích hoạt

Kích hoạt là một cơ chế mạnh mẽ để tạo ra các tác dụng phụ cho hoạt động bình thường, mặc dù chúng có thể nguy hiểm nếu lạm dụng hoặc lạm dụng. Về cơ bản, trình kích hoạt kết nối các sự kiện với các chức năng. Hàm được tham chiếu đến có thể được gọi:

  • trước hoặc sau khi chèn / cập nhật / xóa một hàng của bảng
  • trên phần cắt ngắn của một bảng
  • thay vì chèn / cập nhật / xóa một hàng chế độ xem

Hàm có thể được gọi cho mỗi hàng bị ảnh hưởng bởi một câu lệnh hoặc một lần biểu tượng. Và thậm chí còn có nhiều thứ khác, chẳng hạn như phân tầng các trình kích hoạt, tất cả đều được giải thích ở đây.

Các hàm kích hoạt có thể được viết bằng C hoặc trong bất kỳ hàm PL nào, nhưng không được viết bằng inSQL. Dưới đây là một ví dụ để chèn một hàng vào một kiểm toán bảng, đối với mọi cập nhật được thực hiện theo giá của một mặt hàng .

-- first create the function
CREATE FUNCTION log_update() RETURNS TRIGGER AS $$
    INSERT INTO audit (event, new_price, at, item)
      VALUES ('price changed', NEW.price, now(), OLD.item);
$$
LANGUAGE plpgsql;

-- then create the trigger
CREATE TRIGGER audit_price_changes
    AFTER UPDATE ON items
    FOR EACH ROW
    WHEN (OLD.price IS DISTINCT FROM NEW.price)
    EXECUTE FUNCTION log_update();

Đọc tất cả về trình kích hoạt tại đây, cùng với tài liệu TẠO TRIGGERdocumentation.

Trình kích hoạt Sự kiện

Trong khi trình kích hoạt phản hồi các sự kiện DML trên một bảng, trình kích hoạt sự kiện có thể phản hồi các sự kiện DDL trên một cơ sở dữ liệu cụ thể. Sự kiện bao gồm tạo, thay đổi, thả nhiều đối tượng, như bảng, chỉ mục, lược đồ, dạng xem, hàm, kiểu, toán tử, v.v.

Dưới đây là một trình kích hoạt sự kiện ngăn chặn việc rơi các đối tượng khỏi ‘Audit’schema:

-- create function first
CREATE FUNCTION nodrop() RETURNS event_trigger LANGUAGE plpgsql AS $$
BEGIN
    IF EXISTS(
      SELECT 1
      FROM pg_event_trigger_dropped_objects() AS T
      WHERE T.schema_name = 'audit')
    THEN
      RAISE EXCEPTION 'not allowed to drop objects in audit schema';
    END IF;
END $$;

-- create event trigger
CREATE EVENT TRIGGER trigger_nodrop
    ON sql_drop
    EXECUTE FUNCTION nodrop();

Thông tin thêm có thể được tìm thấy tại đây và trong tài liệu TRIGGER SỰ KIỆN CREATE.

Quy tắc

PostgreSQL đi kèm với một tính năng cho phép bạn viết lại các truy vấn trước khi nó đến với trình lập kế hoạch truy vấn. Thao tác này hơi giống với configNginx hoặc Apache để viết lại URL đến trước khi xử lý.

Dưới đây là hai ví dụ ảnh hưởng đến các câu lệnh INSERT trên một bảng và làm cho chúng trở thành một thứ gì đó khác:

-- make inserts into "items" table a no-op
CREATE RULE rule1 AS ON INSERT TO items DO INSTEAD NOTHING;

-- make inserts go elsewhere
CREATE RULE rule2 AS ON INSERT TO items DO INSTEAD
    INSERT INTO items_pending_review VALUES (NEW.name, NEW.price);

Chương này từ tài liệu có thêm thông tin về các quy tắc.

Các thủ tục được lưu trữ

Bắt đầu với Postgres 11, có thể tạo các thủ tục được lưu trữ So sánh với các hàm được lưu trữ, chỉ có một điều bổ sung mà các thủ tục có thể làm - kiểm soát giao dịch.

Đây là một ví dụ:

CREATE PROCEDURE check_commit(v integer)
LANGUAGE plpgsql AS $$
BEGIN
    IF v % 2 = 0 THEN
        COMMIT;
    ELSE
        ROLLBACK;
    END IF;
END $$;

-- call it
CALL check_commit(10);

Xem tại đây và tại đây để biết thêm thông tin.

Những điều kỳ lạ khác

Trình gói dữ liệu nước ngoài

Trình gói dữ liệu nước ngoài (FDWs) cho phép bạn nói chuyện với các nguồn dữ liệu khác, như máy chủ khácPostgres, MySQL, Oracle, Cassandra và hơn thế nữa. Tất cả logic để truy cập máy chủ nước ngoài được viết bằng C, như một thư viện được chia sẻ.

Thậm chí còn có một cửa hàng chuyên mục có tên là cstore_fdwbased trên FDW.

Bạn có thể tìm thấy danh sách triển khai FDW trong Postgres Wiki và tài liệu khác tại đây.

Phương thức Truy cập Chỉ mục

PostgreSQL đi kèm với các loại chỉ mục như B-Tree, hash, GIN và hơn thế nữa. Có thể viết kiểu chỉ mục của riêng bạn tương tự như kiểu này, dưới dạng thư viện chia sẻ C. Thêm chi tiết tại đây.

Phương thức Truy cập Bảng

Với PostgreSQL 12 sắp ra mắt, bạn có thể tạo cấu trúc lưu trữ dữ liệu của riêng mình. Bằng cách triển khai giao diện được mô tả ở đây, bạn có thể lưu trữ dữ liệu tối đa trên đĩa theo cách bạn chọn.

Các plugin sao chép hợp lý

Trong PostgreSQL, sao chép hợp lý được thực hiện bằng cách “giải mã” nội dung của nhật ký ghi trước (WAL) thành một định dạng tùy ý (như văn bản SQL hoặc json) và được xuất bản cho người đăng ký qua các vị trí sao chép. Quá trình giải mã này được thực hiện thông qua plugin đầu ra giải mã logic , có thể được triển khai dưới dạng thư viện chia sẻ C như được mô tả ở đây. Thư viện chia sẻ “test_decoding” là một trong những plugin như vậy và bạn có thể xây dựng theo ý mình.

Trình xử lý Ngôn ngữ Thủ tục

Bạn cũng có thể thêm hỗ trợ cho ngôn ngữ lập trình yêu thích của mình dưới dạng Postgres PL bằng cách tạo trình xử lý - một lần nữa dưới dạng thư viện chia sẻ C. Bắt đầu tại đây để tạo PL / Go hoặc PL / Rust!

Tiện ích mở rộng

Các tiện ích mở rộng là cách quản lý gói của Postgres. Giả sử bạn có chức năng C sẽ làm được điều gì đó hữu ích và một vài câu lệnh SQL tạo nên câu lệnh “TẠO CHỨC NĂNG” cần thiết để thiết lập nó. Bạn có thể nhóm các “tiện ích mở rộng” asan này mà Postgres có thể cài đặt (và gỡ cài đặt) trong một bước duy nhất (bằng cách gọi “TẠO MỞ RỘNG”). Khi bạn đưa ra phiên bản mới, bạn cũng có thể bao gồm các bước nâng cấp trong tiện ích mở rộng.

Mặc dù không phải lập trình phía máy chủ cho mỗi lần lập trình, nhưng tiện ích mở rộng là cách chuẩn và rất hiệu quả để đóng gói và phân phối mã phía máy chủ của bạn.

Có thể tìm thấy thêm thông tin về tiện ích mở rộng tại đây và tại đây.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Lỗi postgres khi chèn - LỖI:chuỗi byte không hợp lệ để mã hóa UTF8:0x00

  2. Tự động làm mới chế độ xem cụ thể hóa bằng cách sử dụng quy tắc hoặc thông báo

  3. Cột bảng tăng dần tự động

  4. Cách tạo bảng Chỉ khi nó không tồn tại trong PostgreSQL

  5. Tại sao chúng ta cần các nhà môi giới tin nhắn như RabbitMQ trên cơ sở dữ liệu như PostgreSQL?