当前位置:网站首页>Stored procedures of PostgreSQL

Stored procedures of PostgreSQL

2022-06-27 18:46:00 Ink Sky Wheel

stay PostgreSQL in , Process language ( for example PL/pgSQL,C,Perl,Python and Tcl) It is called a stored procedure . This process adds many process elements , For example, control structure , Loops and complex calculations , In order to expand SQL standard . It enables you to PostgreSQL Develop complex functions and stored procedures in , And this is using ordinary SQL May not be possible .

Here we will focus on Oracle PL/SQL alike PL/pgSQL Process language . Here are the options PL/pgSQL Why :

  • PL/pgSQL Easy to learn .

  • PostgreSQL Default with PL/pgSQL. stay PL/pgSQL User defined functions developed in can be used like any built-in function .

  • PL/pgSQL It has many functions , Allows you to develop complex user-defined functions .

1. introduction

PostgreSQL Various process language elements are allowed ( It is often called a stored procedure ) Use user-defined functions and stored procedures to extend database functionality .

A stored procedure defines a function for creating triggers or a custom aggregation function . Besides , Stored procedures also add a number of procedural functions , Such as control structures and complex calculations . These make it easier , Develop custom features more effectively .

have access to DO Command call procedure code block , There is no need to define functions or stored procedures .

