How to write a function that returns text or integer values?

前端 未结 3 977
名媛妹妹
名媛妹妹 2020-12-11 07:34

I\'m using PostgreSQL 9.2.4.

postgres=# select version();

                           version
--------------------------------------------------------         


        
3条回答
  •  春和景丽
    2020-12-11 08:23

    It sounds like you're solving a problem by creating a bigger problem.

    You don't need a function for this at all. Do it on the client side by checking the affected rows count that's returned by every DML query, or use INSERT ... RETURNING.

    You didn't mention your client language, so here's how to do it in Python with psycopg2. The same approach applies in other languages with syntax variations.

    #!/usr/bin/env python
    import psycopg2
    
    # Connect to the db
    conn = psycopg2.connect("dbname=regress")
    curs = conn.cursor()
    
    # Set up the table to use
    curs.execute("""
    DROP TABLE IF EXISTS so17587735;
    
    CREATE TABLE so17587735 (
        id serial primary key,
        blah text not null
    );
    """);
    
    # Approach 1: Do the insert and check the rowcount:
    curs.execute("""
    INSERT INTO so17587735(blah) VALUES ('whatever');
    """);
    if curs.rowcount != 1:
        raise Exception("Argh, insert affected zero rows, wtf?")
    print("Inserted {0} rows as expected".format(curs.rowcount))
    
    # Approach 2: Use RETURNING
    curs.execute("""
    INSERT INTO so17587735(blah) VALUES ('bored') RETURNING id;
    """);
    returned_rows = curs.fetchall();
    if len(returned_rows) != 1:
        raise Exception("Got unexpected row count {0} from INSERT".format(len(returned_rows)))
    
    print("Inserted row id is {0}".format(returned_rows[0][0]))
    

    In the case of PL/PgSQL calling INSERT you can use the GET DIAGNOSTICS command, the FOUND variable, or RETURN QUERY EXECUTE INSERT ... RETURNING .... Using GET DIAGNOSTICS:

    CREATE OR REPLACE FUNCTION blah() RETURNS void AS $$
    DECLARE
        inserted_rows integer;
    BEGIN
        INSERT INTO some_table VALUES ('whatever');
        GET DIAGNOSTICS inserted_rows = ROW_COUNT;
        IF inserted_rows <> 1 THEN
            RAISE EXCEPTION 'Failed to insert rows; expected 1 row, got %', inserted_rows;
        END IF;
    END;
    $$ LANGUAGE plpgsql VOLATILE;
    

    or if you must return values and must for some reason use PL/PgSQL:

    CREATE OR REPLACE FUNCTION blah() RETURNS SETOF integer AS $$
    BEGIN
        RETURN QUERY EXECUTE INSERT INTO some_table VALUES ('whatever') RETURNING id;
    END;
    $$ LANGUAGE plpgsql VOLATILE;
    

    (assuming the key is id)

    which would be the same as:

    CREATE OR REPLACE FUNCTION blah() RETURNS SETOF integer AS $$
    INSERT INTO some_table VALUES ('whatever') RETURNING id;
    $$ LANGUAGE sql;
    

    or just

    INSERT INTO some_table VALUES ('whatever') RETURNING id;
    

    In other words: Why wrap this in a function? It doesn't make sense. Just check the row-count client side, either with RETURNING or by using the client driver's affected-rows count for INSERT.

提交回复
热议问题