Thread: SQL stored function inserting and returning data in a row.
Hi, Is there any way to define a SQL stored function that inserts a row in a table and returns the serial generated? CREATE TABLE matchmaking_session ( session_id bigint NOT NULL DEFAULT nextval('seq_matchmaking_session_id'), ... ); CREATE FUNCTION create_matchmaking_sesssion(...) RETURNS bigint AS $$ INSERT INTO matchmaking_session(...) VALUES (...) RETURNING session_id; $$ LANGUAGE SQL; 2008-01-10 22:08:48 EST ERROR: return type mismatch in function declared to return bigint 2008-01-10 22:08:48 EST DETAIL: Function's final statement must be a SELECT. 2008-01-10 22:08:48 EST CONTEXT: SQL function "create_matchmaking_sesssion" I can easily convert this code into a PL/pgSQL function, but I'm thinking that pure SQL is more natural (and faster?) for such a stored function. Regards, -- Daniel
Daniel Caune wrote: >Hi, > >Is there any way to define a SQL stored function that inserts a row in a >table and returns the serial generated? > >CREATE TABLE matchmaking_session >( > session_id bigint NOT NULL DEFAULT >nextval('seq_matchmaking_session_id'), > ... >); > >CREATE FUNCTION create_matchmaking_sesssion(...) > RETURNS bigint >AS $$ > INSERT INTO matchmaking_session(...) > VALUES (...) > RETURNING session_id; >$$ LANGUAGE SQL; > >2008-01-10 22:08:48 EST ERROR: return type mismatch in function >declared to return bigint >2008-01-10 22:08:48 EST DETAIL: Function's final statement must be a >SELECT. >2008-01-10 22:08:48 EST CONTEXT: SQL function >"create_matchmaking_sesssion" > > > What about $$ INSERT INTO .... ; select currval('seq_matchmaking_session_id'); $$ language sql; ?
On Jan 11, 2008 4:23 AM, Daniel Caune <daniel.caune@ubisoft.com> wrote: > Hi, > > Is there any way to define a SQL stored function that inserts a row in a > table and returns the serial generated? Maybe you just need INSERT ... RETURNING? http://www.postgresql.org/docs/8.2/interactive/sql-insert.html " Insert a single row into table distributors, returning the sequence number generated by the DEFAULT clause: INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') RETURNING did; "
On Jan 11, 2008 4:23 AM, Daniel Caune <daniel.caune@ubisoft.com> wrote: Please ignore my post. I havent' read your message carefully enough.
> What about > $$ > INSERT INTO .... ; > select currval('seq_matchmaking_session_id'); > $$ language sql; > > ? Indeed... :-( For some reason, I thought that it was not possible to have to SQL statement in an SQL stored function. By the way, is there any performance difference between pure SQL and PL/pgSQL stored functions? If I remember correctly there was such a distinction between pure SQL statement and PL/PLSQL stored procedures (Oracle), in the sense that PL/PLSQL stored procedures are executed within the PL/PLSQL engine which sends pure SQL statements to the SQL engine for execution. There is a little overhead between PL/PLSQL and SQL engines. Regards, -- Daniel
Hello > By the way, is there any performance difference between pure SQL and > PL/pgSQL stored functions? If I remember correctly there was such a > distinction between pure SQL statement and PL/PLSQL stored procedures > (Oracle), in the sense that PL/PLSQL stored procedures are executed > within the PL/PLSQL engine which sends pure SQL statements to the SQL > engine for execution. There is a little overhead between PL/PLSQL and > SQL engines. > create or replace function test1(integer) returns integer as $$select $1;$$ language sql immutable; createor replace function test2(integer) returns integer as $$begin return $1; end$$ language plpgsql immutable; postgres=# select count(*) from (select test1(i) from generate_series(1,100000) g(i)) f;count --------100000 (1 row) Time: 123,532 ms postgres=# select count(*) from (select test2(i) from generate_series(1,100000) g(i)) f;count --------100000 (1 row) Time: 123,877 ms but if you forgot immutable postgres=# create or replace function test3(integer) returns integer as $$begin return $1; end$$ language plpgsql; CREATE FUNCTION Time: 430,258 ms postgres=# select count(*) from (select test3(i) from generate_series(1,100000) g(i)) f;count --------100000 (1 row) Time: 472,150 ms Regards Pavel Stehule
> What about > $$ > INSERT INTO .... ; > select currval('seq_matchmaking_session_id'); > $$ language sql; > > ? Hello, I'm not sure that this would return the correct id in case of concurrent calls to your function. I'm using following kind of function to manage reference tables: HTH, Marc Mamin CREATE TABLE xxx ( id serial NOT NULL, mycolumn character varying, CONSTRAINT xxx_pk PRIMARY KEY (id) , CONSTRAINT xxx_uk UNIQUE (mycolumn) ) CREATE OR REPLACE FUNCTION get_or_insert_id_xxx( input_value varchar) RETURNS INT AS $$ DECLARE id_value int; BEGIN select into id_value id from xxx where mycolumn = input_value; IF FOUND THEN return id_value; ELSE insert intoxxx ( mycolumn ) values ( input_value ); return id from xxx where mycolumn = input_value; END IF; EXCEPTION WHEN unique_violation THEN return id from xxx where mycolumn = input_value; END; $$ LANGUAGE plpgsql;