PostgreSQL--PL/pgSQL基本语句

http://www.wohedb.com/db_html_do ... ql_4_statements.htm
www.wohedb.com  中文数据库管理系统

第四章 基本语句
   
本章介绍PL/pgSQL的基本语句。



4.1 赋值语句
   PL/pgSQL的赋值语句的格式如下:


   variable := expression;

   可以对一个变量赋值,也可以对数据行/记录类型的变量的某个域赋值。如果表达式结果的数据类型与变量的数据类型不匹配或者它们的基本类型一样但精度不同(例如,char(5)和char(3)),PL/pgSQL解释器会自动进行类型转换(使用表达式结果的数据类型的输出函数和变量的数据类型的输入函数)。如果无法进行自动类型转换,系统会报错。


   例如:

   tax := subtotal * 0.06;
   my_record.user_id := 20;
4.2 执行不返回任何数据行的SQL命令
    可以PL/pgSQL函数中直接执行不返回任何数据行的SQL命令,例如,不带RETURNING子句的INSERT命令。这些SQL命令可以引用PL/pgSQL函数的变量,在实际执行它们时,会将变量的值传给这些SQL命令。例如:



DECLARE
    key TEXT;
    delta INTEGER;
BEGIN
    ...
    UPDATE mytab SET val = val + delta WHERE id = key;





警告

不要让PL/pgSQL函数的变量与该函数中执行的SQL命令引用的表、表中的列或函数同名。




    有时可能希望对一个表达式求值或者执行一个SELECT查询,但是丢弃表达式的值或查询结果。例如,调用一个有副作用的函数但不需要函数的返回值。PL/pgSQL提供了PERFORM语句来达到这个目的:

    PERFORM query;


    query的语法与SQL SELECT命令相同,但要去掉SELECT关键字。例如:

    PERFORM create_mv('cs_session_page_requests_mv', my_query);

    这条语句将会执行命令 SELECT  create_mv('cs_session_page_requests_mv', my_query)。PL/pgSQL同时提供了一个特殊的变量FOUND,如果PERFORM执行的查询返回了数据行,它的值为true,如果PERFORM执行的查询没有返回任何数据行,它的值为false(参考第4.5节)。



4.3 执行返回单个数据行的查询
    如果一条SQL命令只返回一个数据行,可以把这个数据行赋给一个记录类型的变量、一个数据行类型的变量或多个标量变量。可以使用INTO子句将查询结果赋给一个变量。例如:



SELECT select_expressions INTO [STRICT] target FROM ...;
INSERT ... RETURNING expressions INTO [STRICT] target;
UPDATE ... RETURNING expressions INTO [STRICT] target;
DELETE ... RETURNING expressions INTO [STRICT] target;


    target可以是一个记录类型的变量、一个数据行类型的变量或多个简单变量(包括记录类型的变量的域、数据行类型的变量的域)的列表,不同的变量用逗号分开。

SQL命令可以是SELECT、带RETURNING 子句的INSERT/UPDATE/DELETE和其它返回数据行的SQL命令(如EXPLAIN)。

    提示: 如果想在PL/pgSQL 函数里以一个查询结果为基础建表,应该用CREATE TABLE ... AS SELECT命令,不要用 SELECT INTO命令。     

    如果target是数据行变量或简单变量的列表,查询结果的列的数据类型必须与target的数据类型完全相同,否则系统会报错。如果target是记录类型的变量,它可以接受任何类型的查询结果。



    INTO子句可以出现在SQL命令的任何地方。但对于SELECT命令,它最好在select_expressions的后面,对于其它命令,最好在命令的末尾。这条规则并未强制执行,在以后的版本中可能会强制执行。



    如果没有使用STRICT选项,将把查询返回的第一个数据行赋给target,如果查询没有返回任何数据行,将空值赋给target。如果查询没有使用ORDER BY子句,则第一个数据行将是不确定的。第一个数据行后面的数据行将被丢弃。可以检查变量FOUND(参考第4.5节)来确定查询是否返回了数据行。例如:



SELECT * INTO myrec FROM emp WHERE empname = myname;
IF NOT FOUND THEN
    RAISE EXCEPTION 'employee % not found', myname;
END IF;


    如果使用了STRICT 选项,查询必须而且只能返回一个数据行,否则系统会报错,错误可能是NO_DATA_FOUND (没有数据行)或TOO_MANY_ROWS (超过一个数据行)。可以用一个异常处理块来捕获这个错误,例如:



BEGIN
    SELECT * INTO STRICT myrec FROM emp WHERE empname = myname;
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            RAISE EXCEPTION 'employee % not found', myname;
        WHEN TOO_MANY_ROWS THEN
            RAISE EXCEPTION 'employee % not unique', myname;
