-- 因为只有一个 getf1() 存在,所以不需要类型转换 SELECT getf1(ROW(1,2.5,'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,2.5,'this is a test')); ERROR: function getf1(record) is not unique
SELECT getf1(ROW(1,2.5,'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,2.5,'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 更好。)
上一页 [1] [2] [3] [4] [5] [6] [7]
|