From 4e64e7f5638c2da3769db648408062085e9c43f2 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 7 Jan 2005 22:40:46 +0000 Subject: [PATCH] Improve discussion of SQL functions taking/returning row types. --- doc/src/sgml/xfunc.sgml | 122 ++++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 41 deletions(-) diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index dedf4d73f6..534ba4c08f 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1,5 +1,5 @@ @@ -111,6 +111,39 @@ $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.92 2004/12/30 21:45:37 tgl Exp $ void, the last statement must be a SELECT. + + Any collection of commands in the SQL + language can be packaged together and defined as a function. + Besides SELECT queries, the commands can include data + modification queries (INSERT, + UPDATE, and DELETE), as well as + other SQL commands. (The only exception is that you can't put + BEGIN, COMMIT, ROLLBACK, or + SAVEPOINT commands into a SQL function.) + However, the final command + must be a SELECT that returns whatever is + specified as the function's return type. Alternatively, if you + want to define a SQL function that performs actions but has no + useful value to return, you can define it as returning void. + In that case, the function body must not end with a SELECT. + For example, this function removes rows with negative salaries from + the emp table: + + +CREATE FUNCTION clean_emp() RETURNS void AS ' + DELETE FROM emp + WHERE salary < 0; +' LANGUAGE SQL; + +SELECT clean_emp(); + + clean_emp +----------- + +(1 row) + + + The syntax of the CREATE FUNCTION command requires the function body to be written as a string constant. It is usually @@ -219,35 +252,6 @@ $$ LANGUAGE SQL; which adjusts the balance and returns the new balance. - - - Any collection of commands in the SQL - language can be packaged together and defined as a function. - Besides SELECT queries, - the commands can include data modification (i.e., - INSERT, UPDATE, and - DELETE). However, the final command - must be a SELECT that returns whatever is - specified as the function's return type. Alternatively, if you - want to define a SQL function that performs actions but has no - useful value to return, you can define it as returning void. - In that case, the function body must not end with a SELECT. - For example: - - -CREATE FUNCTION clean_emp() RETURNS void AS $$ - DELETE FROM emp - WHERE salary <= 0; -$$ LANGUAGE SQL; - -SELECT clean_emp(); - - clean_emp ------------ - -(1 row) - - @@ -282,7 +286,7 @@ SELECT name, double_salary(emp.*) AS dream name | dream ------+------- - Sam | 2400 + Bill | 8400 @@ -307,7 +311,7 @@ SELECT name, double_salary(emp) AS dream on-the-fly. This can be done with the ROW construct. For example, we could adjust the data being passed to the function: -SELECT name, double_salary(row(name, salary*1.1, age, cubicle)) AS dream +SELECT name, double_salary(ROW(name, salary*1.1, age, cubicle)) AS dream FROM emp; @@ -320,7 +324,7 @@ SELECT name, double_salary(row(name, salary*1.1, age, cubicle)) AS dream CREATE FUNCTION new_emp() RETURNS emp AS $$ SELECT text 'None' AS name, - 1000 AS salary, + 1000.0 AS salary, 25 AS age, point '(2,2)' AS cubicle; $$ LANGUAGE SQL; @@ -358,9 +362,46 @@ ERROR: function declared to return emp returns varchar instead of text at colum - When you call a function that returns a row (composite type) in a - SQL expression, you might want only one field (attribute) from its - result. You can do that with syntax like this: + A different way to define the same function is: + + +CREATE FUNCTION new_emp() RETURNS emp AS $$ + SELECT ROW('None', 1000.0, 25, '(2,2)')::emp; +$$ LANGUAGE SQL; + + + Here we wrote a SELECT that returns just a single + column of the correct composite type. This isn't really better + in this situation, but it is a handy alternative in some cases + — for example, if we need to compute the result by calling + another function that returns the desired composite value. + + + + We could call this function directly in either of two ways: + + +SELECT new_emp(); + + new_emp +-------------------------- + (None,1000.0,25,"(2,2)") + +SELECT * FROM new_emp(); + + name | salary | age | cubicle +------+--------+-----+--------- + None | 1000.0 | 25 | (2,2) + + + The second way is described more fully in . + + + + When you use a function that returns a composite type, + you might want only one field (attribute) from its result. + You can do that with syntax like this: SELECT (new_emp()).name; @@ -398,15 +439,14 @@ SELECT name(new_emp()); -- This is the same as: --- SELECT emp.name AS youngster FROM emp WHERE emp.age < 30 +-- SELECT emp.name AS youngster FROM emp WHERE emp.age < 30; -SELECT name(emp) AS youngster - FROM emp - WHERE age(emp) < 30; +SELECT name(emp) AS youngster FROM emp WHERE age(emp) < 30; youngster ----------- Sam + Andy @@ -433,7 +473,7 @@ SELECT getname(new_emp()); - + <acronym>SQL</acronym> Functions as Table Sources -- GitLab