zoukankan      html  css  js  c++  java
  • PostgreSQL 函数学习

    最近工作中需要同时插入两张表,老大非要让使用存储过程,因为我们使用的是PostgreSQL,所以就去学习了一下这个PostgreSQL 的存储过程。

    存储过程,在PostgreSQL 这个数据库中,被称为PostgreSQL函数,所以你可以把他看成就是我们平常使用的函数,只是定义和调用的时候,语法的不同。



    基本语法:

    GREATE [OR REPLACE] FUNCTION function_name (arguments)
    RETURNS return_datatype AS $variable_name$
    DECLARE
    Declaration;
    [...]
    BEGIN
    <function_body>
    [...]
    RETURN{variable_name|value}
    END;
    LANGUAGE plpgsql;

    参数说明:

    [OR REPLACE]:是可选的,叫上表示允许修改和替换现有函数。
    比如你创建了一个postgreSQL 函数“insert_data”里面的有一些插入数据的功能,然后在不久后你又创建了一个“insert_data” 的PostgreSQL 函数,则后面这个会替换掉前面那个。

    [RETURN]:指定要从函数返回的数据类型,可以是基础,复合或域类型,也可以是引用表列的类型。

    块名解释:

    DECLARE:在此声明在下方可能使用到的变量,需要指定该变量的类型

    BEGIN...END : 被称为函数的主体,就是具体需要执行的代码,一般是数据库的操作语言,如DQL(查询语句),DML(增删改操纵语句)

    LANGUAGE : CREATE FUNCTION命令的语法要求函数体写成一个字符串文本。通常来说,该文本字符串常量使用两个美元符($$)包裹,然后在最后面指明该字符串文本的语言类型,PostgreSQL 函数中一般使用plpgsql

    具体看一个简单的查看students 表中的所有学生的总年龄的例子,注: “--” 在postgreSQL 中代表的是单行注释:

    -- SQL代码块
    CREATE OR REPLACE FUNCTION totalAge() RETURNS integer AS $agecount$ DECLARE agecount integer; BEGIN SELECT COUNT(age) into agecount FROM students; RETURN agecount; END; $agecount$ LANGUAGE plpgsql;

    我是在psycopg2 中操作的,在这里面创建postgreSQL 和 普通的执行SQL语句类似,首先建立连接:

    1 import psycopg2
    2 conn = psycopg2.connect(dsn)
    3 cur = conn.cursor()
    4 SQL = “““...”””             # 这里放入上面的整个函数代码块
    5 cur.execute(SQL)
    6 conn.commit()
    7 conn.close()

    这就是创建的过程,这时候在pgadmin4 中去查看Schemas的public的functions中,就可以找到你刚刚创建的这个PostgreSQL 函数

    调用的过程也很简单,只是把上面的SQL 里面的代码块换成:

    -- SQL 代码块
    SELECT totalAge()

    下面给这个PostgreSQL 函数增加一些参数:

    -- SQL 代码块
    CREATE OR REPLACE FUNCTION columntotal( tablename varchar, columnname varchar, out columncount integer) AS $$ DECLARE ex_sql text; BEGIN ex_sql:
    =’SELECT COUNT(‘||quote_ident(columnname) ||’) FROM ‘ || quote_ident(tablename); execute ex_sql into columcount; END; $$ LANGUAGE plpgsql;

    由上面的例子可以看出来:

    1. 返回值也可以直接以参数的形式出现在postgreSQL 的形参里面的,只是需要在前面加上“out”这个标识,并且注意每个形参后面都需要指定类型。


    2. 在PostgreSQL函数块里赋值的时候不是“=”,而是“:=”。


    3. 当代码块中引用表名或者是字段名的时候,不能直接引用,需要使用PostgreSQL自带的“quote_ident”函数进行转换。


    4. “||”这个符号的作用是作为连接符,可以将变量和字符串进行拼接,这里只说了简单的做法,具体的作用请参考:https://blog.csdn.net/fred_lzy/article/details/53188082。


    5. 每段话以“;”为结尾。

    调用的时候就可以通过传入表名和字段名,来查看他们的总和了,当然,只能针对整数类型的字段,如:id,age,代码块如下:

    -- SQL 代码块
    SELECT columntotal(‘students’, ‘id’)
    -- SQL 代码块 SELECT columntotal(‘teacher’, ‘age’)

    条件判断if 的使用,从参考资料中“存储过程实战2”中取一个例子进行分析,为了统一本文,修改了例子某些变量名称:

    -- SQL代码块
    CREATE OR REPLACE FUNCTION f_insert_table( tablename varchar, fieldname text[], fieldvalue text[], out returnValue text ) AS $$ DECLARE ex_result integer default
    0; ex_sql text; BEGIN ex_sql:='insert into ' ||quote_ident(tablename) ||'(' ||array_to_string(fieldname,',') ||') values(''' ||array_to_string(fieldvalue,''',''') ||''')'; execute ex_sql; GET DIAGNOSTICS ex_result:= ROW_COUNT; if ex_result<>0 then returnValue:='{"SUCCESS":"插入操作'||ex_sql||'成功!"}'; else returnValue:='{"ERROR":"插入操作'||ex_sql||'失败!"}'; end if; END; $$ language plpgsql;

    针对上面例子做下简单的分析

    1. 首先这个PostgreSQL 函数接收三个参数。text[], 代表这个类型接收的是个字符串格式的数组。如‘{1,2,3,4}’,可能是他们规定的,比如我尝试传入‘[1,2,3,4]’,程序就报错提示说 Array value must start with "{" or dimension information.


    2. 从字面意思上可以看出feildname这个数组肯定不止一个字段,那么进行字符串拼接的时候必须要使用自带的array_to_string,将里面的字段转换成字符串。这个函数接受两个参数,第一个参数是个数组,第二个参数是个连接符,比如上面的例子就是将feildname 中的每个元素使用‘,’拼接成一个大的字符串,再或者array_to_string(feildname,‘/’),就是将它中的每个元素使用‘/’拼接成一个大的字符串。


    3. if 判断的时候,条件和执行语句中间需要加“then”关键字,而判断结束了需要加上‘end if’并且以分号‘;’结尾


    函数调用:

    -- SQL 代码块
    SELECT f_insert_table('func_test','{name,id,time}','{qwe,123,2019-04-04}')


    for 循环的使用-整数(类似于Python 中的range(int)),参考:https://blog.csdn.net/u011768325/article/details/50502490

    -- SQL 代码块
    CREATE OR REPLACE FUNCTION test_for( a1 integer[], a2 bigint) returns void AS $$ DECLARE ii integer; num integer; BEGIN ii:
    =1; num = 1; FOR ii IN 1..a2 LOOP UPDATE student SET id=a1[num] WHERE cd_id = ii; num = num +1; if (num>6) then num = 1; end if; end loop; END; $$ LANGUAGE plpgsql;

    针对上面的例子,简单分析:

    如果需要循环到一个整数,可以自己选择起始数值,如
    从1开始到形参a2 FOR i IN 1..a2 LOOP
    从100开始到形参a2 FOR i IN 100..a2 LOOP
    当循环结束的时候要加上“end loop;”(注意不要少了分号“;”)


    函数的调用:

    -- SQL 代码块
    SELECT test_for(array[1,4,5,6,7,8],6742)

    循环一个可迭代对象,即对数组的遍历,分为三种情况,目前我还在学习中,
    请参考:https://blog.csdn.net/yueliangdao0608/article/details/18735703

    另外,经常在PostgreSQL函数 见到的$1,$2,其实就是位置参数,分别带别第一个和第二个参数
    比较常用的函数定义参考:
    https://blog.csdn.net/paulxin2008/article/details/41980145
    https://blog.csdn.net/Wang_Dong_Liang/article/details/81334278


    扩展:
    1.如果不希望函数有返回值...RETURNS VOID (this defines a function with no return value) AS $$...
    2.在函数代码块中,有两种注释,“--” 双减号为单行注释,“/* ...*/”为多行注释 。
    3.在函数语句里,‘continue’和 ‘exit’相当于Python 中的‘continue’ 和‘break’。
    4.请注意, 定义存储过程内使用的变量, 需要定义在 BEGIN 之前, 需要加 DECLARE 关键字。多个变量之间用分号分隔
    5.每循环一次,循环变量自动加1;使用关键字REVERSE,循环变量自动减1。跟在IN REVERSE 后面的数字必须是从大到小的顺序,而且必须是整数,不能是变量或表达式。可以使用EXIT 退出循环。
    FOR i IN 1..10 LOOP
    -- i will take on the values 1,2,3,4,5,6,7,8,9,10 within the loopEND LOOP;
    FOR i IN REVERSE 10..1 LOOP
    -- i will take on the values 10,9,8,7,6,5,4,3,2,1 within the loopEND LOOP;
    FOR i IN REVERSE 10..1 BY 2 LOOP
    -- i will take on the values 10,8,6,4,2 within the loopEND LOOP;
    6. 删除函数的时候, 需要传递完整的参数列表, 仅仅指定一个 函数的名称, 是无法删除的。

     参考资料:

    官方文档:https://www.postgresql.org/docs/10/plpgsql-declarations.html
    简单易学:https://www.yiibai.com/postgresql/postgresql-functions.html
    存储过程实战1:https://www.cnblogs.com/ssqhan/p/7289931.html
    存储过程实战2:https://www.cnblogs.com/ssqhan/p/7399900.html

  • 相关阅读:
    Sql Server常见错误
    sql server复制需要有实际的服务器名称才能连接到服务器
    学习WCF必备网址
    利用Httphandler、UserControl 输出HTML片段
    SQL点滴—性能分析之执行计划
    我的WCF开发框架简化版及基于NET.TCP传输方式的实现
    数据库优化建议
    实现jQuery扩展总结
    【模板】zkw线段树
    洛谷 P1960 列队
  • 原文地址:https://www.cnblogs.com/yungiu/p/10704008.html
Copyright © 2011-2022 走看看