# 38.5.查询语言(SQL)函数

38.5.1. SQL函数的参数

38.5.2. 基于基类型的SQL函数

38.5.3. 复合类型上的SQL函数

38.5.4. 带有输出参数的SQL函数

38.5.5. 带有输出参数的SQL过程

38.5.6. 参数个数可变的SQL函数

38.5.7. 参数为默认值的SQL函数

38.5.8. SQL用作表源

38.5.9. 返回集合的SQL函数

38.5.10. SQL函数返回桌子

38.5.11. 多态SQL函数

38.5.12. 带有排序规则的SQL函数

SQL函数执行任意SQL语句列表,返回列表中最后一个查询的结果。在简单(非集合)情况下,将返回最后一个查询结果的第一行。(请记住,除非使用订购人。如果上一个查询恰好没有返回任何行,则将返回空值。

或者,可以通过将函数的返回类型指定为一套*某种类型的*,或相当于宣布其为返回表(**)。在这种情况下,将返回最后一个查询结果的所有行。更多细节见下文。

SQL函数体必须是由分号分隔的SQL语句列表。最后一条语句后面的分号是可选的。除非函数被声明为返回无效的,最后一个语句必须是选择,或插入, 使现代化删去这有一个返回条款

SQL语言中的任何命令集合都可以打包在一起并定义为函数。此外选择查询,这些命令可以包括数据修改查询(插入, 使现代化删去),以及其他SQL命令。(不能使用事务控制命令,例如。,犯罪, 保存点,以及一些实用程序命令,例如。,真空,在SQL函数中。)然而,最后的命令必须是选择或者有一个返回子句,返回指定为函数返回类型的任何内容。或者,如果您想定义一个执行操作但没有有用值可返回的SQL函数,可以将其定义为返回无效的。例如,此函数从列表中删除薪资为负的行电磁脉冲表:

CREATE FUNCTION clean_emp() RETURNS void AS '
    DELETE FROM emp
        WHERE salary < 0;
' LANGUAGE SQL;

SELECT clean_emp();

 clean_emp
### Note

 The entire body of an SQL function is parsed before any of it is executed. While an SQL function can contain commands that alter the system catalogs (e.g., `CREATE TABLE`), the effects of such commands will not be visible during parse analysis of later commands in the function. Thus, for example, `CREATE TABLE foo (...); INSERT INTO foo VALUES(...);` will not work as desired if packaged up into a single SQL function, since `foo` won't exist yet when the `INSERT` command is parsed. It's recommended to use PL/pgSQL instead of an SQL function in this type of situation.

 The syntax of the `CREATE FUNCTION` command requires the function body to be written as a string constant. It is usually most convenient to use dollar quoting (see [Section 4.1.2.4](sql-syntax-lexical.html#SQL-SYNTAX-DOLLAR-QUOTING)) for the string constant. If you choose to use regular single-quoted string constant syntax, you must double single quote marks (`'`) and backslashes (`\`) (assuming escape string syntax) in the body of the function (see [Section 4.1.2.1](sql-syntax-lexical.html#SQL-SYNTAX-STRINGS)).

### 38.5.1. Arguments for SQL Functions

[]()

 Arguments of an SQL function can be referenced in the function body using either names or numbers. Examples of both methods appear below.

 To use a name, declare the function argument as having a name, and then just write that name in the function body. If the argument name is the same as any column name in the current SQL command within the function, the column name will take precedence. To override this, qualify the argument name with the name of the function itself, that is `*`function_name`*.*`argument_name`*`. (If this would conflict with a qualified column name, again the column name wins. You can avoid the ambiguity by choosing a different alias for the table within the SQL command.)

 In the older numeric approach, arguments are referenced using the syntax `$*`n`*`: `$1` refers to the first input argument, `$2` to the second, and so on. This will work whether or not the particular argument was declared with a name.

 If an argument is of a composite type, then the dot notation, e.g., `*`argname`*.*`fieldname`*` or `$1.*`fieldname`*`, can be used to access attributes of the argument. Again, you might need to qualify the argument's name with the function name to make the form with an argument name unambiguous.

 SQL function arguments can only be used as data values, not as identifiers. Thus for example this is reasonable:

插入mytable值($1);

but this will not work:

插入1美元价值(42);

### Note

 The ability to use names to reference SQL function arguments was added in PostgreSQL 9.2. Functions to be used in older servers must use the `$*`n`*` notation.

### 38.5.2. SQL Functions on Base Types

 The simplest possible SQL function has no arguments and simply returns a base type, such as `integer`:

CREATE FUNCTION one()返回整数作为$$SELECT 1作为结果;$$语言SQL;

--字符串文本的替代语法:CREATE FUNCTION one()将整数返回为“SELECT 1 AS result;”语言SQL;

选择一个();

# 38.5.3.复合类型上的SQL函数

在使用复合类型的参数编写函数时,我们不仅必须指定所需的参数,还必须指定该参数所需的属性(字段)。例如,假设电磁脉冲是一个包含员工数据的表,因此也是表中每一行的复合类型的名称。这里有一个函数双薪这就计算出如果一个人的工资翻了一番,他的工资会是多少:

CREATE TABLE emp (
    name        text,
    salary      numeric,
    age         integer,
    cubicle     point
);

INSERT INTO emp VALUES ('Bill', 4200, 45, '(2,1)');

CREATE FUNCTION double_salary(emp) RETURNS numeric AS $$
    SELECT $1.salary * 2 AS salary;
$$ LANGUAGE SQL;

SELECT name, double_salary(emp.*) AS dream
    FROM emp
    WHERE emp.cubicle ~= point '(2,1)';

 name | dream
### 38.5.4. SQL Functions with Output Parameters

[]()

 An alternative way of describing a function's results is to define it with *output parameters*, as in this example:

创建函数add_em(IN x int,IN y int,OUT sum int)作为'SELECT x+y'语言SQL;

选择add_em(3,7);加上

# 38.5.5.带有输出参数的SQL过程

过程中也支持输出参数,但它们的工作方式与函数略有不同。在里面呼叫命令、输出参数必须包含在参数列表中。例如,早期的银行账户借记例程可以这样编写:

CREATE PROCEDURE tp1 (accountno integer, debit numeric, OUT new_balance numeric) AS $$
    UPDATE bank
        SET balance = balance - debit
        WHERE accountno = tp1.accountno
    RETURNING balance;
$$ LANGUAGE SQL;

要调用此过程,需要一个与出来参数必须包含在内。写作是一种习惯无效的:

CALL tp1(17, 100.0, NULL);

如果您编写了其他内容,则它必须是一个可隐式强制为参数的声明类型的表达式,就像输入参数一样。但是请注意,这样的表达式不会被计算。

从PL/pgSQL调用过程时,而不是编写无效的必须编写一个变量来接收过程的输出。看见第43.6.3节详细信息。

# 38.5.6.参数个数可变的SQL函数

只要所有“可选”参数都是相同的数据类型,SQL函数可以声明为接受可变数量的参数。可选参数将作为数组传递给函数。通过将最后一个参数标记为可变的; 此参数必须声明为数组类型。例如:

CREATE FUNCTION mleast(VARIADIC arr numeric[]) RETURNS numeric AS $$
    SELECT min($1[i]) FROM generate_subscripts($1, 1) g(i);
$$ LANGUAGE SQL;

SELECT mleast(10, -1, 5, 4.4);
 mleast
### 38.5.7. SQL Functions with Default Values for Arguments

[]()

 Functions can be declared with default values for some or all input arguments. The default values are inserted whenever the function is called with insufficiently many actual arguments. Since arguments can only be omitted from the end of the actual argument list, all parameters after a parameter with a default value have to have default values as well. (Although the use of named argument notation could allow this restriction to be relaxed, it's still enforced so that positional argument notation works sensibly.) Whether or not you use it, this capability creates a need for precautions when calling functions in databases where some users mistrust other users; see [Section 10.3](typeconv-func.html).

 For example:

CREATE函数foo(a int,b int DEFAULT 2,c int DEFAULT 3)将int语言SQL返回为$$SELECT$1+$2+$3;$$;

选择foo(10,20,30);福

# 38.5.8.SQL用作表源

所有SQL函数都可以在从…起子句,但它对于返回复合类型的函数特别有用。如果函数被定义为返回基类型,则table函数将生成一个单列表。如果函数被定义为返回复合类型,则table函数会为复合类型的每个属性生成一列。

下面是一个例子:

CREATE TABLE foo (fooid int, foosubid int, fooname text);
INSERT INTO foo VALUES (1, 1, 'Joe');
INSERT INTO foo VALUES (1, 2, 'Ed');
INSERT INTO foo VALUES (2, 1, 'Mary');

CREATE FUNCTION getfoo(int) RETURNS foo AS $$
    SELECT * FROM foo WHERE fooid = $1;
$$ LANGUAGE SQL;

SELECT *, upper(fooname) FROM getfoo(1) AS t1;

 fooid | foosubid | fooname | upper
### 38.5.9. SQL Functions Returning Sets

[]()

 When an SQL function is declared as returning `SETOF *`sometype`*`, the function's final query is executed to completion, and each row it outputs is returned as an element of the result set.

 This feature is normally used when calling the function in the `FROM` clause. In this case each row returned by the function becomes a row of the table seen by the query. For example, assume that table `foo` has the same contents as above, and we say:

CREATE函数getfoo(int)将foo集合作为$$SELECT*从foo返回,其中fooid=$1;$$语言SQL;

从getfoo(1)中选择*作为t1;

 Then we would get:

fooid | foosubid | fooname

# 笔记

如果函数的最后一个命令是插入, 使现代化删去具有返回,该命令将始终执行到完成,即使函数没有用一套或者调用查询没有获取所有结果行。程序生成的任何额外行返回子句被悄悄地删除,但命令的表修改仍然发生(并且在从函数返回之前都已完成)。

# 笔记

在PostgreSQL 10之前,在同一个选择列表中放置多个集合返回函数的行为并不明智,除非它们总是产生相同数量的行。否则,得到的输出行数等于集合返回函数生成的行数的最小公倍数。此外,嵌套的集合返回函数也没有如上所述工作;相反,一个集合返回函数最多只能有一个集合返回参数,并且集合返回函数的每个嵌套都是独立运行的。此外,条件执行(在内部设置返回函数)案例等),使事情变得更加复杂。使用侧面的在编写需要在较旧的PostgreSQL版本中工作的查询时,建议使用语法,因为这将在不同版本中提供一致的结果。如果查询依赖于集合返回函数的条件执行,则可以通过将条件测试移动到自定义集合返回函数中来修复它。例如

SELECT x, CASE WHEN y > 0 THEN generate_series(1, z) ELSE 5 END FROM tab;

可能成为

CREATE FUNCTION case_generate_series(cond bool, start int, fin int, els int)
  RETURNS SETOF int AS $$
BEGIN
  IF cond THEN
    RETURN QUERY SELECT generate_series(start, fin);
  ELSE
    RETURN QUERY SELECT els;
  END IF;
END$$ LANGUAGE plpgsql;

SELECT x, case_generate_series(y > 0, 1, z, 5) FROM tab;

此公式在所有版本的PostgreSQL中都适用。

# 38.5.10.SQL函数返回桌子

还有另一种方法可以将函数声明为返回集合,即使用语法返回表(**).这相当于使用一个或多个出来参数加上将函数标记为返回一套记录(或一套单个输出参数的类型(视情况而定)。SQL标准的最新版本中指定了这种表示法,因此可能比使用一套.

例如,前面的求和和和积示例也可以这样做:

CREATE FUNCTION sum_n_product_with_tab (x int)
RETURNS TABLE(sum int, product int) AS $$
    SELECT $1 + tab.y, $1 * tab.y FROM tab;
$$ LANGUAGE SQL;

不允许使用显式出来伊努特参数与返回表符号-必须将所有输出列放入桌子列表

# 38.5.11.多态SQL函数

SQL函数可以声明为接受和返回中描述的多态类型第38.2.5节这是一个多态函数制作数组从两个任意数据类型元素构建数组:

CREATE FUNCTION make_array(anyelement, anyelement) RETURNS anyarray AS $$
    SELECT ARRAY[$1, $2];
$$ LANGUAGE SQL;

SELECT make_array(1, 2) AS intarray, make_array('a'::text, 'b') AS textarray;
 intarray | textarray
### 38.5.12. SQL Functions with Collations

[]()

 When an SQL function has one or more parameters of collatable data types, a collation is identified for each function call depending on the collations assigned to the actual arguments, as described in [Section 24.2](collation.html). If a collation is successfully identified (i.e., there are no conflicts of implicit collations among the arguments) then all the collatable parameters are treated as having that collation implicitly. This will affect the behavior of collation-sensitive operations within the function. For example, using the `anyleast` function described above, the result of

选择任意一个('abc'::文本,'abc');

 will depend on the database's default collation. In `C` locale the result will be `ABC`, but in many other locales it will be `abc`. The collation to use can be forced by adding a `COLLATE` clause to any of the arguments, for example

选择任意一个('abc'::文本,'abc'校对“C”);

 Alternatively, if you wish a function to operate with a particular collation regardless of what it is called with, insert `COLLATE` clauses as needed in the function definition. This version of `anyleast` would always use `en_US` locale to compare strings:

创建函数anyleast(VARIADIC anyarray)将anyelement作为$$SELECT min($1)返回[我]从generate_subscripts($1,1)g(i);$语言SQL;

 But note that this will throw an error if applied to a non-collatable data type.

 If no common collation can be identified among the actual arguments, then an SQL function treats its parameters as having their data types' default collation (which is usually the database's default collation, but could be different for parameters of domain types).

 The behavior of collatable parameters can be thought of as a limited form of polymorphism, applicable only to textual data types.