PostgreSQL码农集散地

2025第1个好消息

参考文档点击文末阅读原文打开; 推荐《最好的PostgreSQL学习镜像》;

2025,1个好消息

别找Oracle pl/sql与PG plpgsql的存储过程/函数语法转换工具了, 用AI就可以!

好消息是去O更方便了, 坏消息是, 可能一些工作又要和AI抢了, 相关公司估计也要洗牌了!  不过对于拥抱AI的人总体来说是好消息!

我拿菜鸟教程里Oracle pl/sql例子试了一下, AI真的搞定了.

https://www.cainiaoya.com/plsql/plsql-coll.html

万能的AI, 麻烦你把这个oracle pl/sql存储过程改成PostgreSQL plpgsql存储过程.

DECLARE   
   TYPE names_table IS TABLE OF VARCHAR2(10);   
   TYPE grades IS TABLE OF INTEGER;    
   names names_table;   
   marks grades;   
   total integer;   
BEGIN   
   names := names_table('Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz');   
   marks:= grades(98, 97, 78, 87, 92);   
   total := names.count;   
   dbms_output.put_line('Total '|| total || ' Students');   
   FOR i IN 1 .. total LOOP   
      dbms_output.put_line('Student:'||names(i)||', Marks:' || marks(i));   
   end loop;   
END;   
/    

在将 Oracle PL/SQL 存储过程转换为 PostgreSQL PL/pgSQL 时,需要注意以下几个关键点:

  1. 数组和集合类型:在 Oracle 中,使用 TABLE 类型来定义集合(如 names_table 和 grades),而在 PostgreSQL 中没有直接的 TABLE 类型。可以使用 数组(ARRAY)来代替集合。
  2. **DBMS_OUTPUT.PUT_LINE**:在 PostgreSQL 中,可以使用 RAISE NOTICE 来替代 Oracle 的 DBMS_OUTPUT.PUT_LINE。
  3. **count**:在 Oracle 中,集合的 count 方法用来获取元素的个数。PostgreSQL 数组可以使用 array_length 函数来获取数组的长度。

Oracle PL/SQL 示例:

DECLARE   
   TYPE names_table IS TABLE OF VARCHAR2(10);   
   TYPE grades IS TABLE OF INTEGER;    
   names names_table;   
   marks grades;   
   total integer;   
BEGIN   
   names := names_table('Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz');   
   marks := grades(98, 97, 78, 87, 92);   
   total := names.count;   
   dbms_output.put_line('Total ' || total || ' Students');   
   FOR i IN 1 .. total LOOP   
      dbms_output.put_line('Student: ' || names(i) || ', Marks: ' || marks(i));   
   END LOOP;   
END;  
/  

转换为 PostgreSQL PL/pgSQL 示例:

DO $$   
DECLARE  
   names TEXT[] := ARRAY['Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz'];   
   marks INTEGER[] := ARRAY[98, 97, 78, 87, 92];   
   total INTEGER;   
BEGIN  
   -- 获取学生数量  
   total := array_length(names, 1);   

   RAISE NOTICE 'Total % Students', total;  

   -- 循环遍历学生和成绩  
   FOR i IN 1..total LOOP   
      RAISE NOTICE 'Student: %, Marks: %', names[i], marks[i];   
   END LOOP;   
END $$;  

