前端之家收集整理的这篇文章主要介绍了
postgresql-值表达式,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
聚集表达式 一个聚集表达式代表一个聚集函数对一个查询选出的行的处理。 一个聚集函数把多个输入缩减为一个输出值, 比如给输入求和或平均。一个聚集表达式的语法是下列之一: aggregate_name (expression) aggregate_name (ALL expression) aggregate_name (DISTINCT expression) aggregate_name ( * ) 这里 aggregate_name 是前面定义的聚集,(可能是全称), 而 expression 是一个本身不包含聚集表达式的任意值表达式。 第一种形式的聚集表达式为所有表达式生成非空值的输入行调用聚集。 (实际上,是否忽略空值由聚集函数决定 — 但是所有标准的聚集函数都忽略它们。) 第二种形式和第一种一样,因为 ALL 是缺省值。 第三种形式为所有输入行里找到表达式的所有唯一的非空值调用聚集。 最后一种形式为每个输入行(不管是空还是非空)调用一次聚集; 因为没有声明特定的输入值。通常它只是对 count() 聚集函数有用。 比如,count(*) 生成输入行的总数; count(f1) 生成 f1 为非空的输入行数; count(distinct f1) 生成 f1 唯一非空的行数。 预定义的聚集函数在 Section 9.15 里描述。 其它聚集函数可以由用户增加。 一个聚集表达式只能在 SELECT 命令的结果列表或者 HAVING 子句里出现。 禁止在其它子句里出现,比如 WHERE 里面,因为这些子句逻辑上在生成聚集结果之前计算。 如果一个聚集表达式出现在一个子查询里(参阅 Section 4.2.9 和 Section 9.16), 聚集通常是在子查询的行上进行计算。但是如果聚集的参数只包含外层查询的变量则有一个例外: 这个聚集会属于离他最近的外层查询,并且在该查询上进行计算。 该聚集表达式整体上属于它出现的子查询对外层查询的引用,其作用相当于子查询任何一次计算中的一个常量。 这个聚集表达式的有关只能出现在结果列或者 HAVING 子句的限制适用于聚集所属的查询层。 4.2.8. 类型转换 一个类型转换声明一个从一种数据类型到另外一种数据类型的转换。 Postgresql 接受两种等效的类型转换语法: CAST ( expression AS type ) expression::type CAST 语法遵循 sql;:: 的语法是 Postgresql 传统用法。 如果对一个已知类型的值表达式应用转换,它代表一个运行时类型转换。 只有在定义了合适的类型转换操作的情况下,该转换才能成功。 请注意这一点和用于常量的转换略有区别,如 Section 4.1.2.5 所示。 一个应用于某个未修饰的字串文本的转换表示给一个字串文本数值赋予一个初始化类型, 因此它对于任何类型都会成功(如果字串文本的内容符合该数据类型的输入语法接受。) 如果对于一个值表达式生成的数值对某类型而言不存在混淆的情况, 那么我们可以省略明确的类型转换(比如,在给一个表字段赋值的时候); 在这样的情况下,系统将自动附加一个类型转换。 不过,自动转换只适用于那些系统表中标记着 "OK to apply implicitly" 的转换函数。 其它转换函数必须用明确的转换语法调用。 这些限制是为了避免一些怪异的转换被应用。 我们也可以用函数样的语法声明一个类型转换: typename ( expression ) 不过,这个方法只能用于那些名字同时也是有效函数名字的类型。 比如,double precision 就不能这么用, 但是等效的 float8 可以。同样,interval, time,和 timestamp 如果加了双引号也只能这么用, 因为存在语法冲突。因此,函数样的类型转换会导致不一致, 所以可能应该避免在新应用中这么用。 (函数样语法实际上就似乎一个函数调用。如果使用两种标准转换语法做运行时转换, 那么它将在内部调用一个已注册得函数执行转换。通常, 这种转换函数和它们得输出类型同名,但是这个要点可不是那些可以移植的程序可以依赖的东西。) 4.2.9. 标量子查询 一个标量子查询是一个放在圆括弧里的普通 SELECT查询, 它只返回只有一个字段的一行。(参阅 Chapter 7 获取有关写查询的信息。) 该 SELECT 将被执行, 而其单个返回值将在周围的值表达式中使用。 把一个返回超过一行或者超过一列的查询用做标量查询是错误的。 (不过,在特定的执行中,子查询不返回行则不算错误;标量结果认为是NULL。) 该子查询可以引用周围查询的变量,那些变量也是在计算任意子查询的时候当做常量使用的。 又见 Section 9.16。 比如,下面的查询找出每个州中的最大人口数量的城市: SELECT name,(SELECT max(pop) FROM cities WHERE cities.state = states.name) FROM states; 4.2.10. 数组构造器 一个数组构造器是一个表达式,它从它的成员元素上构造一个数组值。 一个简单的数组构造器由关键字 ARRAY,一个左方括弧 [, 一个或多个表达式(用逗号分隔)表示数组元素值,以及最后一个右方括弧 ]。 比如 SELECT ARRAY[1,2,3+4]; array --------- {1,7} (1 row) 数组元素类型是成员表达式的公共类型,使用和 UNION 或 CASE 构造一样的规则决定。 (参阅 Section 10.5)。 多维数组值可以通过嵌套数组构造器的方法来制作。 在内层构造器里,关键字 ARRAY 可以省略。比如,下面的两句生成同样的结果: SELECT ARRAY[ARRAY[1,2],ARRAY[3,4]]; array --------------- {{1,2},{3,4}} (1 row) SELECT ARRAY[[1,[3,4}} (1 row) 因为多维数组必须是方形,同层的内层构造器必须生成同维的子数组。 多维数组构造器元素可以是任何生成合适数组的东西,而不仅仅是一个子 ARRAY 构造。 比如: CREATE TABLE arr(f1 int[],f2 int[]); INSERT INTO arr VALUES (ARRAY[[1,4]],ARRAY[[5,6],[7,8]]); SELECT ARRAY[f1,f2,'{{9,10},{11,12}}'::int[]] FROM arr; array ------------------------------------------------ {{{1,4}},{{5,6},{7,8}},{{9,12}}} (1 row) 我们也可以从一个子查询的结果中构造一个数组。在这种形式下, 数组构造器是用关键字 ARRAY 后面跟着一个用圆括弧(不是方括弧)包围的子查询。 比如: SELECT ARRAY(SELECT oid FROM pg_proc WHERE proname LIKE 'bytea%'); ?column? ------------------------------------------------------------- {2011,1954,1948,1952,1951,1244,1950,2005,1949,1953,2006,31} (1 row) 子查询必须返回一个字段。生成的一维数组将为子查询里每行结果生成一个元素, 元素类型匹配子查询的输出字段。 用 ARRAY 建立的数组值的脚标总是从一开始。 有关数组的更多信息,参阅 Section 8.10。 4.2.11. 行构造 一个行构造器是一个从提供给它的成员字段数值中制作行数值(也叫复合类型值)的表达式。 一个行构造器由关键字 ROW,一个左圆括弧, 零个或者多个用做行字段值的表达式(用逗号分隔),以及最后一个右圆括弧。比如, SELECT ROW(1,2.5,'this is a test'); 如果在列表里有多个表达式,那么关键字 ROW 是可选的。 缺省时,ROW 表达式创建的值是一个匿名的记录类型。如果必要,你可以把它转换成一个命名的复合类型 — 既可以是一个表的行类型,也可以是一个用 CREATE TYPE AS 创建的复合类型。 可能会需要一个明确的转换以避免歧义。比如: CREATE TABLE mytable(f1 int,f2 float,f3 text); CREATE FUNCTION getf1(mytable) RETURNS int AS 'SELECT $1.f1' LANGUAGE sql; -- 因为只有一个 getf1() 存在,所以不需要类型转换 SELECT getf1(ROW(1,'this is a test')); getf1 ------- 1 (1 row) CREATE TYPE myrowtype AS (f1 int,f2 text,f3 numeric); CREATE FUNCTION getf1(myrowtype) RETURNS int AS 'SELECT $1.f1' LANGUAGE sql; -- 现在我们需要类型转换以表明调用哪个函数: SELECT getf1(ROW(1,'this is a test')); ERROR: function getf1(record) is not unique SELECT getf1(ROW(1,'this is a test')::mytable); getf1 ------- 1 (1 row) SELECT getf1(CAST(ROW(11,'this is a test',2.5) AS myrowtype)); getf1 ------- 11 (1 row) 行构造器可以用于制作存储在复合类型表字段里面的复合类型值, 或者是传递给一个接受复合类型参数的函数。还有,我们也可以比较两个行数值或者用 IS NULL 或 IS NOT NULL 测试一个行数值,比如 SELECT ROW(1,'this is a test') = ROW(1,3,'not the same'); SELECT ROW(a,b,c) IS NOT NULL FROM table; 更多的细节,请参阅 Section 9.17。 行构造还可以用于连接子查询,这些在 Section 9.16 里面有详细讨论。 4.2.12. 表达式计算规则 子表达式的计算顺序是没有定义的。特别要指出的是, 一个操作符或者函数的输入并不一定是按照从左向右的顺序或者以某种特定的顺序进行计算的。 另外,如果一个表达式的结果可以通过只判断它的一部分就可以得到, 那么其它子表达式就可以完全不计算了。比如,如果我们这么写 SELECT true OR somefunc(); 那么 somefunc() 就(可能)根本不会被调用。 如果我们写下面的,也可能会是这样 SELECT somefunc() OR true; 请注意这里和某些编程语言里的从左向右"短路"是不一样的。 因此,拿那些有副作用的函数作为复杂表达式的一部分是不明智的选择。 在 WHERE 和 HAVING 子句里面依赖副作用或者是计算顺序是特别危险的, 因为这些子句都是作为生成一个执行规划的一部分进行了大量的再处理。 在这些子句里的布尔表达式(AND/OR/NOT 的组合)可以以布尔代数运算律允许的任意方式进行识别。 如果强制计算顺序非常重要,那么可以使用 CASE 构造(参阅 Section 9.13)。 比如,下面是一种视图避免在 WHERE 子句里被零除的不可信的方法: SELECT ... WHERE x <> 0 AND y/x > 1.5; 但是下面这样的是安全的: SELECT ... WHERE CASE WHEN x <> 0 THEN y/x > 1.5 ELSE false END; 用这种风格的 CASE 构造会阻止优化,因此应该只在必要的时候使用。 (在这个特殊的例子里,毫无疑问写成 y > 1.5*x 更好。) 原文链接:https://www.f2er.com/postgresql/196625.html