PostgreSQL Process languages are divided into two categories :

  • Any user can use the security language .SQL and PL/pgSQL It's the language of security .

  • Sandboxed languages are used only by super users , Because sandboxed languages provide the ability to bypass security and allow access to external sources .C Is an example of a sandbox language .


    By default ,PostgreSQL Three process languages are supported :SQL,PL/pgSQL and C. You can also use extensions to integrate other process languages ( for example Perl,Python and TCL) Load into PostgreSQL in .

    1.1、 Use PostgreSQL Advantages of stored procedures

    • Reduce the number of round trips between the application and the database server . all SQL Statements are packaged and stored in PostgreSQL Functions in the database server , Therefore, the application only needs to issue a function call to return the result , You don't have to send multiple SQL Statement and wait for the result between calls .


    • Since user-defined functions and stored procedures have been precompiled and stored in PostgreSQL In the database server , Therefore, the application performance is improved .

    • Reusable in many applications . Once the functionality is developed , You can reuse it in any application .

    1.2、 Use PostgreSQL Disadvantages of stored procedures

    • Because stored procedure programming requires many professional skills that developers do not have , So the speed of software development is slow .

    • Difficult to manage versions and debug .

    • You may not be able to migrate to other database management systems , for example MySQL or Microsoft SQL Server.

    2.PL/pgSQL Block structure

    PL/pgSQL Is a block structured language , therefore ,PL/pgSQL Functions or stored procedures are organized into blocks .

    2.1、PL/pgSQL The grammar of

    [ <<label>> ]
    [ DECLARE
    declarations ]
    BEGIN
    statements;
    ...
    END [ label ];

    • Each block has two parts : Statement and body . The declaration section is optional , The main part is required . The block is marked with END Semicolon after keyword (;) ending .

    • The beginning and end of the block may have optional labels . If you want to EXIT Specify it in the statement of the block body , Or to qualify the name of the variable declared in the block , Please use block labels .


    • In the declaration section , You can declare all variables used in the body section . Each statement in the declaration section is preceded by a semicolon (;) ending .

      • The body is where you put the code . Each statement in the body section is also marked with a semicolon (;) End .

      2.2、PL/pgSQL Block structure example

      Anonymous block

      test=# DO $$
      <<first_block>>
      DECLARE
      counter integer := 0;
      BEGIN
      counter := counter + 1;
      RAISE NOTICE 'The current value of counter is %', counter;
      END first_block $$;
      Be careful : The current value of counter is 1
      DO

      • Please note that ,DO Statement does not belong to the block . It is used to execute anonymous blocks .

      • In the declaration section , Declared a variable counter And set its value to zero .

      • Inside the main body , Increase the value of the counter to 1 And use RAISE NOTICE Statement outputs its value .

      • first_block The label is for demonstration purposes only . In this example , It does nothing .

      Double dollar ($$) Is single quotes (') An alternative . Development PL/pgSQL block , Function or stored procedure , Its body must be passed as a string literal . If you use double dollars ($$), You can avoid reference problems . You can also visit $$ Use tokens between , for example $function$ or $procedure$.

      2.3、PL/pgSQL Subblock

      PL/pgSQL Allows you to place one block within the host of another . A block nested within another block is called a sub block . A block that contains sub blocks is called an external block .

      Subblocks are used to group statements , So that large blocks can be divided into smaller and more logical sub blocks . Variables in a sub block can have the same name as variables in an external block , Even if it's not a good habit .

      When a variable with the same name as that in the external block is declared in the sub block , Variables in external blocks are hidden in sub blocks . If you want to access variables in an external block , Use a block label to qualify its name , This is shown in the following example :

      test=# DO $$
      <<outer_block>>
      DECLARE
      counter integer := 0;
      BEGIN
      counter := counter + 1;
      RAISE NOTICE 'The current value of counter is %', counter;

      DECLARE
      counter integer := 0;
      BEGIN
      counter := counter + 10;
      RAISE NOTICE 'The current value of counter in the subblock is %', counter;
      RAISE NOTICE 'The current value of counter in the outer block is %', outer_block.counter;
      END;

      RAISE NOTICE 'The current value of counter in the outer block is %', counter;

      END outer_block $$;
      Be careful : The current value of counter is 1
      Be careful : The current value of counter in the subblock is 10
      Be careful : The current value of counter in the outer block is 1
      Be careful : The current value of counter in the outer block is 1
      DO

      • First , We are outer_block A statement named counter The variable of .

      • Next , In a sub block , We also declare a variable with the same name .

      • then , Before entering the sub block , The value of the counter is 1. In a sub block , We increase the value of the counter to 10 And print it out . Be careful , The change affects only the counter variables in the sub block .

      • after , We use block labels to reference counter variables in external blocks , To qualify its name external_block.counter.

      • Last , We print out the value of the counter variable in the external block , Its value remains unchanged .

      3.PL/pgSQL Variable

      PL/pgSQL Variables are meaningful names for memory locations . A variable holds a value that can be changed by a block or function . Variables are always associated with specific data types .

      Before using variables , Must be in PL/pgSQL Block is declared in the declaration section of the . Syntax for declaring variables :

      variable_name data_type [:= expression];

      • First , Specify the name of the variable . It is a good habit to assign meaningful names to variables . for example , You should use index or i Substitute named variable counter.

      • secondly , Associate a specific data type with a variable . The data type can be any valid PostgreSQL data type , for example INTEGER,NUMERIC,VARCHAR and CHAR.

      • Third , Optionally assign default values to variables . If you don't do that , The initial value of the variable will be initialized to NULL.

      Declare and initialize various variables

      DO $$
      DECLARE
      counter INTEGER := 1;
      first_name VARCHAR(50) := 'John';
      last_name VARCHAR(50) := 'Doe';
      payment NUMERIC(11,2) := 20.5;
      BEGIN
      RAISE NOTICE '% % % has been paid % USD', counter, first_name, last_name, payment;
      END $$;

      • counter Variables are initialized to 1 The integer of

      • first_name and last_name yes VARCHAR,50 Characters , And initialization John and Doe Text string .

      • payment There are two decimal numbers and initialization 20.5

      Please note that , When the block is entered ,PostgreSQL Default values will be evaluated and set for variables .

      test=# DO $$
      DECLARE
      created_at time := NOW();
      BEGIN
      RAISE NOTICE '%', created_at;
      PERFORM pg_sleep(10);
      RAISE NOTICE '%', created_at;
      END $$;
      Be careful : 23:07:05.060536
      Be careful : 23:07:05.060536
      DO

      • First , Declare a variable , Its default value is initialized to the current time .

      • secondly , Print out the value of the variable and put it in 10 Pause execution within seconds

      • Third , Print it out again created_at The value of the variable .

      3.1、 Copy data type

      PostgreSQL Allows you to define variables of a data type , This data type refers to the data type of the column of the table or the data type of another variable :

      variable_name table_name.column_name%TYPE;

      variable_name variable%TYPE;

      Define a variable city_name, Its name name And city The column names of the tables are the same , The data types are as follows :

      city_name city.name%TYPE := 'San Francisco';

      By using the copy type function , You can get the following benefits :

      • First , You don't have to worry about the data type of the column . You declare a variable to keep only the value of that column in the query .

      • secondly , When the data type of a column changes , You do not need to change the variable declaration in the function to adapt to the new changes .


      • Third , Because the type of internal variables can be changed from one call to another , So you can reference the type of a variable as the data type of a function parameter to create a polymorphic function .

        3.2、 Assign aliases to variables

        PostgreSQL Allows you to define aliases for any variable , As shown below :

        new_name ALIAS FOR old_name;

        Alias is mainly used in triggering process , In order to have a predetermined name for ( for example NEW or OLD) To assign more meaningful names to variables .

        4.PL/pgSQL Constant

        Different from variables , The value of a constant cannot be changed once initialized . Here are the reasons for using constants :

        • First , Constants make the code more readable . for example , Suppose we have a formula as follows :

        price = net_price * 0.8;

        • 0.8 What does that mean? ? It can be interpreted as anything . however , We can give it the meaning of discount :

        price = net_price * ZK;

        • secondly , Constants reduce maintenance , Suppose you have a formula in the function to calculate the price . When the discount is from, for example 0.8 Change to 0.9 when , You need to change all these hard coded values . however , By using constants , You only need to make changes in one place to declare and initialize constants .

        4.1、 Declare constant syntax

        To be in PL/pgSQL Declare a constant in , Please use the following syntax :

        constant_name CONSTANT data_type := expression;

        • First , Specify constant name . By convention , It is capitalized , for example ZK and DISCOUNT.

        • secondly , place CONSTANT Keyword and specify the data type associated with the constant .

        • Third , Initializing a value for a constant .

        4.2、PL/pgSQL Constant example

        Declare a name for the discount zk The constant , And calculate the selling price according to the net price :

        test=# DO $$
        DECLARE
        ZK CONSTANT NUMERIC := 0.8;
        net_price NUMERIC := 50;
        BEGIN
        RAISE NOTICE 'The price is %', net_price * ZK ;
        END $$;
        Be careful : The price is 40.0
        DO

        Now? , An error occurred while trying to change the value of a constant as follows :

        test=# DO $$
        DECLARE
        ZK constant NUMERIC := 0.8;
        net_price NUMERIC := 50;
        BEGIN
        RAISE NOTICE 'The price is %', net_price * ZK ;
        ZK := 0.85;
        END $$;
        error : Variable "zk" Declared as a constant
        LINE 7: ZK := 0.85;
        ^

        Be careful , When the block is entered at run time instead of compile time ,PostgreSQL The value of an accounting constant .

        test=# DO $$
        DECLARE
        start_at CONSTANT time := now();
        BEGIN
        RAISE NOTICE 'Start executing block at %', start_at;
        END $$;
        Be careful : Start executing block at 11:38:34.260159
        DO

        Every time we call the block ,PostgreSQL City assessment NOW() function . To prove it , We execute the block again :

        test=# DO $$
        DECLARE
        start_at CONSTANT time := now();
        BEGIN
        RAISE NOTICE 'Start executing block at %', start_at;
        END $$;
        Be careful : Start executing block at 11:39:52.209155
        DO

        5.PL/pgSQL Errors and messages

        To send a message , Please use RAISE sentence :

        RAISE level format;

        stay RAISE Statement is followed by a level option that specifies the severity of the error .PostgreSQL There are the following levels :

        • DEBUG( debugging )

        • LOG( journal )

        • NOTICE( Be careful )

        • INFO( Information )

        • WARNING( Warning )

        • EXCEPTION( exception )

        If you do not specify a level , By default ,RAISE Statement will use EXCEPTION Level , This raises an error and stops and stops the current transaction .

        The format is a string that specifies the message . This format uses percentage (%) Place holder , These placeholders will be replaced by the next parameter . The number of placeholders must match the number of parameters , otherwise ,PostgreSQL An error message will be reported .

        The following example illustrates RAISE sentence , This statement reports different messages at the current time :

        test=# DO $$
        BEGIN
        RAISE INFO 'information message %', now() ;
        RAISE LOG 'log message %', now();
        RAISE DEBUG 'debug message %', now();
        RAISE WARNING 'warning message %', now();
        RAISE NOTICE 'notice message %', now();
        END $$;
        Information : information message 2019-12-03 12:03:41.136714+08
        Warning : warning message 2019-12-03 12:03:41.136714+08
        Be careful : notice message 2019-12-03 12:03:41.136714+08
        DO

        Please note that , Not all messages are reported to the client , Only INFO,WARNING and NOTICE Level messages are reported to the client . This is due to client_min_messages and log_min_messages Configure parameter control .

        5.1、PL/pgSQL Raise an error message

        To raise an error message , Please be there. RAISE Use... After the statement EXCEPTION Level . Please note that ,RAISE Statement uses... By default EXCEPTION Level .

        In addition to causing an error message , You can also do it in RAISE Statement to add more details :

        USING option = expression

        • MESSAGE: Set error message text

        • HINT: Provide prompt information , To make it easier to find the root cause of the error .

        • DETAIL: Provide details about the error .

        • ERRCODE: Identify the error code , You can use a condition name or a directly five character SQLSTATE Code .

        Causes duplicate email error messages :

        test=# DO $$
        DECLARE
        email varchar(255) := '[email protected]';
        BEGIN
        -- check email for duplicate
        -- ...
        -- report duplicate email
        RAISE EXCEPTION 'Duplicate email: %', email
        USING HINT = 'Check the email again';
        END $$;
        error : Duplicate email: [email protected]
        HINT: Check the email again
        CONTEXT: stay RAISE Of the 8 Yes PL/pgSQL function inline_code_block

        The following example shows how to trigger SQLSTATE And its corresponding conditions :

        DO $$
        BEGIN
        --...
        RAISE SQLSTATE '2210B';
        END $$;

        DO $$
        BEGIN
        --...
        RAISE invalid_regular_expression;
        END $$;

        5.2、 Use ASSERT Statement for debugging checks

        ASSERT Sentence syntax

        ASSERT condition [, message];

        The condition is a Boolean expression . If the condition is evaluated as TRUE, be ASSERT Statement does nothing . If the condition is evaluated as FALSE or NULL, The cause ASSERT_FAILURE.

        If this message is not provided , be PL/pgSQL By default “ Assertion failed ” news . If this message is provided , be ASSERT Statement will use it to replace the default message .

        6.CREATE FUNCTION sentence

        6.1、CREATE FUNCTION Sentence syntax

        To be in PostgreSQL Create a new user-defined function in , Please use CREATE FUNCTION sentence :

        CREATE FUNCTION function_name(p1 type, p2 type)
        RETURNS type AS
        BEGIN
        -- logic
        END;
        LANGUAGE language_name;

        • First , stay CREATE FUNCTION Keyword to specify the name of the function .

        • then , Put a comma separated parameter list in parentheses after the function name .

        • Next , stay RETURNS Keyword to specify the return type of the function .

        • after , Put the code in BEGIN and END In block . The function is always preceded by a semicolon (;) ending , Heel END keyword .

        • Last , In the use of PL/pgSQL Under the circumstances , A procedural language that describes functions , for example plpgsql.

        6.2、CREATE FUNCTION Statement example

        Develop a program called inc A very simple function of , This function increments an integer by 1 And return the result .

        test=# CREATE FUNCTION inc(val integer) RETURNS integer AS $$
        BEGIN
        RETURN val + 1;
        END; $$
        LANGUAGE PLPGSQL;
        CREATE FUNCTION

        Provide to CREATE FUNCTION The entire function definition of must be a single quoted string . This means that if the function has any single quotation marks ('), It must be escaped .

        PostgreSQL There is provided a type called “$” The function of , This feature allows you to select an appropriate string , So you don't have to escape it .

        If the function is valid , be PostgreSQL The function is created and returns CREATE FUNCTION sentence , As shown above .

        Call function :

        test=# SELECT inc(20);
        inc
        -----
        21
        (1 row)

        test=# SELECT inc(inc(20));
        inc
        -----
        22
        (1 row)

        7.PL/pgSQL Function parameter

        7.1、PL/pgSQL IN Parameters

        From create a file named get_sum() The new function of :

        test=# CREATE OR REPLACE FUNCTION get_sum(
        a NUMERIC,
        b NUMERIC)
        RETURNS NUMERIC AS $$
        BEGIN
        RETURN a + b;
        END; $$

        LANGUAGE plpgsql;
        CREATE FUNCTION

        get_sum() The function takes two arguments :a and b And return a number . The data type of these two parameters is NUMERIC. By default ,PostgreSQL The parameter type of any parameter in is IN Parameters . Can be IN Parameters are passed to functions , But they cannot be retrieved as part of the result .

        test=# SELECT get_sum(10,20);
        get_sum
        ---------
        30
        (1 row)

        7.2、PL/pgSQL OUT Parameters

        OUT Parameters are defined as part of the function parameter list , And return as part of the result .

        To define the OUT Parameters , Please use OUT keyword , This is shown in the following example :

        test=# CREATE OR REPLACE FUNCTION abc(
        a NUMERIC,
        b NUMERIC,
        c NUMERIC,
        OUT high NUMERIC,
        OUT low NUMERIC)
        AS $$
        BEGIN
        high := GREATEST(a,b,c);
        low := LEAST(a,b,c);
        END; $$

        LANGUAGE plpgsql;
        CREATE FUNCTION

        abc Function acceptance 5 Parameters :

        • Three IN Parameters :a,b,c.

        • Two OUT Parameters :high( high ) and low( low ).

        Inside the function , Use GREATEST and LEAST The built-in function can get the maximum and minimum three IN Parameters . Because we use OUT Parameters , So we don't need RETURN sentence .OUT Arguments are useful in functions that need to return multiple values without defining custom types .

        The following statement calls abc function :

        test=# SELECT abc(10,20,30);
        abc
        ---------
        (30,10)
        (1 row)

        The output is separated into columns , Please use the following syntax :

        test=# SELECT * FROM abc(10,20,30);
        high | low
        ------+-----
        30 | 10
        (1 row)

        7.3、PL/pgSQL INOUT Parameters

        INOUT Parameter is IN and OUT Combination of parameters . This means that the caller can pass the value to the function . then , Function to change parameters , And return the value as part of the result .

        The following example shows the square function , This function takes a number and returns the square of that number :

        test=# CREATE OR REPLACE FUNCTION square(
        INOUT a NUMERIC)
        AS $$
        BEGIN
        a := a * a;
        END; $$
        LANGUAGE plpgsql;
        CREATE FUNCTION

        test=# SELECT square(4);
        square
        --------
        16
        (1 row)

        7.4、PL/pgSQL VARIADIC Parameters

        PostgreSQL Function can accept a variable number of arguments , But the condition is that all parameters have the same data type . Parameters are passed to the function as an array . See the following example :

        test=# CREATE OR REPLACE FUNCTION sum_avg(
        VARIADIC list NUMERIC[],
        OUT total NUMERIC,
        OUT average NUMERIC)
        AS $$
        BEGIN
        SELECT INTO total SUM(list[i])
        FROM generate_subscripts(list, 1) g(i);

        SELECT INTO average AVG(list[i])
        FROM generate_subscripts(list, 1) g(i);

        END; $$
        LANGUAGE plpgsql;
        CREATE FUNCTION

        test=# SELECT * FROM sum_avg(10,20,30);
        total | average
        -------+---------------------
        60 | 20.0000000000000000
        (1 row)

        8.PL/pgSQL function overloading

        PostgreSQL Allow multiple functions to have the same name , As long as the parameters are different . If multiple functions have the same name , These functions are overloaded . When you call a function ,PostgreSQL Determine the exact function being called according to the input parameters .

        get_rental_function Function acceptance p_customer_id As a parameter . It returns a lease to a specific customer DVD Total duration of ( In days ). for example , We can get customers ID by 232 The lease term of the customer , We call get_rental_duration function , As shown below :

        test=# CREATE OR REPLACE FUNCTION get_rental_duration(p_customer_id INTEGER)
        RETURNS INTEGER AS $$

        DECLARE
        rental_duration INTEGER;
        BEGIN
        -- get the rate based on film_id
        SELECT INTO rental_duration SUM( EXTRACT( DAY FROM return_date - rental_date))
        FROM rental
        WHERE customer_id=p_customer_id;

        RETURN rental_duration;
        END; $$
        LANGUAGE plpgsql;
        CREATE FUNCTION

        test=# SELECT get_rental_duration(232);
        get_rental_duration
        ---------------------
        90
        (1 row)

        Suppose we want to know the lease term of the customer from a specific date to the present . We can do it in get_retal_duration() Add another parameter to the function p_from_date, Or you can develop a new function with the same name but two arguments , As shown below :

        test=# CREATE OR REPLACE FUNCTION get_rental_duration(p_customer_id INTEGER, p_from_date DATE)
        RETURNS INTEGER AS $$
        DECLARE
        rental_duration integer;
        BEGIN
        -- get the rental duration based on customer_id and rental date
        SELECT INTO rental_duration
        SUM( EXTRACT( DAY FROM return_date + '12:00:00' - rental_date))
        FROM rental
        WHERE customer_id= p_customer_id AND
        rental_date >= p_from_date;

        RETURN rental_duration;
        END; $$
        LANGUAGE plpgsql;
        CREATE FUNCTION

        This function has the same name as the first function , It just has two parameters . We said get_rental_duration(integer) Function is get_rental_duration(integer,date) function overloading . The following statement is obtained from 2005 year 7 month 1 From the day of, the customer ID by 232 The lease term of the customer :

        test=# SELECT get_rental_duration(232,'2005-07-01');
        get_rental_duration
        ---------------------
        85
        (1 row)

        Be careful , If we ignore the second parameter ,PostgreSQL The first function... Will be called .

        PL/pgSQL Function overloading and default values

        stay get_rental_duration(integer,date) Function , If we want to add a default value for the second parameter , As shown below :

        test=# CREATE OR REPLACE FUNCTION get_rental_duration(
        p_customer_id INTEGER,
        p_from_date DATE DEFAULT '2005-01-01'
        )
        RETURNS INTEGER AS $$
        DECLARE
        rental_duration integer;
        BEGIN
        -- get the rental duration based on customer_id and rental date
        SELECT INTO rental_duration
        SUM( EXTRACT( DAY FROM return_date + '12:00:00' - rental_date))
        FROM rental
        WHERE customer_id= p_customer_id AND
        rental_date >= p_from_date;

        RETURN rental_duration;
        END; $$
        LANGUAGE plpgsql;
        CREATE FUNCTION

        This means that if we ignore passing p_from_date Parameters ,PostgreSQL Will use 2015 year 1 month 1 Day as default .

        test=# SELECT get_rental_duration(232);
        error : function get_rental_duration(integer) It's not the only one
        LINE 1: SELECT get_rental_duration(232)
        ^
        HINT: Unable to select the best candidate function . You may need to add explicit type conversions .

        PostgreSQL Should I call the first function with one argument or the second function with two arguments ? It cannot choose . therefore , When reloading existing functions , Their functional interfaces should always be different . Now? , You can use only the second function by explicitly passing the second argument . The first function... Cannot be used , Because it makes PostgreSQL Confused which function to call .

        We need to delete the with default values get_rental_duration() function , And recreate... Again with two parameters get_rental_duration function , There is no need to specify a default value for the second parameter .

        test=# DROP FUNCTION get_rental_duration(INTEGER,DATE);
        DROP FUNCTION

        Please note that , When deleting a function , Both parameter and function names must be specified . actually , stay PostgreSQL in , The full name of the function includes the name and parameters .

        The last important note is , Excessive heavy loads should be avoided , This makes it difficult for developers to look at the code to know which function to call .

        Use ILIKE Operator returns all movies whose titles match a particular pattern

        test=# CREATE OR REPLACE FUNCTION get_film (p_pattern VARCHAR)
        RETURNS TABLE (
        film_title VARCHAR,
        film_release_year INT
        )
        AS $$
        BEGIN
        RETURN QUERY SELECT
        title,
        cast( release_year as integer)
        FROM
        film
        WHERE
        title ILIKE p_pattern ;
        END; $$

        LANGUAGE 'plpgsql';
        CREATE FUNCTION

        get_film(varchar) Function takes an argument p_pattern, This is the pattern you want to match with the movie title . To return a table from a function , Please use RETURNS TABLE Syntax and specify the columns of the table . Each column is marked with a comma (,) Separate .

        In this function , We return a query , The query is SELECT Result of statement . Please note that ,SELECT The columns in the statement must match the columns of the table we want to return . Because of the data type of the movie table release_year Is not an integer , So we have to cast it to an integer using a cast .

        call get_film(varchar) Function to get the title with Al All the movies at the beginning :

        test=# SELECT
        *
        FROM
        get_film ('Al%');
        film_title | film_release_year
        ------------------+-------------------
        Alabama Devil | 2006
        Aladdin Calendar | 2006
        Alamo Videotape | 2006
        Alaska Phantom | 2006
        Ali Forever | 2006
        Alice Fantasia | 2006
        Alien Center | 2006
        Alley Evolution | 2006
        Alone Trip | 2006
        Alter Victory | 2006
        (10 rows)

        If you call this function with the following statement ,PostgreSQL Return a table with one column , It contains an array of movies :

        test=# SELECT
        get_film ('Al%');
        get_film
        ---------------------------
        ("Alabama Devil",2006)
        ("Aladdin Calendar",2006)
        ("Alamo Videotape",2006)
        ("Alaska Phantom",2006)
        ("Ali Forever",2006)
        ("Alice Fantasia",2006)
        ("Alien Center",2006)
        ("Alley Evolution",2006)
        ("Alone Trip",2006)
        ("Alter Victory",2006)
        (10 rows)

        actually , Each row is usually processed before it is added to the result set of a function .

        test=# CREATE OR REPLACE FUNCTION get_film (p_pattern VARCHAR,p_year INT)
        RETURNS TABLE (
        film_title VARCHAR,
        film_release_year INT
        ) AS $$
        DECLARE
        var_r record;
        BEGIN
        FOR var_r IN(SELECT
        title,
        release_year
        FROM film
        WHERE title ILIKE p_pattern AND
        release_year = p_year)
        LOOP
        film_title := upper(var_r.title) ;
        film_release_year := var_r.release_year;
        RETURN NEXT;
        END LOOP;
        END; $$
        LANGUAGE 'plpgsql';
        CREATE FUNCTION

        Created a file with a similar name get_film(varchar,int) Function of , But accept two parameters :

        • The first parameter is p_pattern, If the title matches this pattern , We will use p_pattern Search for movies . We use ILIKE Operator to perform a search .

        • The second parameter is the year the movie was released .

        • Because each row needs to be processed before it is returned , So we use FOR LOOP Statement to process it . In each iteration , We use UPPER Function to capitalize the title of the movie .

        RETURN NEXT Statement to add a row to the result set of the function . Carry on , And establish the result set in each iteration of the loop .

        test=# SELECT
        *
        FROM
        get_film ('wr%', 2006);
        film_title | film_release_year
        ----------------+-------------------
        WRATH MILE | 2006
        WRONG BEHAVIOR | 2006
        (2 rows)

        9.PL/pgSQL IF sentence

        IF Statement is used to conditionally execute a command .PL/pgSQL Provides you with three forms of IF sentence .

        9.1、IF The simplest form of a statement

        If the condition is true , be IF Statement execute statement . If the result of the condition is false, Pass control to END IF The next statement after the section . This is explained below IF The simplest form of a statement :

        IF condition THEN
        statement;
        END IF;

        The condition is a Boolean expression , The result is true or false.

        This statement is the statement that will be executed when the condition is true . It can be any valid statement , It can even be another IF sentence .IF The code statement is placed in another IF Statement within , It's called nesting IF sentence .

        test=# DO $$
        DECLARE
        a integer := 10;
        b integer := 20;
        BEGIN
        IF a > b THEN
        RAISE NOTICE 'a is greater than b';
        END IF;

        IF a < b THEN
        RAISE NOTICE 'a is less than b';
        END IF;

        IF a = b THEN
        RAISE NOTICE 'a is equal to b';
        END IF;
        END $$;
        Be careful : a is less than b
        DO

        In this example , We declared two variables a and b. In the body of the block , We use IF The comparison operator in the Boolean expression of the statement >,< and = Compare a and b Value , And print out the corresponding message .

        9.2、IF THEN ELSE sentence

        9.2.1、IF THEN ELSE Sentence syntax

        IF THEN ELSE Statement under condition true To execute an order , Condition is false Execute alternate command when . This is explained below IF THEN ELSE Sentence syntax :

        IF condition THEN
        statements;
        ELSE
        alternative-statements;
        END IF;

        9.2.1、IF THEN ELSE Statement example
        test=# DO $$
        DECLARE
        a integer := 10;
        b integer := 20;
        BEGIN
        IF a > b THEN
        RAISE NOTICE 'a is greater than b';
        ELSE
        RAISE NOTICE 'a is not greater than b';
        END IF;
        END $$;
        Be careful : a is not greater than b
        DO

        Because of the expression a > b For false , Therefore, the ELSE Statement in clause .

        9.3、IF THEN ELSIF THEN ELSE sentence

        9.3.1、IF THEN ELSIF THEN ELSE Sentence syntax

        IF and IF THEN ELSE Statement allows you to evaluate only one condition . however , Use this form of IF sentence , You may need to evaluate several conditions .

        IF condition-1 THEN
        if-statement;
        ELSIF condition-2 THEN
        elsif-statement-2
        ...
        ELSIF condition-n THEN
        elsif-statement-n;
        ELSE
        else-statement;
        END IF:

        Condition is true, Then execute the corresponding statement in the branch . for example , If condition-1,condition-2 Wait for true, The corresponding statement will be executed :if-statement,elseif-statement-2 etc. . If a condition is met ,PostgreSQL The evaluation of the following conditions will be stopped .

        If all the conditions are false, Then execute the last ELSE Statements in branches .

        9.3.2、IF THEN ELSIF THEN ELSE Example
        test=# DO $$
        DECLARE
        a integer := 10;
        b integer := 10;
        BEGIN
        IF a > b THEN
        RAISE NOTICE 'a is greater than b';
        ELSIF a < b THEN
        RAISE NOTICE 'a is less than b';
        ELSE
        RAISE NOTICE 'a is equal to b';
        END IF;
        END $$;
        Be careful : a is equal to b
        DO

        In this example , because a be equal to b, So will execute ELSE Statements in branches .

        10.PL/pgSQL CASE sentence

        except IF Out of statement ,PostgreSQL It also provides CASE Statements that allow conditional execution of code blocks . The CASE There are two forms of statements : Simple CASE Statement and search CASE sentence .

        10.1、 ordinary CASE sentence

        CASE search-expression
        WHEN expression_1 [, expression_2, ...] THEN
        when-statements
        [ ... ]
        [ELSE
        else-statements ]
        END CASE;

        search-expression It's an expression , It will use equal operands (=) With each WHEN Expression evaluation in branch . If I find a match , Then execute the corresponding WHEN In the branch when sentence . The following subsequent expressions will not be evaluated .

        If no match is found , execute ELSE In the branch else sentence .ELSE Branches are optional . If no match is found , And there's no ELSE Branch , be PostgreSQL Will lead to CASE_NOT_FOUND abnormal .

        10.2、 Simple CASE Examples of statements

        test=# CREATE OR REPLACE FUNCTION get_price_segment(p_film_id integer)
        RETURNS VARCHAR(50) AS $$
        DECLARE
        rate NUMERIC;
        price_segment VARCHAR(50);
        BEGIN
        -- get the rate based on film_id
        SELECT INTO rate rental_rate
        FROM film
        WHERE film_id = p_film_id;

        CASE rate
        WHEN 0.99 THEN
        price_segment = 'Mass';
        WHEN 2.99 THEN
        price_segment = 'Mainstream';
        WHEN 4.99 THEN
        price_segment = 'High End';
        ELSE
        price_segment = 'Unspecified';
        END CASE;

        RETURN price_segment;
        END; $$
        LANGUAGE plpgsql;
        CREATE FUNCTION

        test=# SELECT get_price_segment(123) AS "Price Segment";
        Price Segment
        ---------------
        High End
        (1 row)

        In this example , We created a get_price_segment The new function of , This function accepts p_film_id As a parameter . According to the movie rent , It returns the price segment : The public , Main stream , High-end . If the price is not 0.99、2.99 or 4.99, Then the function returns the unspecified price .

        10.3、 The search of CASE sentence

        The following syntax describes the CASE sentence

        CASE
        WHEN boolean-expression-1 THEN
        statements
        [ WHEN boolean-expression-2 THEN
        statements
        ... ]
        [ ELSE
        statements ]
        END CASE;

        The search of CASE Statements are based on each WHEN Clause to execute the statement .PostgreSQL Evaluate Boolean expressions from top to bottom , Until an expression is true . Then evaluate the stop and execute the corresponding statement . Control in END CASE Then pass to the next statement .

        If you can't find the right result , execute ELSE Statement in clause .ELSE Clauses are optional . If omitted ELSE Clause , But no real results , be PostgreSQL Will lead to CASE_NOT_FOUND abnormal .

        10.4、 The search of CASE Statement example

        test=# CREATE OR REPLACE FUNCTION get_customer_service (p_customer_id INTEGER)
        RETURNS VARCHAR (25) AS $$
        DECLARE
        total_payment NUMERIC ;
        service_level VARCHAR (25) ;
        BEGIN
        -- get the rate based on film_id
        SELECT
        INTO total_payment SUM (amount)
        FROM
        payment
        WHERE
        customer_id = p_customer_id ;

        CASE
        WHEN total_payment > 200 THEN
        service_level = 'Platinum' ;
        WHEN total_payment > 100 THEN
        service_level = 'Gold' ;
        ELSE
        service_level = 'Silver' ;
        END CASE ;

        RETURN service_level ;
        END ; $$
        LANGUAGE plpgsql;
        CREATE FUNCTION

        get_customer_service Function acceptance p_customer_id As a parameter . It first obtains the total payment paid by the customer from the payment table . then , Based on total payment , This function uses the CASE Statement returns the service level platinum , Gold and silver .

        test=# SELECT
        148 AS customer,
        get_customer_service (148)
        UNION

        SELECT
        178 AS customer,
        get_customer_service (178)
        UNION

        SELECT
        81 AS customer,
        get_customer_service (81);
        customer | get_customer_service
        ----------+----------------------
        178 | Gold
        81 | Silver
        148 | Platinum
        (3 rows)

        Please note that , To search the case Statement similar to IF ELSIF ELSE sentence .

        11.PL/pgSQL Loop statement

        PostgreSQL Three loop statements are provided :LOOP,WHILE Circulation and FOR loop .

        11.1、LOOP sentence

        11.1.1、LOOP Sentence syntax

        Sometimes , You need to repeat a statement block , Until the condition becomes true . So , have access to PL/pgSQL LOOP sentence . This is explained below LOOP Sentence syntax :

        <<label>>
        LOOP
        Statements;
        EXIT [<<label>>] WHEN condition;
        END LOOP;

        LOOP Statements are also called unconditional loop statements , Because it executes the statement until EXIT The condition in the statement evaluates to true. Please note that , stay EXIT Statement WHEN The condition specified after the keyword is a Boolean expression , The result is true or false.

        Loop statements can be nested . One LOOP Statement placed in another LOOP In the sentence , This is called a nested loop . under these circumstances , You need to specify for the loop label that you want to EXIT Loop terminated in statement .

        11.1.2、PL/pgSQL LOOP Example

        Use LOOP Statement development returns to the n A function of Fibonacci serial number .

        test=# CREATE OR REPLACE FUNCTION fibonacci (n INTEGER)
        RETURNS INTEGER AS $$
        DECLARE
        counter INTEGER := 0 ;
        i INTEGER := 0 ;
        j INTEGER := 1 ;
        BEGIN

        IF (n < 1) THEN
        RETURN 0 ;
        END IF;

        LOOP
        EXIT WHEN counter = n ;
        counter := counter + 1 ;
        SELECT j, i + j INTO i, j ;
        END LOOP ;

        RETURN i ;
        END ;
        $$ LANGUAGE plpgsql;
        CREATE FUNCTION

        Fibonacci The() function accepts an integer and returns the n Fibonacci Numbers . According to the definition , Fibonacci number is expressed in 0 and 1 A sequence of integers starting with , Each subsequent number is the sum of the first two numbers , for example 1、1、2(1 + 1),3(2 + 1), 5(3 +2),8(5 + 3),......

        In the declaration section , Initialize the counter variable to zero (0). Inside the loop , When the counter is equal to n when , Loop exit .

        SELECT j, i + j INTO i,   j ;

        Without using temporary variables , Exchange at the same time i and j.

        11.2、WHILE loop

        WHILE A loop statement executes a block of statements , Until the condition is evaluated as false. stay WHILE In loop statement ,PostgreSQL Evaluate the condition before executing the statement block . If the condition is true, Then execute the statement block , Until the assessment is false.

        11.2.1、WHILE Cyclic grammar

        [ <<label>> ]
        WHILE condition LOOP
        statements;
        END LOOP;

        11.2.2、WHILE Loop example

        Use loop Statement rewriting Fibonacci function , As shown below :

        test=# CREATE OR REPLACE FUNCTION fibonacci (n INTEGER)
        RETURNS INTEGER AS $$
        DECLARE
        counter INTEGER := 0 ;
        i INTEGER := 0 ;
        j INTEGER := 1 ;
        BEGIN

        IF (n < 1) THEN
        RETURN 0 ;
        END IF;

        WHILE counter <= n LOOP
        counter := counter + 1 ;
        SELECT j, i + j INTO i, j ;
        END LOOP ;

        RETURN i ;
        END ;
        $$ LANGUAGE plpgsql;
        CREATE FUNCTION

        11.3、FOR Loop statement

        FOR The loop statement is PostgreSQL The most complex loop statement in .

        11.3.1、 Used to traverse the integer range

        FOR Loop through the range of integers loop Sentence syntax :

        [ <<label>> ]
        FOR loop_counter IN [ REVERSE ] from.. to [ BY expression ] LOOP
        statements
        END LOOP [ label ];

        • First ,PostgreSQL Create an integer variable that exists only inside the loop loop_counter. By default , The loop counter is added after each iteration . If you use REVERSE keyword ,PostgreSQL The cycle counter will be subtracted .

        • secondly ,from and to Is an expression that specifies the lower and upper limits of the range .PostgreSQL These expressions are evaluated before entering the loop .

        • Third ,BY Clause specifies the iteration step . If you omit this option , The default step is 1.PostgreSQL The expression is also evaluated once in the loop entry .

        11.3.2、FOR Examples of loop statements 1

        Loop traversal 1 To 5, And print out a message in each iteration . The counter needs 1、2、3、4、5. In each iteration of the loop ,PostgreSQL take 1 Add to the counter .

        DO $$
        BEGIN
        FOR counter IN 1..5 LOOP
        RAISE NOTICE 'Counter: %', counter;
        END LOOP;
        END; $$

        11.3.3、FOR Examples of loop statements 2

        from 5 Loop to 1, And print a message in each iteration . The counter takes 5、4、3、2、1. In each iteration ,PostgreSQL Subtract... From the counter 1.

        DO $$
        BEGIN
        FOR counter IN REVERSE 5..1 LOOP
        RAISE NOTICE 'Counter: %', counter;
        END LOOP;
        END; $$

        11.3.4、FOR Examples of loop statements 3

        stay 1 To 6 In between , And print out the counter in each cycle iteration . The counter takes 1、3、5. In each iteration ,PostgreSQL take 2 Add to the counter .

        DO $$
        BEGIN
        FOR counter IN 1..6 BY 2 LOOP
        RAISE NOTICE 'Counter: %', counter;
        END LOOP;
        END; $$

        11.4、FOR Loop through the query results

        11.4.1、 Syntax for traversing query results

        [ <<label>> ]
        FOR target IN query LOOP
        statements
        END LOOP [ label ];

        11.4.2、 Example of traversing query results

        The following function accepts an integer , This integer specifies the... To be retrieved from the sample database film Number of rows queried in the table .FOR Loop statement loop through the rows returned by the query , And print out the movie title .

        test=# CREATE OR REPLACE FUNCTION for_loop_through_query(
        n INTEGER DEFAULT 10
        )
        RETURNS VOID AS $$
        DECLARE
        rec RECORD;
        BEGIN
        FOR rec IN SELECT title
        FROM film
        ORDER BY title
        LIMIT n
        LOOP
        RAISE NOTICE '%', rec.title;
        END LOOP;
        END;
        $$ LANGUAGE plpgsql;
        CREATE FUNCTION

        test=# SELECT for_loop_through_query(5);
        for_loop_through_query
        ------------------------

        (1 row)

        Be careful : Academy Dinosaur
        Be careful : Ace Goldfinger
        Be careful : Adaptation Holes
        Be careful : Affair Prejudice
        Be careful : African Egg

        11.5、 Query results for traversing dynamic queries

        11.5.1、 Traverse the syntax of dynamic queries

        Sometimes , You want to be in PL/pgSQL Function to construct a dynamic query and traverse its results . So , have access to FOR The syntax of circular statements :

        [ <<label>> ]
        FOR row IN EXECUTE string_expression [ USING query_param [, ... ] ]
        LOOP
        statements
        END LOOP [ label ];

        • You can use string expressions ( It's text formatted SQL sentence ) Instead of SQL sentence . This allows you to dynamically construct queries .

        • If the query has parameters , You can use USING Statement to pass parameters to a query .

        11.5.2、 Traversal dynamic query example

        The following function demonstrates how to use FOR Loop statements loop through dynamic queries . It takes two arguments :

        • sort_type:1 Indicates sorting query results by title ,2 Indicates sorting results by release year .

        • n: Number of rows to query from the movie table . Be careful , It will be USING Used in clauses .

        First , We build the query based on the input parameters , And then in FOR Execute query in loop function .

        test=# CREATE OR REPLACE FUNCTION for_loop_through_dyn_query(
        sort_type INTEGER,
        n INTEGER
        )
        RETURNS VOID AS $$
        DECLARE
        rec RECORD;
        query text;
        BEGIN

        query := 'SELECT title, release_year FROM film ';
        IF sort_type = 1 THEN
        query := query || 'ORDER BY title';
        ELSIF sort_type = 2 THEN
        query := query || 'ORDER BY release_year';
        ELSE
        RAISE EXCEPTION 'Invalid sort type %s', sort_type;
        END IF;

        query := query || ' LIMIT $1';

        FOR rec IN EXECUTE query USING n
        LOOP
        RAISE NOTICE '% - %', rec.release_year, rec.title;
        END LOOP;

        END;
        $$ LANGUAGE plpgsql;
        CREATE FUNCTION

        call for_loop_through_dyn_query() obtain 5 Film and sort by title :

        test=# SELECT for_loop_through_dyn_query(1,5);
        for_loop_through_dyn_query
        ----------------------------

        (1 row)

        Be careful : 2006 - Academy Dinosaur
        Be careful : 2006 - Ace Goldfinger
        Be careful : 2006 - Adaptation Holes
        Be careful : 2006 - Affair Prejudice
        Be careful : 2006 - African Egg

        call for_loop_through_dyn_query() obtain 5 Films and sorted by release year :

        test=# SELECT for_loop_through_dyn_query(2,5);
        for_loop_through_dyn_query
        ----------------------------

        (1 row)

        Be careful : 2006 - Grosse Wonderful
        Be careful : 2006 - Airport Pollock
        Be careful : 2006 - Bright Encounters
        Be careful : 2006 - Academy Dinosaur
        Be careful : 2006 - Chamber Italian

        12.PL/pgSQL The cursor

        PL/pgSQL Cursors allow us to encapsulate queries and process each individual row at once . When we want to divide a large result set into multiple parts and deal with each part separately , We use cursors . If we deal with it immediately , Memory overflow errors may occur .

        in addition , We can develop a function that returns a reference to a cursor . This is an effective way to return a large result set from a function . Function callers can process result sets based on cursor references .

        To use a cursor :

        • First , Declare a cursor .

        • Next , Open the cursor .

        • then , Extract the rows in the result set into the target .

        • after , Check if there are any remaining rows to extract . yes , Execution steps 3, Otherwise, carry out the steps 5.

        • Last , Close the cursor .

        12.1、 declare cursor

        To access the cursor , A cursor variable needs to be declared in the declaration part of the block .PostgreSQL It provides us with a kind of product called REFCURSOR To declare cursor variables :

        DECLARE
        my_cursor REFCURSOR;

        Another way to declare a cursor bound to a query is to use the following syntax :

        cursor_name [ [NO] SCROLL ] CURSOR [( name datatype, name data type, ...)] FOR query;

        • First , Specify a variable name for the cursor .

        • Next , Specify whether you can use SCROLL Scroll the cursor backwards . If you use NO SCROLL, You cannot scroll the cursor backwards .

        • then , place CURSOR keyword , Followed by a comma separated list of parameters ( Name data type ), These parameters define the parameters of the query . When opening cursor , These parameters will be replaced by values .

        • after , Can be in FOR Keyword followed by a query . Any valid... Can be used here SELECT sentence .

        Declare cursor examples

        DECLARE
        cur_films CURSOR FOR SELECT * FROM film;
        cur_films2 CURSOR (year integer) FOR SELECT * FROM film WHERE release_year = year;

        • cur_films It's a cursor , It encapsulates the film All the rows in the table .

        • cur_films2 It's a cursor , Used to package movies with a specific release year in film In the table .

        12.2、 Open cursor

        The cursor must be opened before it can be used to query rows .PostgreSQL Provides syntax for opening unbound and bound cursors .

        12.2.1、 Open unbound cursor

        Use the following syntax to open an unbound cursor :

        OPEN unbound_cursor_variable [ [ NO ] SCROLL ] FOR query;

        Because the unbound cursor variable at the time of declaration is not bound to any query , So you must specify a query when you open it :

        OPEN my_cursor FOR SELECT * FROM city WHERE counter = p_country;

        PostgreSQL Allows us to open a cursor and bind it to a dynamic query . The grammar is as follows :

        OPEN unbound_cursor_variable[ [ NO ] SCROLL ]
        FOR EXECUTE query_string [USING expression [, ... ] ];

        In the following example , We built a dynamic query , The query is based on sort_field Parameter to sort rows , And open the cursor that executes the dynamic query :

        query := 'SELECT * FROM city ORDER BY $1';

        OPEN cur_city FOR EXECUTE query USING sort_field;

        12.2.2、 Open bound cursor

        Because the cursor bound at the time of declaration is already bound to the query , So when we open it , Just pass the parameters to the query if necessary :

        OPEN cursor_variable[ (name:=value,name:=value,...)];

        In the following example , We opened the binding cursor declared above cur_films and cur_films2:

        OPEN cur_films;
        OPEN cur_films2(year:=2005);

        12.2.3、 Use cursors

        After opening the cursor , We can use FETCH,MOVE,UPDATE or DELETE Statement to operate on it .

        12.3、 Get the next line

        FETCH [ direction { FROM | IN } ] cursor_variable INTO target_variable;

        FETCH Statement to get the next line from the cursor , And assign a target_variable, The target_variable It can be a record , Row variables or comma separated list of variables . If no more rows are found , Will target_variable Set to NULL.

        By default , If you do not specify a direction , The cursor will move to the next line . The following is valid for cursors :

        • NEXT

        • LAST

        • PRIOR

        • FIRST

        • ABSOLUTE count

        • RELATIVE count

        • FORWARD

        • BACKWARD

        Please note that ,FORWARD and BACKWARD The direction is only applicable to the use of SCROLL Option declared cursors .

        Get an example of a cursor :

        FETCH cur_films INTO row_film;
        FETCH LAST FROM row_film INTO title, release_year;

        12.4、 Move the cursor

        MOVE [ direction { FROM | IN } ] cursor_variable;

        If you just want to move the cursor without retrieving any rows , You can use MOVE sentence . This direction accepts and FETCH Statement with the same value .

        MOVE cur_films2;
        MOVE LAST FROM cur_films;
        MOVE RELATIVE -1 FROM cur_films;
        MOVE FORWARD 3 FROM cur_films;

        12.5、 Delete or update rows

        After positioning the cursor , have access to DELETE WHERE CURRENT OF or UPDATE WHERE CURRENT OF Statement to delete or update the row identified by the cursor , As shown below :

        UPDATE table_name
        SET column = value, ...
        WHERE CURRENT OF cursor_variable;

        DELETE FROM table_name
        WHERE CURRENT OF cursor_variable;

        See the following example :

        UPDATE film SET release_year = p_year
        WHERE CURRENT OF cur_films;

        To close an open cursor , Use CLOSE sentence , As shown below :

        CLOSE cursor_variable;

        CLOSE Statement to release resources , Or the cursor variable is released , Make it reusable OPEN Statement open .

        12.6、PL/pgSQL The cursor – All put together

        following get_film_titles(integer) The function accepts a parameter that indicates the year the movie was released . Inside the function , Query all movies whose release year is equal to the release year passed to this function . Use the cursor to cycle through the rows , And link the title to the year the movie was released , The title of the movie contains ful .

        test=# CREATE OR REPLACE FUNCTION get_film_titles(p_year INTEGER)
        RETURNS text AS $$
        DECLARE
        titles TEXT DEFAULT '';
        rec_film RECORD;
        cur_films CURSOR(p_year INTEGER)
        FOR SELECT title, release_year
        FROM film
        WHERE release_year = p_year;
        BEGIN
        -- Open the cursor
        OPEN cur_films(p_year);

        LOOP
        -- fetch row into the film
        FETCH cur_films INTO rec_film;
        -- exit when no more row to fetch
        EXIT WHEN NOT FOUND;

        -- build the output
        IF rec_film.title LIKE '%ful%' THEN
        titles := titles || ',' || rec_film.title || ':' || rec_film.release_year;
        END IF;
        END LOOP;

        -- Close the cursor
        CLOSE cur_films;

        RETURN titles;
        END; $$

        LANGUAGE plpgsql;
        CREATE FUNCTION

        test=# SELECT get_film_titles(2006);
        get_film_titles
        ----------------------------------------------------------------------------------------------------------
        ,Grosse Wonderful:2006,Day Unfaithful:2006,Reap Unfaithful:2006,Unfaithful Kill:2006,Wonderful Drop:2006
        (1 row)

        13.PostgreSQL The creation process

        13.1、CREATE PROCEDURE Sentence syntax

        To create a new stored procedure , Please use CREATE PROCEDURE sentence . The following shows CREATE PROCEDURE A simplified syntax for statements :

        CREATE [OR REPLACE] PROCEDURE procedure_name(parameter_list)
        LANGUAGE language_name
        AS $$
        stored_procedure_body;
        $$;

        • First , stay CREATE PROCEDURE Clause to specify the name of the stored procedure .

        • Next , Define a parameter list similar to the parameter list of user-defined functions .

        • then , Specify the programming language for the stored procedure , for example PLpgSQL and SQL.

        • after , Place the code in the body of the stored procedure AS After keyword .

        • Last , Use binary ($$) End stored procedure .

        Different from user-defined functions , The stored procedure did not return a value . If you want to end the process earlier , You can use... Without any expression RETURN sentence , As shown below :

        RETURN;

        If you want to return a value from a stored procedure , You can use the output parameter . The final value of the output parameter is returned to the caller .

        13.2、 Create a sample stored procedure

        Use the following accounts Table :

        test=# CREATE TABLE accounts (
        id INT GENERATED BY DEFAULT AS IDENTITY,
        name VARCHAR(100) NOT NULL,
        balance DEC(15,2) NOT NULL,
        PRIMARY KEY(id)
        );

        INSERT INTO accounts(name,balance)
        VALUES('Bob',10000);

        INSERT INTO accounts(name,balance)
        VALUES('Alice',10000);
        CREATE TABLE

        INSERT 0 1

        INSERT 0 1

        Here are accounts Table data :

        test=# SELECT * FROM accounts;
        id | name | balance
        ----+-------+----------
        1 | Bob | 10000.00
        2 | Alice | 10000.00
        (2 rows)

        Create a file called transfer Stored procedure , This process transfers the specified amount from one account to another :

        test=# CREATE OR REPLACE PROCEDURE transfer(INT, INT, DEC)
        LANGUAGE plpgsql
        AS $$
        BEGIN
        -- subtracting the amount from the sender's account
        UPDATE accounts
        SET balance = balance - $3
        WHERE id = $1;

        -- adding the amount to the receiver'
        s account
        UPDATE accounts
        SET balance = balance + $3
        WHERE id = $2;

        COMMIT;
        END;
        $$;
        CREATE PROCEDURE

        To call a stored procedure , Please use CALL sentence , As shown below :

        CALL stored_procedure_name(parameter_list);

        Call the stored procedure and verify :

        test=# CALL transfer(1,2,1000);
        CALL

        test=# SELECT * FROM accounts;
        id | name | balance
        ----+-------+----------
        1 | Bob | 9000.00
        2 | Alice | 11000.00
        (2 rows)


        原网站

        版权声明
        本文为[Ink Sky Wheel]所创,转载请带上原文链接,感谢
        https://yzsam.com/2022/178/202206271615586303.html