Domanda

(cross posted to the pgsql-novice mailing list)

Suppose the following:

CREATE TABLE base_foo (size int);                                                                              

CREATE VIEW foo AS SELECT * FROM base_foo;                                                                     

CREATE FUNCTION insert_foo() RETURNS TRIGGER AS                                                                
$$BEGIN                                                                                                        
  INSERT INTO base_foo VALUES (NEW.size);                                                                      
  RETURN NEW;                                                                                                  
END$$ language plpgsql;                                                                                        

CREATE TRIGGER insert_foo INSTEAD OF INSERT ON foo                                                             
FOR EACH ROW execute PROCEDURE insert_foo();                                                                   

Observe This Behavior

I can insert into my view:

INSERT INTO foo VALUES (2);                                                                                    

It works; no problem. Now, if I change the trigger function so
that instead of two statements, the second one RETURN, it is rather one
INSERT with a RETURNING clause, as so:

CREATE OR REPLACE FUNCTION insert_foo() RETURNS TRIGGER AS                                                     
$$BEGIN                                                                                                        
  INSERT INTO base_foo VALUES (NEW.size)                                                                       
  RETURNING NEW;                                                                                               
END$$ language plpgsql;                                                                                        

then an insert causes an error:

INSERT INTO foo VALUES (3);                                                                                    
ERROR:  query has no destination for result data                                                               
CONTEXT:  PL/pgSQL function insert_foo() line 2 at SQL statement                                               

The Documentation

Docs say of RETURN:

RETURN with an expression terminates the function and returns the value of expression to the caller.

Docs say of RETURNING:

The optional RETURNING clause causes INSERT to compute and return value(s) based on each row actually inserted.

(emphases mine)

My questions are two:

  1. What is the actual difference in meaning between these two keywords in this context, explained in a way that would permit me to predict the error?

  2. What is the meaning of the error, i.e., since the trigger function needs a value to return, and since the INSERT is the final statement of the trigger function, why does the query have no destination for the result data?

È stato utile?

Soluzione

Please read also this excerpt (from the same link: http://www.postgresql.org/docs/9.3/static/sql-insert.html)

If the INSERT command contains a RETURNING clause, the result will be similar to that of a SELECT statement containing the columns and values defined in the RETURNING list, computed over the row(s) inserted by the command.

Yes, I know that this description may be confusing :)
In easy words: returning clause works similar to SELECT, which retrieves rows from the table, combines them into a resultset, and sends this resultset directly to the client (the client = gui tool, java/c++ programm etc.). The client must know how to read this resultset (open it, retrieve rows, values etc. from it), using some API - for example in java there is JDBC api for processing resultsets--> look for ResultSet class.

So, returning clause creates a resultset and sent it to the client - in the same way as ordinary SELECT does.

Return statement in the function terminates that function and returns the value of expression to the caller.
Not directly to the client, but to the caller - to the other function/procedure or SELECT statement which called this function. And doesn't returns the resultset (a set of rows), but the value.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top