END;


   带STRICT选项的命令执行成功以后,FOUND的值总是被设为true。



   对于带RETURNING子句的 INSERT/UPDATE/DELETE 命令,无论是否使用了STRICT选项,如果返回的数据行的个数大于一,系统会报错。

   注意: STRICT选项的行为与Oracle PL/SQL's SELECT INTO和相关语句的行为相同。  

   如果想处理查询返回的多个数据行,参考第5.4节。



4.4 执行动态命令
      有时候可能在PL/pgSQL函数中使用动态命令。动态命令是在每次执行时引用不同的表或数据类型的命令。使用EXECUTE语句来执行动态命令:

EXECUTE command-string [ INTO [STRICT] target ];

   

    command-string是一个表达式,它的值是一个字符串(类型为text),这个字符串包含将要被执行的SQL命令。target可以是一个记录类型的变量、一个数据行类型的变量或多个简单变量(包括记录类型的变量的域、数据行类型的变量的域)的列表,不同的变量用逗号分开 。

       如果没有使用INTO子句,查询结果将被丢弃。如果使用了INTO子句,查询结果将被赋给指定的变量。如果target是数据行变量或简单变量的列表,查询结果的列的数据类型必须与target的数据类型完全相同,否则系统会报错。如果target是记录类型的变量,它可以接受任何类型的查询结果。如果查询返回了多个数据行,只有第一个数据行被赋给INTO子句中的变量。如果查询没有返回任何数据行,将把NULL赋给INTO子句中的变量。

       如果使用了STRICT 选项,查询必须而且只能返回一个数据行,否则系统会报错。

       EXECUTE语句不支持SELECT命令。

       注意: PL/pgSQL EXECUTE 语句与SQL的EXECUTE命令没有任何联系。不能在PL/pgSQL函数内部直接使用SQL的EXECUTE命令。  

       使用动态命令时,要注意对单引号的转移处理。可以使用函数quote_ident和quote_literal完成对标识符和普通字符串的转义处理。表名和列名这样的标识符应该传给函数quote_ident,普通字符串常量应该传给函quote_literal,例如:



EXECUTE 'UPDATE tbl SET '
        || quote_ident(colname)
        || ' = '
        || quote_literal(newvalue)
        || ' WHERE key = '
       || quote_literal(keyvalue);





4.5 检查命令执行结果
    PL/pgSQL提供了两种方法来检查一个命令的执行结果。第一种方法是使用GET DIAGNOSTICS命令。它的形式如下:

GET DIAGNOSTICS variable = item [ , ... ];



其中的item可以是ROW_COUNT和RESULT_OID。ROW_COUNT表示上一条SQL命令处理的数据行的个数。RESULT_OID表示最近的SQL命令插入的最后一个数据行的OID。variable是一个变量。例如:

GET DIAGNOSTICS integer_var = ROW_COUNT;

这条命令将ROW_COUNT的值赋给变量integer_var。



       第二种方法是检查一个boolean类型的特殊变量FOUND的值来确定命令的执行结果。FOUND在开始调用每个函数时,首先被自动赋为false。下面的语句会影响FOUND的值:

(1)如果SELECT INTO语句将一个数据行赋给了指定的变量,将FOUND赋为true,否则,将FOUND赋为false。  

(2)PERFORM语句的查询如果返回了一个或多个数据行,将FOUND赋为true,否则,将FOUND赋为false。   

(3)UPDATE、INSERT和DELETE语句如果至少影响了一个数据行,将FOUND赋为true,否则,将FOUND赋为false。

(4)FETCH语句如果返回一个数据行,将FOUND赋为true。如果没有返回数据行,将FOUND赋为false。  

(5)MOVE语句成功地重定位游标,将FOUND赋为true,否则,将FOUND赋为false。

(6)如果FOR语句(包括所有类型的FOR语句)循环了一次或多次,FOUND被赋为真,否则FOUND被赋为假。FOR语句执行结束以后,才会对FOUND赋值。



     FOUND在每个PL/pgSQL函数内部是一个局部变量,对它的任何修改只影响当前的函数。



4.6 空语句
       NULL在 PL/pgSQL中表示一条空语句,它的意思是什么都不做。它通常被用在if/then/else中,表示它的某个分支不需要有任何处理。例如:

BEGIN

        y := x / 0;

    EXCEPTION

        WHEN division_by_zero THEN

            NULL;  -- 忽略这个错误

END;



       下面是一个等价的,更简单的写法,NULl也被省略:   

BEGIN

        y := x / 0;

    EXCEPTION

        WHEN division_by_zero THEN  -- 忽略这个错误

END;

   注意: Oracle's PL/SQL中NULL不能被省略,在PL/pgSQL中,NULL可以被省略。

你可能感兴趣的:(PostgreSQL--PL/pgSQL基本语句)