主要变动解释:

  1. 数组类型替换:

  • 在 Oracle 中,names_table 和 grades 使用 TABLE 类型定义了集合。在 PostgreSQL 中,我们使用 数组(TEXT[] 和 INTEGER[])来代替。
  • 数组初始化:

    • 在 Oracle 中,names 和 marks 使用了类型的初始化方法(names_table('Kavita', 'Pritam', ...))。在 PostgreSQL 中,使用 ARRAY[] 来初始化数组。
  • count 替代:

    • 在 Oracle 中,使用 names.count 来获取数组的大小。在 PostgreSQL 中,使用 array_length 函数来获取数组的长度:array_length(names, 1)。1 是指定第一个维度的长度。
  • 输出:

    • 在 Oracle 中,使用 dbms_output.put_line 输出信息,而在 PostgreSQL 中,使用 RAISE NOTICE 来输出信息。RAISE NOTICE 支持格式化输出,因此可以直接使用类似 RAISE NOTICE 'text', var1, var2 的方式。

    执行方法:

    • 在 PostgreSQL 中,如果你希望将这个代码变成一个存储过程,可以使用 CREATE PROCEDURE,而不是 DO $$ 块。使用 DO $$ 块是用于执行匿名代码块。

    如果要创建一个存储过程,可以如下所示:

    CREATE OR REPLACE PROCEDURE student_marks()  
    LANGUAGE plpgsql  
    AS $$  
    DECLARE  
       names TEXT[] := ARRAY['Kavita', 'Pritam', 'Ayan', 'Rishav', 'Aziz'];   
       marks INTEGER[] := ARRAY[98, 97, 78, 87, 92];   
       total INTEGER;   
    BEGIN  
       total := array_length(names, 1);  
       RAISE NOTICE 'Total % Students', total;  

       FOR i IN 1..total LOOP   
          RAISE NOTICE 'Student: %, Marks: %', names[i], marks[i];   
       END LOOP;   
    END;  
    $$;  

    通过 CALL student_marks(); 调用这个存储过程。

    总结:

    • 在 PostgreSQL 中使用数组代替 Oracle 中的 TABLE 类型。
    • 使用 array_length 获取数组长度。
    • 使用 RAISE NOTICE 代替 DBMS_OUTPUT.PUT_LINE 输出调试信息。

    运行结果正确

    postgres=# CALL student_marks();  
    NOTICE:  Total 5 Students  
    NOTICE:  Student: Kavita, Marks: 98  
    NOTICE:  Student: Pritam, Marks: 97  
    NOTICE:  Student: Ayan, Marks: 78  
    NOTICE:  Student: Rishav, Marks: 87  
    NOTICE:  Student: Aziz, Marks: 92  
    CALL  

    -- 和Oracle结果一致:  

    Total 5 Students   
    Student:Kavita, Marks:98   
    Student:Pritam, Marks:97   
    Student:Ayan, Marks:78   
    Student:Rishav, Marks:87   
    Student:Aziz, Marks:92    
    PL/SQL procedure successfully completed.   

    大家可以试试逻辑和语法更加复杂的, 或者试试需要自定义类型, 自定义包的.

    文末彩蛋:国产数据库周边生态

    当然一款数据库要流行起来, 除了自己要强大, 还离不开生态. 用好周边生态工具, 管理水平战胜90%老司机!!! 下面简单介绍一下国产数据库周边生态.

    1、管控软件

    鸣嵩(前阿里云数据库总经理 / 研究员)等大佬们创业创办的云猿生, 核心产品是KubeBlocks. 他们的理念是让管理数据库和搭积木一样简单, 如果你要管理很多套并且种类(OLTP\OLAP\NoSQL\KV\TS\MQ等)很多的数据库产品, 推荐首选.

    • https://github.com/apecloud/kubeblocks

    PG中文社区核心委员唐成老师的公司乘数开源的Clup, 专用管理PostgreSQL和PolarDB的集群管理软件, 如果你要管理很多套数据库, 推荐选择. 并且Clup还提供了企业版、自研的连接池、分布式存储、一体机、备份平台等, 是企业用户推荐之选.

    • https://www.csudata.com/

    若航老司机开源的pigsty, 集成了300多个PG插件的PG集群和PolarDB集群管理软件, 如果你要管理很多套PG或PolarDB数据库, 且对插件有特别多的需求, 推荐选择.

    • https://pigsty.cc/zh/

    2、审计监控诊断优化

    翟总(曾经是我背后的男人)到海信聚好看后研发的 DBdoctor, 采用ebpf技术, 在对数据库几乎没有影响的情况下实时监控数据库和服务器的各项指标, 发现和诊断问题根因非常方便.

    • https://www.dbdoctor.cn/

    天舟老哥的核心产品Bytebase 是位于您和数据库之间的中间件。它是数据库 DevOps 的 GitLab/GitHub,专为开发人员、DBA 和平台工程师打造。

    • https://bytebase.cc/docs/introduction/what-is-bytebase/

    PawSQL, SQL优化和诊断产品.  

    D-Smart, Oracle老前辈白老大出品, 专注企业级市场, 将业界顶级DBA经验的产品化作品, 产品功能包括数据库监控、诊断、优化等.

    • https://www.modb.pro/db/567140

    3、国产数据库IDE

    IDE是开发者的必备工具,例如社区有pgAdmin, 国产IDE则可以看看老程序猿达刚老师的DeskUI:

    • https://www.deskui.com

    4、数据同步&迁移&备份恢复

    NineData, 老领导出去创业做的产品, 产品涵盖了数据同步、迁移、备份、比对、devops、chatDBA等.

    • https://www.ninedata.cloud/home

    DSG, 非常老牌的数据库同步迁移企业级产品, 支持各种数据库的异构和同构迁移, 用他们的话说, 没有dsg搞不定的迁移, 比goldengate还牛.

    • https://www.dsgdata.com/

    公开课

    如果你对PolarDB学习感兴趣可以阅读这个公开课系列:

    除了PolarDB还非常值得关注的几款PG栈国产数据库:

    • HaloDB(基于PG兼容PostgreSQL、Oracle、MySQL. http://www.halodbtech.com/ )、
    • IvorySQL(基于开源PG兼容PG、Oracle. https://www.ivorysql.org/zh-cn/ )、
    • ProtonBase(云原生分布式数仓. https://protonbase.com/ )、
    • 成都文武数据库(https://ww-it.cn)

    参考文档点击阅读原文获得


    感谢关注我的github (https://github.com/digoal/blog) 及视频号:

    Image