函数和操作符
1. 概述
UXsinoDB提供了大量的内置数据类型的函数和操作符。本章描述了大部分,尽管其他特殊用途的函数出现在手册的相关部分。用户也可以定义自己的函数和操作符。
本章中用于描述函数或操作符的参数和结果数据类型的符号如下:
repeat (text, integer ) → text
上述示例说明函数 repeat 接受一个文本和一个整数参数,并返回一个文本类型的结果。右箭头也用于指示示例的结果,如下所示:
repeat('Ux', 4) → UxUxUxUx
如果您关心可移植性,那么请注意本章中描述的大多数函数和操作符,除了最普通的算术和比较操作符以及一些显式标记的函数之外,都没有被 SQL 标准指定。其他 SQL 数据库管理系统中也存在这种扩展功能,在许多情况下,这种功能在各种实现之间是兼容和一致的。
2. 逻辑操作符
通常的逻辑操作符如下:
boolean AND boolean → boolean
boolean OR boolean → boolean
NOT boolean → boolean
SQL 使用三值逻辑系统,包括真、假和 null,表示“未知”。请参阅以下真值表:
| a | b | a AND b | a OR b |
|---|---|---|---|
| TRUE | TRUE | TRUE | TRUE |
| TRUE | FALSE | FALSE | TRUE |
| TRUE | NULL | NULL | TRUE |
| FALSE | FALSE | FALSE | FALSE |
| FALSE | NULL | FALSE | NULL |
| NULL | NULL | NULL | NULL |
| a | NOT a |
|---|---|
| TRUE | FALSE |
| FALSE | TRUE |
| NULL | NULL |
操作符 AND 和 OR 是可交换的,也就是说,你可以交换左右操作数而不影响结果。(然而,并不能保证左操作数在右操作数之前被评估。)
3. 比较函数和操作符
通常的比较操作符都可用,如表 比较操作符所示。
| 操作符 | 描述 |
|---|---|
datatype < datatype → boolean | 小于 |
datatype > datatype → boolean | 大于 |
datatype <= datatype → boolean | 小于等于 |
datatype >= datatype → boolean | 大于等于 |
datatype = datatype → boolean | 等于 |
datatype <> datatype → boolean | 不等于 |
datatype != datatype → boolean | 不等于 |
datatype ^= datatype → boolean | 不等于 |
注意
<>是标准SQL表示“不等于”的符号,而!=是 UXsinoDB 的扩展。“等于”操作符是=,不等于操作符是<>,它是!=的别名,在解析的早期阶段就被转换为<>。因此,无法实现执行不同操作的!=和<>操作符。
支持部分多符号操作符中间存在空白(空格或者换行或者制表符,一个或者多个),后续处理中数据库会忽略掉中间的空白。
这些比较操作符适用于所有具有自然排序的内置数据类型,包括数字、字符串和日期/时间类型。此外,如果它们的组件数据类型是可比较的,那么可以比较数组、复合类型和范围。
通常也可以比较相关数据类型的值;例如,integer > bigint 是可行的。这种情况的某些情况是由“跨类型”比较操作符直接实现的,但如果没有这样的操作符,则解析器将强制将较不一般的类型转换为较一般的类型,并应用后者的比较操作符。
支持与 - 或者 + 连用,例如 !=-、!=+、^=-、^=+、>=+ 等。示例如下。
select 1!=-1;
?column?
----------
t
(1 row)
select 1!=+1;
?column?
----------
f
(1 row)
select 1^=-1;
?column?
----------
t
(1 row)
select 1^=+1;
?column?
----------
f
(1 row)
如上所示,所有比较操作符都是返回 boolean 类型的二元操作符。因此,像 1 < 2 < 3 这样的表达式是无效的(因为没有 < 操作符将布尔值与 3 进行比较)。使用下面显示的 BETWEEN 谓词执行范围测试。
还有一些比较谓词,如表 比较谓词所示。它们的行为很像操作符,但具有SQL标准规定的特殊语法。
| 谓词 / 描述 / 示例 | 描述 | 示例 |
|---|---|---|
datatype BETWEEN datatype AND datatype → boolean | 在范围内(包括范围端点)。 | 2 BETWEEN 1 AND 3 → t2 BETWEEN 3 AND 1 → f |
datatype NOT BETWEEN datatype AND datatype → boolean | 不在范围内(BETWEEN 的否定)。 | 2 NOT BETWEEN 1 AND 3 → f |
datatype BETWEEN SYMMETRIC datatype AND datatype → boolean | 在排序两个端点值之后的范围内。 | 2 BETWEEN SYMMETRIC 3 AND 1 → t |
datatype NOT BETWEEN SYMMETRIC datatype AND datatype → boolean | 不在两个端点值排序后的范围内。 | 2 NOT BETWEEN SYMMETRIC 3 AND 1 → f |
datatype IS DISTINCT FROM datatype → boolean | 不相等,将 null 视为可比较的值。 | 1 IS DISTINCT FROM NULL → t(而不是 NULL)NULL IS DISTINCT FROM NULL → f(而不是 NULL) |
datatype IS NOT DISTINCT FROM datatype → boolean | 相等,将 null 视为可比较的值。 | 1 IS NOT DISTINCT FROM NULL → f(而不是 NULL)NULL IS NOT DISTINCT FROM NULL → t(而不是 NULL) |
datatype IS NULL → boolean | 测试值是否为 null。 | 1.5 IS NULL → f |
datatype IS NOT NULL → boolean | 测试值是否不为 null。 | 'null' IS NOT NULL → t |
datatype ISNULL → boolean | 测试值是否为 null(非标准语法)。 | |
datatype NOTNULL → boolean | 测试值是否不为 null(非标准语法)。 | |
boolean IS TRUE → boolean | 测试布尔表达式是否为 true。 | true IS TRUE → tNULL::boolean IS TRUE → f(而不是 NULL) |
boolean IS NOT TRUE → boolean | 测试布尔表达式是否为 false 或未知。 | true IS NOT TRUE → fNULL::boolean IS NOT TRUE → t(而不是 NULL) |
boolean IS FALSE → boolean | 测试布尔表达式是否为假。 | true IS FALSE → fNULL::boolean IS FALSE → f(而不是 NULL) |
boolean IS NOT FALSE → boolean | 测试布尔表达式是否为真或未知。 | true IS NOT FALSE → tNULL::boolean IS NOT FALSE → t(而不是 NULL) |
boolean IS UNKNOWN → boolean | 测试布尔表达式是否为未知。 | true IS UNKNOWN → fNULL::boolean IS UNKNOWN → t(而不是 NULL) |
boolean IS NOT UNKNOWN → boolean | 测试布尔表达式是否为真或假。 | true IS NOT UNKNOWN → tNULL::boolean IS NOT UNKNOWN → f(而不是 NULL) |
BETWEEN 谓词简化了范围测试:
a BETWEEN x AND y
等价于
a >= x AND a <= y
请注意,BETWEEN 将端点值视为包含在范围内。BETWEEN SYMMETRIC 与 BETWEEN 类似,除了没有要求左侧的参数小于或等于右侧的参数。如果不是,则自动交换这两个参数,以便始终隐含非空范围。
各种 BETWEEN 变体是基于普通比较操作符实现的,因此适用于任何可比较的数据类型。
注意
BETWEEN语法中使用AND会产生歧义,与逻辑操作符AND的使用产生歧义。为了解决这个问题,只允许有限的表达式类型作为BETWEEN子句的第二个参数。如果需要在BETWEEN中编写更复杂的子表达式,请在子表达式周围加括号。
普通比较操作符在任一输入为 null 时产生 null(表示“未知”),而不是 true 或 false。例如,7 = NULL 产生 null,7 <> NULL 也是如此。当此行为不合适时,请使用 IS [ NOT ] DISTINCT FROM 谓词:
a IS DISTINCT FROM b
a IS NOT DISTINCT FROM b
对于非空输入,IS DISTINCT FROM 等同于 <> 操作符。但是,如果两个输入都是 null,则返回 false,如果只有一个输入为 null,则返回 true。同样,IS NOT DISTINCT FROM 对于非空输入与 = 相同,但当两个输入都为 null 时返回 true,只有一个输入为 null 时返回 false。因此,这些谓词实际上表现得好像 null 是一个正常的数据值,而不是“未知”。
要检查一个值是否为 null,请使用以下谓词:
expression IS NULL
expression IS NOT NULL
或等效但非标准的谓词:
expression ISNULL
expression NOTNULL
不要写成 expression = NULL,因为 NULL 不等于 “等于” NULL。(null 值表示未知值,不知道两个未知值是否相等。)
提示
有些应用程序可能期望expression = NULL在expression评估为 null 值时返回 true。强烈建议修改这些应用程序以符合 SQL 标准。但是,如果无法这样做,则可以使用transform_null_equals配置变量。如果启用了它,UXsinoDB 将把x = NULL子句转换为x IS NULL。
如果 expression 是行值,则当行表达式本身为 null 或所有行字段都为 null 时,IS NULL 为 true,而当行表达式本身为非 null 且所有行字段都为非 null 时,IS NOT NULL 为 true。由于这种行为,IS NULL 和 IS NOT NULL 并不总是对行值表达式返回相反的结果;特别是,包含 null 和非 null 字段的行值表达式将对两个测试都返回 false。在某些情况下,最好编写 row IS DISTINCT FROM NULL 或 row IS NOT DISTINCT FROM NULL,这将仅检查整个行值是否为 null,而不进行任何其他行字段的测试。
布尔值也可以使用以下谓词进行测试:
boolean_expression IS TRUE
boolean_expression IS NOT TRUE
boolean_expression IS FALSE
boolean_expression IS NOT FALSE
boolean_expression IS UNKNOWN
boolean_expression IS NOT UNKNOWN
这些函数总是返回 true 或 false,即使操作数为 null 时也不会返回 null 值。null 输入被视为逻辑值“unknown”。请注意,IS UNKNOWN 和 IS NOT UNKNOWN 实际上与 IS NULL 和 IS NOT NULL 相同,只是输入表达式必须是布尔类型。
还有一些比较相关的函数,如表 比较函数所示。
| 函数 | 描述 | 示例 |
|---|---|---|
num_nonnulls ( VARIADIC "any" ) → integer | 返回非空参数的数量。 | num_nonnulls(1, NULL, 2) → 2 |
num_nulls ( VARIADIC "any" ) → integer | 返回空参数的数量。 | num_nulls(1, NULL, 2) → 1 |
3.1. INTERVAL()
-
功能
INTERVAL(N, N1, N2, N3...)函数可以返回 N 在后续输入数列中的位置。 -
函数
INTERVAL(N, N1, N2, N3...)如果 N < N1,则返回 0,如果 N1 <= N < N2,则返回 1,如果 N2 <= N < N3,则返回 2。以此类推,至少输入 2 个参数,区间是前闭后开的,对于输入个数少于 8 时逐一比较,大于 8 时使用二分查找算法比较。该函数仅在 mysql 兼容模式支持。
-
示例
-
比较结果
select interval(2.3, 1, 2, 3, 4); interval_function ------------------- 2 -
开头数字为 null 时,返回 -1
select interval(null, 2, 1, 3, 4); interval_function ------------------- -1 -
输入数据,null 在被比较数据中作为最小值
select interval(-23544365472.3, null, 1, 2.2, 4); interval_function ------------------- 1 -
接受表达式的输入
select interval(3-2, 1, 1+1, 4); interval_function ------------------- 1
-
4. 数学函数和操作符
许多 UXsinoDB 类型都提供了数学操作符。对于没有标准数学约定的类型(例如日期/时间类型),在后续章节中描述实际行为。
表 数学操作符显示了标准数值类型可用的数学操作符。除非另有说明,以 numeric_type 为参数的操作符可用于所有类型 smallint、integer、bigint、numeric、real 和 double precision。以 integral_type 为参数的操作符可用于类型 smallint、integer 和 bigint。除非另有说明,每种操作符形式返回与其参数相同的数据类型。涉及多个参数数据类型的调用(例如 integer + numeric)将使用这些列表中后面出现的类型进行解析。
| 操作符 | 说明 | 示例 |
|---|---|---|
numeric_type + numeric_type → numeric_type | 加法 | 2 + 3 → 5 |
+ numeric_type → numeric_type | 一元加(无操作) | + 3.5 → 3.5 |
numeric_type - numeric_type → numeric_type | 减法 | 2 - 3 → -1 |
- numeric_type → numeric_type | 否定 | - (-4) → 4 |
numeric_type * numeric_type → numeric_type | 乘法 | 2 * 3 → 6 |
numeric_type / numeric_type → numeric_type | 除法(对于整数类型,除法将结果截断为零) | 5.0 / 2 → 2.50000000000000005 / 2 → 2(-5) / 2 → -2 |
numeric_type % numeric_type → numeric_type | 模数(余数);适用于 smallint、integer、bigint 和 numeric | 5 % 4 → 1 |
numeric ^ numeric → numericdouble precision ^ double precision → double precision | 指数 与典型的数学实践不同,默认情况下,多次使用 ^ 将从左到右关联: | 2 ^ 3 → 82 ^ 3 ^ 3 → 5122 ^ (3 ^ 3) → 134217728 |
|/ double precision → double precision | 平方根 | |/ 25.0 → 5 |
||/ double precision → double precision | 立方根 | ||/ 64.0 → 4 |
@ numeric_type → numeric_type | 绝对值 | @ -5.0 → 5.0 |
integral_type & integral_type → integral_type | 按位与 | 91 & 15 → 11 |
integral_type | integral_type → integral_type | 按位或 | 32 | 3 → 35 |
integral_type # integral_type → integral_type | 按位异或 | 17 # 5 → 20 |
~ integral_type → integral_type | 按位取反 | ~1 → -2 |
integral_type << integer → integral_type | 按位左移 | 1 << 4 → 16 |
integral_type >> integer → integral_type | 按位右移 | 8 >> 2 → 2 |
! numeric_type → boolean | 一元取反,每两个连续 ! 为一组(一个 ! 与两个 ! 效果相同),识别为一次取反,即三个 ! 与四个 ! 的效果相同,都是取两次反,以此类推。注:若 ! 之间存在空格分隔,那么分别计数 ! 的数量得出取反的效果,再进行组合得到最终结果 | !5 → f!!5 → f!!!5 → t!!!!5 → t! !5 → t |
表 数学函数显示了可用的数学函数。其中许多函数提供了多种不同的参数类型。除非另有说明,函数的任何给定形式都返回与其参数相同的数据类型;交叉类型的情况解决方式与上述操作符相同。与 double precision 数据一起工作的函数大多是在主机系统的 C 库之上实现的;因此,精度和边界情况下的行为可能因主机系统而异。
| 函数 | 描述 | 示例 |
|---|---|---|
abs ( numeric_type ) → numeric_type | 绝对值 | abs(-17.4) → 17.4 |
cbrt ( double precision ) → double precision | 立方根 | cbrt(64.0) → 4 |
ceil ( numeric ) → numericceil ( double precision ) → double precision | 大于等于参数的最小整数 | ceil(42.2) → 43ceil(-42.8) → -42 |
ceiling ( numeric ) → numericceiling ( double precision ) → double precision | 大于等于参数的最小整数(与 ceil 相同) | ceiling(95.3) → 96 |
degrees ( double precision ) → double precision | 将弧度转换为角度 | degrees(0.5) → 28.64788975654116 |
div ( y numeric, x numeric ) → numeric | y / x 的整数商(向零截断) | div(9, 4) → 2 |
exp ( numeric ) → numericexp ( double precision ) → double precision | 指数(e 的给定幂次方) | exp(1.0) → 2.7182818284590452 |
factorial ( bigint ) → numeric | 阶乘 | factorial(5) → 120 |
floor ( numeric ) → numericfloor ( double precision ) → double precision | 小于或等于参数的最小整数 | floor(42.8) → 42floor(-42.8) → -43 |
gcd ( numeric_type, numeric_type ) → numeric_type | 返回 0,如果两个输入都为零,返回 0,可用于 integer、bigint 和 numeric | gcd(1071, 462) → 21 |
lcm ( numeric_type, numeric_type ) → numeric_type | 最小公倍数(两个输入的整数倍的最小严格正数);如果其中一个输入为零,返回 0;可用于 integer、bigint 和 numeric | lcm(1071, 462) → 23562 |
ln ( numeric ) → numericln ( double precision ) → double precision | 自然对数 | ln(2.0) → 0.6931471805599453 |
log ( numeric ) → numericlog ( double precision ) → double precision | 10 进制对数 | log(100) → 2 |
log10 ( numeric ) → numericlog10 ( double precision ) → double precision | 以 10 为底的对数(与 log 相同) | log10(1000) → 3 |
log ( b numeric, x numeric ) → numeric | x 的对数到基数 b | log(2.0, 64.0) → 6.0000000000000000 |
min_scale ( numeric ) → integer | 精确表示所提供的值所需的最小小数位数(小数位数) | min_scale(8.4100) → 2 |
mod ( y numeric_type, x numeric_type ) → numeric_type | Y/x 的余数;可用于 smallint、integer、bigint 和 numeric | mod(9, 4) → 1 |
pi () → double precision | π 的近似值 | pi() → 3.141592653589793 |
power ( a numeric, b numeric ) → numericpower ( a double precision, b double precision ) → double precision | a 的 b 次方 | power(9, 3) → 729 |
radians ( double precision ) → double precision | 将度数转换为弧度 | radians(45.0) → 0.7853981633974483 |
round ( numeric ) → numericround ( double precision ) → double precision | 四舍五入到最接近的整数。对于 numeric,平局是从零舍入而打破的。对于 double precision,打结行为是平台相关的,但“圆至最接近偶数”是最常见的规则。 | round(42.4) → 42 |
round ( v numeric, s integer ) → numeric | 将 source 四舍五入到小数点右侧第 n 位。如果 n 是负数则 round 到小数点左侧。若忽略 n 则 round 到个位,等同于 round(source,0),若 n 是小数,则舍去小数位。 source 可支持以下类型:smallint,integer,bigint,double precision,numeric,real,float,text,char,nchar,varchar,varchar2,nvarchar2。 | select round(12.3456::double, '1.2'::varchar); → 12.3 |
round ( source, [n] ) → numeric | 四舍五入到小数点后的位置。从零开始四舍五入打破平局。 | round(42.4382, 2) → 42.44 |
scale ( numeric ) → numeric | 参数的小数位数(小数部分的位数)。 | scale(8.4100) → 4 |
sign ( numeric ) → numericsign ( double precision ) → double precision | 参数的符号(-1、0 或 +1)。 | sign(-8.4) → -1 |
sqrt ( numeric ) → numericsqrt ( double precision ) → double precision | 平方根。 | sqrt(2) → 1.4142135623730951 |
trim_scale ( numeric ) → numeric | 通过删除尾随的零,将值的小数位数(小数部分的位数)减少。 | trim_scale(8.4100) → 8.41 |
trunc ( numeric ) → numerictrunc ( double precision ) → double precision | 截断为整数(朝向零)。 | trunc(42.8) → 42trunc(-42.8) → -42 |
trunc ( v numeric, s integer ) → numeric | 将 v 截断为 s 位小数。 | trunc(42.4382, 2) → 42.43 |
trunc ( text ) → text | 对函数数值或者时间类型格式的字符串截取,优先选择字符串为数值,其次按照 dd 截取时间,否则报错。 | trunc('2021-02-05 12:12:12'); → 2021-02-05 00:00:00 |
width_bucket ( operand numeric, low numeric, high numeric, count integer ) → integerwidth_bucket ( operand double precision, low double precision, high double precision, count integer ) → integer | 返回落在直方图中的桶的编号,直方图由跨越范围 low 到 high 的 count 个等宽桶组成。对于超出该范围的输入,返回 0 或 count+1。 | width_bucket(5.35, 0.024, 10.06, 5) → 3 |
width_bucket ( operand anycompatible, thresholds anycompatiblearray ) → integer | 给定一个列出桶下限的数组,返回落在哪个桶中的 operand 的编号。对于小于第一个下限的输入,返回 0。operand 和数组元素可以是具有标准比较操作符的任何类型。thresholds 数组必须排序,最小的在前,否则将得到意外的结果。 | width_bucket(now(), array['yesterday', 'today', 'tomorrow']::timestamptz[]) → 2 |
remainder ( dividend, divisor ) → numeric | 计算两个参数的余数,如 dividend/divisor。 | remainder(5.5, 5.2) → 1.1 |
truncate ( tinyInt/smallint/mediumint/int, D ) → inttruncate ( bigint, D ) → biginttruncate ( decimal/numeric, D ) → numerictruncate ( float/double, D ) → double | 返回被舍去至小数点后 D 位的数字 X。入参 1:X 为待截取的数字或纯数字字符串;入参 2:D 为截断的位数(整数、小数),小数遵循四舍五入。 | select truncate(1.2345, 3) → 1.234select truncate(1.23456, 3.5) → 1.2345 |
mod(y, x) 函数参数类型支持数字类型及纯数字的字符串类型,不支持空串。
表 随机函数显示了用于生成随机数的函数。
| 函数 | 描述 | 示例 |
|---|---|---|
random ( ) → double precision | 返回范围在 0.0 <= x < 1.0 内的随机值 | random() → 0.897124072839091 |
setseed ( double precision ) → void | 设置随后 random() 调用的种子;参数必须在 -1.0 和 1.0 之间(包括边界) | setseed(0.12345) |
random() 函数使用确定性伪随机数生成器。它速度快,但不适用于加密应用程序;请参见 uxcrypto 模块以获取更安全的替代方案。如果调用 setseed(),那么当前会话中后续 random() 调用的一系列结果可以通过使用相同参数重新发出 setseed() 来重复。如果在同一个会话中没有任何之前的 setseed() 调用,那么第一个 random() 调用将从依赖于平台的随机位源获得一个种子。
表 三角函数显示了可用的三角函数。每个函数都有两个变体,一个用弧度度量角度,另一个用度数度量角度。
| 函数 | 描述 | 示例 |
|---|---|---|
acos ( double precision ) → double precision | 反余弦,结果以弧度为单位 | acos(1) → 0 |
acosd ( double precision ) → double precision | 反余弦,结果以度数为单位 | acosd(0.5) → 60 |
asin ( double precision ) → double precision | 反正弦,结果以弧度为单位 | asin(1) → 1.5707963267948966 |
asind ( double precision ) → double precision | 反正弦,结果以度数为单位 | asind(0.5) → 30 |
atan ( double precision ) → double precision | 反正切,结果以弧度为单位 | atan(1) → 0.7853981633974483 |
atan ( double precision, double precision ) → double precision | y / x 的反正切,结果以弧度为单位 | atan(1, 0) → 1.5707963267948966 |
atand ( double precision ) → double precision | 反正切,结果以度数为单位 | atand(1) → 45 |
atan2 ( y double precision, x double precision ) → double precision | y / x 的反正切,结果以弧度为单位 | atan2(1, 0) → 1.5707963267948966 |
atan2d ( y double precision, x double precision ) → double precision | 反正切,参数为 y / x,结果以度为单位 | atan2d(1, 0) → 90 |
cos ( double precision ) → double precision | 余弦,参数为弧度 | cos(0) → 1 |
cosd ( double precision ) → double precision | 余弦,参数为度数 | cosd(60) → 0.5 |
cot ( double precision ) → double precision | 余切,参数为弧度 | cot(0.5) → 1.830487721712452 |
cotd ( double precision ) → double precision | 余切,参数为度数 | cotd(45) → 1 |
sin ( double precision ) → double precision | 正弦,参数为弧度 | sin(1) → 0.8414709848078965 |
sind ( double precision ) → double precision | 正弦,参数为度数 | sind(30) → 0.5 |
tan ( double precision ) → double precision | 正切,参数为弧度 | tan(1) → 1.5574077246549023 |
tand ( double precision ) → double precision | 正切,参数为度数 | tand(45) → 1 |
注意
另一种处理以度数表示的角度的方法是使用前面展示的单位转换函数radians()和degrees()。然而,使用基于度数的三角函数是更好的,该方式避免了特殊情况下的舍入误差,例如sind(30)。
表 双曲函数显示了可用的双曲函数。
| 函数 | 描述 | 示例 |
|---|---|---|
sinh ( double precision ) → double precision | 双曲正弦 | sinh(1) → 1.1752011936438014 |
cosh ( double precision ) → double precision | 双曲余弦 | cosh(0) → 1 |
tanh ( double precision ) → double precision | 双曲正切 | tanh(1) → 0.7615941559557649 |
asinh ( double precision ) → double precision | 反双曲正弦 | asinh(1) → 0.881373587019543 |
acosh ( double precision ) → double precision | 反双曲余弦 | acosh(1) → 0 |
atanh ( double precision ) → double precision | 反双曲正切 | atanh(0.5) → 0.5493061443340548 |
5. 字符串函数和操作符
本节介绍用于检查和操作字符串值的函数和操作符。在此上下文中,字符串包括类型为 character、character varying 和 text 的值。除非另有说明,这些函数和操作符被声明为接受和返回类型为 text。它们将互换地接受 character varying 参数。在应用函数或操作符之前,类型为 character 的值将被转换为 text,从而剥离 character 值中的任何尾随空格。
SQL定义了一些使用关键字而不是逗号分隔参数的字符串函数。详细信息请参见表 SQL 字符串函数和操作符。UXsinoDB还提供了使用常规函数调用语法的这些函数的版本(请参见表 其他字符串函数和操作符)。
注意
字符串连接操作符(||)将接受非字符串输入,只要至少有一个输入是字符串类型,如表 SQL 字符串函数和操作符所示。对于其他情况,可以插入显式强制转换为text,以使非字符串输入被接受。
| 函数/操作符 | 描述 | 示例 |
|---|---|---|
text || text → text | 连接两个字符串。 | 'UX' || 'sinoDB' → UXsinoDB |
text || anynonarray → textanynonarray || text → text | 将非字符串输入转换为文本,然后连接两个字符串。(非字符串输入不能是数组类型,因为这会与数组 || 操作符产生歧义。如果要连接数组的文本等效项,请将其显式转换为 text。) | 'Value: ' || 42 → Value: 42 |
text IS [NOT] [form] NORMALIZED → boolean | 检查字符串是否符合指定的 Unicode 规范化形式。可选的 form 关键字指定形式:NFC(默认值)、NFD、NFKC 或 NFKD。此表达式只能在服务器编码为 UTF8 时使用。请注意,使用此表达式检查规范化通常比规范化可能已经规范化的字符串更快。 | U&'\0061\0308bc' IS NFD NORMALIZED → t |
bit_length ( text ) → integer | 返回字符串中的位数(octet_length 的 8 倍)。 | bit_length('jose') → 32 |
char_length ( text ) → integercharacter_length ( text ) → integer | 返回字符串中的字符数。 | char_length('josé') → 4 |
lower ( text ) → text | 根据数据库的语言环境将字符串转换为全小写。 | lower('TOM') → tom |
normalize ( text [ , form ] ) → text | 将字符串转换为指定的 Unicode 规范形式。可选的 form 关键字指定规范形式:NFC(默认值)、NFD、NFKC 或 NFKD。此函数仅适用于服务器编码为 UTF8 的情况。 | normalize(U&'\0061\0308bc', NFC) → U&'\00E4bc' |
octet_length ( text ) → integer | 返回字符串中的字节数。 | octet_length('josé') → 5(如果服务器编码为 UTF8) |
octet_length ( character ) → integer | 返回字符串中的字节数。由于此版本的函数直接接受类型 character,因此它不会删除尾随空格。 | octet_length('abc '::character(4)) → 4 |
overlay ( string text PLACING newsubstring text FROM start integer [ FOR count integer ] ) → text | 用 newsubstring 替换从 start 字符开始并延伸 count 个字符的 string 的子字符串。如果省略 count,则默认为 newsubstring 的长度。 | overlay('Txxxxas' placing 'hom' from 2 for 4) → Thomas |
position ( substring text IN string text ) → integer | 返回指定的 substring 在 string 中的第一个起始索引,如果不存在则返回零。 | position('om' in 'Thomas') → 3 |
substring ( string text [ FROM start integer ] [ FOR count integer ] ) → text | 提取 string 的子字符串,如果指定了 start,则从第 start 个字符开始,如果指定了 count,则在 count 个字符后停止。提供 start 和 count 中的至少一个。 | substring('Thomas' from 2 for 3) → homsubstring('Thomas' from 3) → omassubstring('Thomas' for 2) → Th |
substring ( string text FROM pattern text ) → text | 提取第一个与 POSIX 正则表达式匹配的子字符串。 | substring('Thomas' from '...$') → mas |
substring ( string text SIMILAR pattern text ESCAPE escape text ) → textsubstring ( string text FROM pattern text FOR escape text ) → text | 提取第一个与 SQL 正则表达式匹配的子字符串。第一种形式自 SQL:2003 以来已经指定;第二种形式仅在 SQL:1999 中,应被视为过时。 | substring('Thomas' similar '%#"o_a#"_' escape '#') → oma |
trim ( [ LEADING | TRAILING | BOTH ] [ characters text ] FROM string text ) → text | ||
trim ( [ LEADING | TRAILING | BOTH ] [ FROM ] string text [ , characters text ] ) → text | ||
upper ( text ) → text | 将字符串转换为全大写,根据数据库的区域设置规则。 | upper('tom') → TOM |
substring_index ( string, delim, count ) → varchar | 以 delim 为分隔符,截取字符串 string,若 count 为正数,则返回从 string 头部往后计数 count 个包含分隔符的字符串;若 count 为负数,则返回截取后,从 str 尾部往前计数 count 个包含分隔符字符串。 | substring_index('111a222A333a444A555', 'a', -2) → 222A333a444A555 |
locate ( substr, string[, pos] ) → int | 返回 substr 在 string 中第一次出现的位置,pos 指定起始检索位置,如果字符串中不存在子字符串,则它将返回 0。当数据库为 mysql 运行模式且 ignore_case=on 时,在字符串中搜索子字符串的位置时,大小写不敏感,非 mysql 模式下,大小写敏感。 | locate('b', 'abc'); → 2locate('c', 'abc', '2') → 3 |
还有其他可用的字符串操作函数和操作符,列在表 其他字符串函数和操作符中。(其中一些用于内部实现表 SQL 字符串函数和操作符中列出的 SQL 标准字符串函数。)还有模式匹配操作符,这些在模式匹配中描述,以及全文搜索操作符。
| 函数/操作符 | 说明 | 示例 |
|---|---|---|
text ^@ text → boolean | 如果第一个字符串以第二个字符串开头,则返回 true(等同于 starts_with() 函数)。 | 'alphabet' ^@ 'alph' → t |
ascii ( text ) → integer | 返回参数的第一个字符的数字代码。在 UTF8 编码中,返回字符的 Unicode 代码点。在其他多字节编码中,参数必须是 ASCII 字符。 | ascii('x') → 120 |
btrim ( string text [ , characters text ] ) → text | 从 string 的开头和结尾删除包含 characters(默认为空格)中的字符的最长字符串。 | btrim('xyxtrimyyx', 'xy') → trim |
chr ( integer ) → text | 返回给定代码的字符。在 UTF8 编码中该参数被视作一个 Unicode 代码点。在其他多字节编码中该参数必须指定一个 ASCII 字符。chr(0) 字符不被允许,因为文本数据类型不能存储这种字符。 | chr(65) → A |
concat ( val1 "any"[, val2 "any" [, ...] ] ) → text | 连接所有参数的文本表示。空参数被忽略。 | concat('abcde', 2, NULL, 22) → abcde222 |
concat_ws ( sep text, val1 "any"[, val2 "any" [, ...] ] ) → text | 用分隔符连接除第一个参数外的所有参数。第一个参数用作分隔符字符串,不应为 NULL。其他 NULL 参数将被忽略。 | concat_ws(',', 'abcde', 2, NULL, 22) → abcde,2,22 |
format ( formatstr text[, formatarg "any" [, ...] ] ) → text | 根据格式字符串对参数进行格式化。这个函数类似于 C 函数 sprintf。 | format('Hello %s, %1$s', 'World') → Hello World, World |
initcap ( text ) → text | 将每个单词的第一个字母转换为大写,其余字母转换为小写。单词是由非字母数字字符分隔的字母数字字符序列。 | initcap('hi THOMAS') → Hi Thomas |
left ( string text, n integer ) → text | 返回字符串中的第一个 n 字符,或在 n 为负时,返回最后 | n |
length ( string text ) → integer | 返回 string 的长度(以字符为单位)。 | length('hello') → 5 |
lpad ( string text, length integer[ , fill text ] ) → text | 将 string 扩展为长度 length,通过前置字符 fill(默认空格)。如果 string 已经超过 length 那么它将被截断(在右侧)。 | lpad('hi', 5, 'xy') → xyxhi |
ltrim ( string text[ , characters text ] ) → text | 从 string 开始删除包含 characters(默认空格)中仅包含字符的最长字符串。 | ltrim('zzzytest', 'xyz') → test |
md5 ( text ) → text | 计算参数的 MD5 hash,结果以十六进制形式写入。 | md5('abc') → 900150983cd24fb0d6963f7d28e17f72 |
parse_ident ( qualified_identifier text[, strict_mode boolean DEFAULT true ] ) → text[] | 将 qualified_identifier 拆分为一个标识符数组,删除单个标识符的任何引用。默认情况下,最后一个标识符之后的额外字符被视为错误;但是,如果第二个参数为 false,则忽略这些额外的字符。(这种行为对于解析类似函数的对象的名称有作用。)请注意,此函数不会截断超长标识符。如果你想截断,你可以把结果给到 name[]。 | parse_ident('"SomeSchema".someTable') → {SomeSchema,sometable} |
ux_client_encoding ( ) → name | 返回当前客户端编码名称。 | ux_client_encoding() → UTF8 |
quote_ident ( text ) → text | 返回适合引用的给定字符串,作为 SQL 语句字符串中的标识符。只有在必要的情况下才添加引号(例如,如果字符串包含非标识符字符或将被大小写折叠)。嵌入的引号被适当地加双引号。 | quote_ident('Foo bar') → "Foo bar" |
quote_literal ( text ) → text | 返回在 SQL 语句字符串中适当引用的给定字符串,用作字符串文字。嵌入式单引号和反斜线适当的翻倍(转双引号或双斜线)。请注意,quote_literal 返回无效输入;如果这个参数可能为空,quote_nullable 通常更合适。 | quote_literal(E'O\'Reilly') → 'O''Reilly' |
quote_literal ( anyelement ) → text | 将给定的值转换为文本,然后将其作为字面量引用。内嵌的单引号和反斜杠被适当地翻倍。 | quote_literal(42.5) → '42.5' |
quote_nullable ( text ) → text | 返回在 SQL 语句字符串中适当引用的给定字符串文字;或者,如果参数为 null,则返回 NULL。内嵌的单引号和反斜杠被适当地翻倍。 | quote_nullable(NULL) → NULL |
quote_nullable ( anyelement ) → text | 将给定值转换为文本,然后将其作为字面量引用;或者,如果参数为 null,则返回 NULL。内嵌的单引号和反斜杠被适当地翻倍。 | quote_nullable(42.5) → '42.5' |
regexp_count ( string text, pattern text [, start integer [, flags text ] ] ) → integer | 返回 POSIX 正则表达式 pattern 在 string 中匹配的次数。 | regexp_count('123456789012', '\d\d\d', 2) → 3 |
regexp_instr ( string text, pattern text [, start integer [, N integer [, endoption integer [, flags text [, subexpr integer ] ] ] ] ] ) → integer | 返回 POSIX 正则表达式 pattern 的第 N 次匹配在 string 中的位置,如果没有这样的匹配,则返回零。 | regexp_instr('ABCDEF', 'c(.)(..)', 1, 1, 0, 'i') → 3regexp_instr('ABCDEF', 'c(.)(..)', 1, 1, 0, 'i', 2) → 5 |
regexp_like ( string text, pattern text [, flags text ] ) → boolean | 检查 POSIX 正则表达式 pattern 是否在 string 中出现。 | regexp_like('Hello World', 'world$', 'i') → t |
regexp_match ( string text, pattern text [, flags text ] ) → text[] | 返回 POSIX 正则表达式 pattern 的第一个匹配中的子字符串到 string。 | regexp_match('foobarbequebaz', '(bar)(beque)') → {bar,beque} |
regexp_matches ( string text, pattern text [, flags text ] ) → setof text[] | 返回第一个匹配 POSIX 正则表达式 pattern 的子字符串到 string 中,或者如果使用了 g 标志,则返回所有这样的匹配的子字符串。 | regexp_matches('foobarbequebaz', 'ba.', 'g') → {bar}{baz} |
regexp_replace ( string text, pattern text, replacement text [, start integer ] [, flags text ] ) → text | 替换第一个匹配 POSIX 正则表达式 pattern 的子字符串,或者如果使用了 g 标志,则替换所有这样的匹配。 | regexp_replace('Thomas', '.[mN]a.', 'M') → ThM |
regexp_replace ( string text, pattern text, replacement text, start integer, N integer [, flags text ] ) → text | 替换第 N 个匹配 POSIX 正则表达式 pattern 的子字符串,或者如果 N 为零,则替换所有这样的匹配。 | regexp_replace('Thomas', '.', 'X', 3, 2) → ThoXas |
regexp_split_to_array ( string text, pattern text [, flags text ] ) → text[] | 使用 POSIX 正则表达式作为分隔符拆分 string,生成结果数组。 | regexp_split_to_array('hello world', '\s+') → {hello,world} |
regexp_split_to_table ( string text, pattern text [, flags text ] ) → setof text | 使用 POSIX 正则表达式作为分隔符拆分 string,生成一组结果。 | regexp_split_to_table('hello world', '\s+') → helloworld |
regexp_substr ( string text, pattern text [, start integer [, N integer [, flags text [, subexpr integer ] ] ] ] ) → text | 返回与 POSIX 正则表达式 pattern 的第 N 次出现匹配的 string 中的子字符串,如果没有这样的匹配,则返回 NULL。 | regexp_substr('ABCDEF', 'c(.)(..)', 1, 1, 'i') → CDEFregexp_substr('ABCDEF', 'c(.)(..)', 1, 1, 'i', 2) → EF |
repeat ( string text, number integer ) → text | 重复 string 指定的 number 次。 | repeat('Ux', 4) → UxUxUxUx |
replace ( string text, from text, to text ) → text | 将 string 中所有出现的子字符串 from 替换为子字符串 to。 | replace('abcdefabcdef', 'cd', 'XX') → abXXefabXXef |
reverse ( text ) → text | 反转字符串中字符的顺序。 | reverse('abcde') → edcba |
right ( string text, n integer ) → text | 返回字符串中的最后 n 个字符,或当 n 为负数时,返回除去前 | n |
rpad ( string text, length integer [, fill text ] ) → text | 通过附加字符 fill(默认为空格)将 string 扩展到长度 length。如果 string 已经比 length 长,则将其截断。 | rpad('hi', 5, 'xy') → hixyx |
rtrim ( string text [, characters text ] ) → text | 从 string 的末尾删除仅包含 characters(默认为空格)中字符的最长字符串。 | rtrim('testxxzx', 'xyz') → test |
split_part ( string text, delimiter text, n integer ) → text | 在 delimiter 出现的位置分割 string,并返回第 n 个字段(从 1 开始计数),或当 n 为负数时,返回倒数第 | n |
space ( numeric N ) → text | 返回 N 个空格字符串。 | select space(5), length(space(5)); → ' ', 5 |
starts_with ( string text, prefix text ) → boolean | 如果 string 以 prefix 开头,则返回 true。 | starts_with('alphabet', 'alph') → t |
string_to_array ( string text, delimiter text [, null_string text ] ) → text[] | 将 string 按 delimiter 分割,并将结果字段组成 text 数组。如果 delimiter 是 NULL,则 string 中的每个字符都将成为数组中的一个单独元素。如果 delimiter 是空字符串,则将 string 视为单个字段。如果提供了 null_string 并且不是 NULL,则匹配该字符串的字段将被替换为 NULL。 | string_to_array('xx~~yy~~zz', '~~', 'yy') → {xx,NULL,zz} |
string_to_table ( string text, delimiter text [, null_string text ] ) → setof text | 将 string 按 delimiter 分割,并将结果字段作为 text 行的集合返回。如果 delimiter 是 NULL,则 string 中的每个字符都将成为结果的一个单独行。如果 delimiter 是空字符串,则将 string 视为单个字段。如果提供了 null_string 并且不是 NULL,则匹配该字符串的字段将被替换为 NULL。 | string_to_table('xx~^~yy~^~zz', '~^~', 'yy') → xxNULLzz |
strpos ( string text, substring text ) → integer | 返回指定的 substring 在 string 中的第一个起始索引,如果不存在则返回 0。(与 position(substring in string) 相同,但请注意参数顺序相反) | strpos('high', 'ig') → 2 |
substr ( string text, start integer [, count integer ] ) → text | 提取从第 start 个字符开始的 string 子字符串,并在指定的情况下延伸 count 个字符。(与 substring(string from start for count) 相同) | substr('alphabet', 3) → phabetsubstr('alphabet', 3, 2) → ph |
to_ascii ( string text ) → textto_ascii ( string text, encoding name ) → textto_ascii ( string text, encoding integer ) → text | 将 string 从另一种编码转换为 ASCII,可以通过名称或数字进行标识。如果省略 encoding,则假定数据库编码(在实践中,这是唯一有用的情况)。转换主要包括删除重音符号。仅支持从 LATIN1、LATIN2、LATIN9 和 WIN1250 编码进行转换。 | to_ascii('Karél') → Karel |
to_hex ( integer ) → textto_hex ( bigint ) → text | 将数字转换为其等效的十六进制表示形式。 | to_hex(2147483647) → 7fffffff |
translate ( string text, from text, to text ) → text | 将 from 集中与 string 中的每个字符匹配的字符替换为 to 集中的相应字符。如果 from 比 to 长,则会出现额外字符的情况。from 被删除。 | translate('12345', '143', 'ax') → a2x5 |
unistr ( text ) → text | 对参数中的转义 Unicode 字符进行求值。Unicode 字符可以被指定为 \XXXX(4 个十六进制数字)、+XXXXXX(6 个十六进制数字)、\uXXXX(4 个十六进制数字)或 \UXXXXXXXX(8 个十六进制数字)。要指定反斜杠,请写两个反斜杠。所有其他字符都被视为字面量。如果服务器编码不是 UTF-8,则由这些转义序列标识的 Unicode 代码点将转换为实际的服务器编码;如果不可能,则报告错误。该函数提供了一个(非标准的)使用 Unicode 转义的字符串常量的替代方法。 | unistr('d\0061t\+000061') → dataunistr('d\u0061t\U00000061') → data |
find_in_set ( str text, strlist anyset ) → int | 找出 str 在 strlist 中第一次出现的位置。 | create table t1(id int, name set('caicai','fly','ys','cat'));insert into t1 values(1,'fly,ys'),(2,'caicai'),(3,'cat,ys,caicai');select find_in_set('ys'::text,name) from t1; → find_in_set-------------303 |
elt ( a_expr, expr_list ) → varchar | a_expr 为数字类型,根据 a_expr 的值,返回 expr_list 字符串列表中的第 N 个元素,如果参数 a_expr 为 1,返回 expr1,如果为 2,返回 expr2,依次类推,若 a_expr 小于 1 或大小超出 expr_list 参数个数,则返回 NULL。 | elt(1, 'Aa', 'Bb') → Aa |
field ( a_expr, expr_list ) → int | 返回 a_expr 在 expr_list 列表中的索引(位置),如果 a_expr 未找到,则返回 0,如果 a_expr 为 null,最终也返回 0,因为 null 不与任何值做相等比较。 | field('Aa', 'Aa', 'Bb'); → 1 |
chr ( double precision ) → text | 给定代码的字符。在运行模式为 oracle 时支持该类型。 | chr(65.5::DOUBLE PRECISION) → A |
chr ( text ) → text | 给定代码的字符。 | select chr('128'::TEXT); → \u0080 |
hex ( number ) → text | 将给定的参数转为 16 进制表示。hex 函数将参数理解为十进制数,并返回该数字的十六进制值的字符形式。如果 number 不是整数,那么在进行运算前,会将其四舍五入为最接近的整数(bigint),然后返回该数的十六进制数值。比如入参是 float 类型,hex 函数会先将入参转为 bigint 类型,然后再做进制转换。number 包括 smallint、integer、bigint、numeric、real、double precision 类型。 | hex(16) → '10' |
hex ( string ) → text | 将给定的参数转为 16 进制表示。hex 函数会将参数的每个字符转换成 2 位的十六进制值的字符形式。string 包括 text、timestamptz、timestamp、date、time、timetz、interval、blob、boolean 类型。 | hex('123') → '313233' |
strcmp ( expr1, expr2 ) → int | 比较 expr1, expr2(字符串),若 expr1 和 expr2 任意一个为 NULL 则返回 NULL;若 expr1 和 expr2 相同,则返回 0,若 expr1 小于 expr2,则返回 -1,其余情况返回 1。 | strcmp(1, 1); → 0strcmp('apple', 'apple1'); → -1strcmp('apple', 'app'); → 1 |
convert ( str using charset_name ) → text | 将 str 串转换成 charset_name 指定的编码值返回。该函数仅支持 mysql 运行模式。 | convert('abc' using gb18030) → abc |
convert ( expr, typename ) | 将 expr 按照 typename 指定的类型转换,返回转换后类型对应值。该函数仅支持 mysql 运行模式。 | convert('1', numeric) → 1 |
format ( num, scale [, local] ) → text | 将数字格式化为指定的格式,返回格式化后的字符串值,num 表示要格式化的数字,scale 表示小数点后的位数,local 表示指定使用的本地化格式。该函数仅支持 mysql 运行模式。 | format(123456.123456, 1) → 123,456.1 |
instr ( string1, string2 [, n [, m ]] ) → int | 在 string1 中查找 string2,如果查找到则返回 string2 在 string1 中的首位置;如果没有,则返回 0。n 表示从 string1 的第 n 个字符开始搜索,如果 n 为负,则从后向前搜索,即从 string1 的末尾开始的第 abs(n) 个字符开始。如果没有传 n,默认为 1(从第 1 个字符开始搜索)。m 表示 string2 在 string1 出现的第 m 次出现,如果没有传 m,则默认为 1(找第 1 次出现)。string1 支持字符类型,数值类型(包括浮点数),日期和时间型数据类型,大对象类型(clob,blob)。string2 支持字符类型,数值类型(包括浮点数),日期和时间型数据类型,大对象类型(clob,blob)。n 支持数字类型(整数和浮点数均可,浮点数会被四舍五入),支持数值类型的字符串比如 '12' 等,而 'abc' 不可以,除此之外的其他类型均不支持。m 支持数字类型(整数和浮点数均可,浮点数会被四舍五入),支持数值类型的字符串比如 '12' 等,而 'abc' 不可以,除此之外的其他类型均不支持。 | instr('2023-02-28':: timestamptz, '8') → 10 |
NCHR ( number_value ) → text | 返回与 unicode 码值相等的字符。number_value 取值范围 0 到 1114111(0x10FFFF),支持类型为 smallint,int,bigint,real,double precision,char,varchar,varchar2,text。注意:服务端只能为 UTF8 编码。 | NCHR('20013') → 中 |
nls_upper ( str ) → str | 将 str 转为全大写字符串。str 支持字符类型(text、varchar、char、varchar2、nvarchar2、nchar、name),时间类型(time、time with time zone、timestamp、timestamp time zone、date、interval)、数字类型(smallint、integer、bigint、numeric、real、float)及大对象(clob),但是 clob 会有 1GB 大小的限制。 | nls_upper('abc\EfdG!') → ABC\EFDG! |
make_set ( numeric bits, text str1, text str2, ... ) → varchar | 根据给定的位标志 bits 和字符串列表返回一个字符串集合,以逗号分隔。其中,bits 的第 0 位对应 str1,第 1 位对应 str2……,以此类推,位值为 1 则选取对应字符串放入集合中,位值为 0 则不选。 | make_set(6, 'hello', 'nice', 'world') → nice,world |
len ( string text ) → integer | 返回给定字符串表达式的字符(而不是字节)个数(汉字为一个字符),其中不包含尾随空格。 | select len('hello world'); → 11select len(920323.11); → 9 |
LOWER ( str ) → textLCASE ( str ) → text | 返回根据当前字符集映射将 str 所有字符更改为小写的字符串,如果 str 为 NULL 则函数返回 NULL。LCASE() 是 LOWER() 的同义词。 | select lower('New York'); → new yorkselect lcase('New York'); → new york |
UPPER ( str ) → textUCASE ( str ) → text | 返回根据当前字符集映射将 str 所有字符更改为大写的字符串,如果 str 为 NULL 则函数返回 NULL。UCASE() 是 UPPER() 的同义词。 | select ucase('New York'); → NEW YORK |
concat、concat_ws 和 format 函数是可变参数的,因此可以将要连接或格式化的值作为带有 VARIADIC 关键字标记的数组传递。数组的元素被视为函数的单独普通参数。如果可变数组参数为 NULL,则 concat 和 concat_ws 返回 NULL,但 format 将 NULL 视为零元素数组。
另请参见聚合函数中的 string_agg,以及在表 文本/二进制字符串转换函数中用于在字符串和 bytea 类型之间转换的函数。
5.1. format
函数 format 根据格式字符串生成格式化输出,类似于 C 函数 sprintf。
format(formatstr text [, formatarg "any" [, ...] ])
formatstr 是一个格式字符串,指定结果应该如何格式化。格式字符串中的文本直接复制到结果中,除非使用了格式说明符。格式说明符在字符串中充当占位符,定义如何格式化并插入后续函数参数到结果中。每个 formatarg 参数都按照其数据类型的通常输出规则转换为文本,然后根据格式说明符格式化并插入到结果字符串中。
格式说明符由 % 字符引入,其形式为
%[position][flags][width]type
其中组件字段为:
-
position(可选) 格式为n$的字符串,其中n是要打印的参数索引。索引 1 表示formatstr之后的第一个参数。如果省略position,则默认使用下一个序列中的参数。 -
flags(可选) 控制格式说明符输出格式的其他选项。目前,唯一支持的标志是减号(-),它将导致格式说明符的输出左对齐。除非指定了width字段,否则这没有任何影响。 -
width(可选) 指定用于显示格式说明符输出的最小字符数。根据需要在左侧或右侧(取决于-标志)用空格填充输出以填充宽度。太小的宽度不会导致输出被截断,而只是被忽略。可以使用以下任何一种指定宽度:正整数;星号(*)使用下一个函数参数作为宽度;或形式为*n$的字符串,以使用第n个函数参数作为宽度。如果宽度来自函数参数,则在用于格式说明符的值的参数之前使用该参数。如果宽度参数为负,则结果将左对齐(就像指定了
-标志一样)在长度为abs(width)的字段内。 -
type(必需) 用于生成格式说明符输出的格式转换类型。支持以下类型:s将参数值格式化为简单字符串。空值视为空字符串。I将参数值视为 SQL 标识符,必要时用双引号括起来。值为空(等效于quote_ident)是错误的。L将参数值引用为 SQL 文字。空值显示为字符串NULL,不带引号(等效于quote_nullable)。
除了上面描述的格式说明符之外,还可以使用特殊序列 %% 来输出文字 % 字符。
以下是一些基本格式转换的示例:
SELECT format('Hello %s', 'World');
Result: Hello World
SELECT format('Testing %s, %s, %s, %%', 'one', 'two', 'three');
Result: Testing one, two, three, %
SELECT format('INSERT INTO %I VALUES(%L)', 'Foo bar', E'O\'Reilly');
Result: INSERT INTO "Foo bar" VALUES('O''Reilly')
SELECT format('INSERT INTO %I VALUES(%L)', 'locations', 'C:\Program Files');
Result: INSERT INTO locations VALUES('C:\Program Files')
以下是使用 width 字段和 - 标志的示例:
SELECT format('|%10s|', 'foo');
Result: | foo|
SELECT format('|%-10s|', 'foo');
Result: |foo |
SELECT format('|%*s|', 10, 'foo');
Result: | foo|
SELECT format('|%*s|', -10, 'foo');
Result: |foo |
SELECT format('|%-*s|', 10, 'foo');
Result: |foo |
SELECT format('|%-*s|', -10, 'foo');
Result: |foo |
这些示例展示了 position 字段的使用:
SELECT format('Testing %3$s, %2$s, %1$s', 'one', 'two', 'three');
Result: Testing three, two, one
SELECT format('|%*2$s|', 'foo', 10, 'bar');
Result: | bar|
SELECT format('|%1$*2$s|', 'foo', 10, 'bar');
Result: | foo|
与标准 C 函数 sprintf 不同,UXsinoDB 的 format 函数允许在同一格式字符串中混合使用带有和不带有 position 字段的格式说明符。没有 position 字段的格式说明符总是使用上一个参数之后的下一个参数。此外,format 函数不要求在格式字符串中使用所有函数参数。例如:
SELECT format('Testing %3$s, %2$s, %s', 'one', 'two', 'three');
Result: Testing three, two, three
%I 和 %L 格式说明符特别适用于安全地构建动态 SQL 语句。
5.2. btrim
-
功能
btrim函数可以去除 expr 头尾的指定 chr。调用时只有 expr 而不指定 chr 时,可以去除 expr 头尾的空格。 -
函数
btrim(expr[, chr]) -
参数
表 btrim 参数说明
参数 说明 expr 一个表中已经存在的列名。 chr 指定字符。 -
返回值
text -
示例
select btrim(' abcda ') from dual; select btrim(' abcda ', 'a') from dual; -
注意事项
此函数需要加载 oracle 插件。 此函数不支持 blob 和 clob 等大对象。
5.3. group_concat
-
功能
对多行内容做字符串拼接,默认以 ',' 分隔开,但是可以指定。有多个参数时会将每一行先做一个字符串拼接中间无间隔;再对每行拼接以分隔符拼接。
-
函数
GROUP_CONCAT([DISTINCT] cat_arg1 [,cat_arg2 ...] [ORDER BY {unsigned_integer | col_name | expr} [ASC | DESC] [,col_name ...]] [SEPARATOR str_val])注意
DISTINCT、ORDER BY 不能同时使用。 -
参数
表 group_concat 参数说明
参数 说明 cat_arg 连接内容参数,1 个或多个;可以为能转换为字符的任意类型。 SEPARATOR str_val 用于指定间隔符号,可以是空串,但是不能为空;只能是单引号常量(即字符),当省略这个字段时间默认为 ','。 -
返回值
返回连接后的字符串,类型为
text。注意
- 一行中有一列为空,那一行会被忽略。
- 参数
group_concat_max_len用于指定拼接结果的最大长度,连接后的字符串超过时按照group_concat_max_len指定的长度截断(最小值为 4,设置小于 4 的值时,不会报错,实际会设置为 4);字符串小于最大限制时不会补充空格。
-
示例
uxdb=# CREATE TABLE products (product_no integer, name text, price numeric); CREATE TABLE uxdb=# INSERT INTO products VALUES(1, 'Cheese', 9.99),(2, 'Bread', 1.99),(3, 'Milk', 2.99); INSERT 0 3 uxdb=# select group_concat(product_no, name) from products; group_concat ---------------------- 1Cheese,2Bread,3Milk (1 row) uxdb=# select group_concat(product_no, name separator '+') from products; group_concat ---------------------- 1Cheese+2Bread+3Milk (1 row)
5.4. substr
-
功能
substr截取字符串或字符串表达式。 -
函数
substr(A, B, C); substr(A, B); substr(A from B for C); substr(A from B); substr(A for C); substr(A for C from B); -
参数
表 substr 参数说明
参数 说明 A 需要被截取的字符串或字符串表达式。 B 从第 B 个字符开始截取。 C 截取长度为 C 的字符串信息。 -
返回值
text -
示例
select substr('tesabcdefg', 2, 5); select substr('tesabcdefg', 2); select substr('tesabcdefg' from 2 for 5); select substr('tesabcdefg' from 2); select substr('tesabcdefg' for 5); select substr('tesabcdefg' for 5 from 2);
5.5. unhex
-
功能
根据输入的字符串,每对字符理解为十六进制数字并返回其对应的 ASCII 码字符。 字符必须是合法的十六进制数字,否则返回 NULL(空)。 输入奇数个字符时,会在字符串左侧补 0。
-
函数
unhex(str); unhex(number);返回显示效果由
binary-as-hex参数控制。启动数据库时若
binary-as-hex = true,则unhex返回值显示为二进制字符串。 启动数据库时若binary-as-hex = false,则unhex返回值显示为 ASCII 字符。 -
返回值
varbinary -
示例
uxdb=> select unhex('55584442'); unhex ------------ 0x55584442 (1 row) uxdb=> select unhex(55584442); unhex ------------ 0x55584442 (1 row)
5.6. || 操作符
-
双竖线操作符作为字符连接操作符功能使用,如下所示。
函数 返回值 描述 示例 string||stringtext串接 'UXsino' || 'DB'→UXsinoDBstring||non-string或non-string||stringtext使用一个非字符串输入的串接 'Value: ' || 42→Value: 42varbinary||varbinaryvarbinary串接 binary||binaryvarbinary串接 -
mysql 模式下为 sql_mode 添加
PIPES_AS_CONCAT参数,||操作符转为逻辑或功能使用。select 1 || 0; ?column? ---------- t (1 row) select ux_typeof(1 || 0); ux_typeof ----------- boolean (1 row)
5.7. insert()
-
功能
insert()函数返回 str 字符串从位置 pos 开始剪切,len 字符长被字符串 newstr 替换的新字符串。如果 pos 不在字符串的长度范围内,则返回原始字符串。 如果 len 不在字符串其余部分的长度范围内,则从位置 pos 替换字符串的其余部分。 如果任何参数为 NULL,则返回 NULL。
-
函数
INSERT (str, pos, len, newstr) -
示例
uxdb=# SELECT INSERT ('Quadratic', 3, 4, 'What'); insert ----------- QuWhattic (1 row) uxdb=# SELECT INSERT ('Quadratic', -1, 4, 'What'); insert ----------- Quadratic (1 row) uxdb=# SELECT INSERT ('Quadratic', 3, 100, 'What'); insert -------- QuWhat (1 row)
5.8. NLS
支持 Oracle 的 NLS 系列函数 NLS_LOWER,NLS_UPPER,NLS_INITCAP。
5.8.1. NLS_LOWER
-
功能
返回将字符串并将其变成小写,按 y 指定的排序规则输出。 如果不带参数 y,则函数的功能和对应的去掉 NLS 前缀的函数效果一样,例如
NLS_LOWER(x)和LOWER(x)一样。 -
函数
NLS_LOWER(x[, y]) -
参数
表 NLS_LOWER 参数说明
参数 说明 x text类型字符或者可以转换成text类型的数据。y nls_parameter,可选的 NLS 参数,格式为nls_sort= ...,后面的内容可以指定ux_collation中collname的所有字段。参数 y 需要以
nls_sort=为开头,不区分大小写,可以有空格。 如果 x 和 y 至少有一项为 NULL,则函数会直接返回 NULL。 -
示例
uxdb=# select nls_lower('AC','nls_sort=C'); nls_lower ----------- ac (1 row)
5.8.2. NLS_UPPER
-
功能
返回将字符串并将其变成大写,按 y 指定的排序规则输出。
-
函数
NLS_UPPER(x[, y]) -
参数
表 NLS_UPPER 参数说明
参数 说明 x text类型字符或者可以转换成text类型的数据。y nls_parameter,可选的 NLS 参数,格式为nls_sort= ...,后面的内容可以指定ux_collation中collname的所有字段。参数 y 需要以
nls_sort=为开头,不区分大小写,可以有空格。 如果 x 和 y 至少有一项为 NULL,则函数会直接返回 NULL。 -
示例
uxdb=# select nls_upper('ab','NLS_SORT=zh_SG'); nls_upper ----------- AB (1 row)
5.8.3. NLS_INITCAP
-
功能
返回将字符串并将其变成首字母大写其他小写的格式,按 y 指定的排序规则输出。
-
函数
NLS_INITCAP(x[, y]) -
参数
表 NLS_INITCAP 参数说明
参数 说明 x text类型字符或者可以转换成text类型的数据。y nls_parameter,可选的 NLS 参数,格式为nls_sort= ...,后面的内容可以指定ux_collation中collname的所有字段。参数 y 需要以
nls_sort=为开头,不区分大小写,可以有空格。 如果 x 和 y 至少有一项为 NULL,则函数会直接返回 NULL。 -
示例
uxdb=# select nls_initcap('aAadf', NULL); nls_initcap ------------- (1 row) uxdb=# select nls_initcap('aAadf','nls _so r t=C'); nls_initcap ------------- Aaadf (1 row)
5.9. MID
-
功能
MID函数是 MySQL 的字符串截取函数。此函数用于返回一个字符串中从指定位置开始的指定长度的子字符串。MID(str, pos, len)等同于SUBSTRING(str, pos, len)和SUBSTR(str, pos, len)函数。 -
函数
MID(str, pos, len) -
参数
表 MID 参数说明
参数 说明 str(text类型)必需的。从中提取子字符串的原字符串。 pos(int类型)必需的。开始提取的位置。它可以是正数或者负数。如果是正数,则从字符串的开头开始提取子字符串。如果是负数,则从字符串的结尾提取子字符串。 len(int类型)可选的。子字符串的长度(字符数)。如果不指定,则提取到原字符串的结尾。 -
返回值
当
pos为 0 或者超过原字符串的长度时,MID()函数将返回空串。当参数为NULL时,MID()函数将返回NULL。 -
示例
uxdb=# select mid('hello', 0); mid ----- (1 row) uxdb=# select mid('hello', 3); mid ----- llo (1 row) uxdb=# select mid('hello', 8); mid ----- (1 row) uxdb=# select mid('hello', 2, 3); mid ----- ell (1 row) uxdb=# select mid('hello', -1, 3); mid ----- o (1 row) uxdb=# select mid('hello', -4, 3); mid ----- ell (1 row)
6. 二进制字符串函数和操作符
本节介绍用于检查和操作二进制字符串的函数和操作符,即类型为 bytea 的值。其中许多在目的和语法上等效于前一节中描述的文本字符串函数。
SQL定义了一些字符串函数,使用关键字而不是逗号来分隔参数。详情请参见表 SQL 二进制字符串函数和操作符。UXsinoDB还提供了这些函数的版本,使用常规函数调用语法(请参见表 其他二进制字符串函数)。
| 函数/操作符 | 说明 | 示例 |
|---|---|---|
bytea || bytea → bytea | 连接两个二进制字符串。 | '\x123456'::bytea || '\x789a00bcde'::bytea → \x123456789a00bcde |
bit_length ( bytea ) → integer | 返回二进制字符串中的位数(octet_length 的 8 倍)。 | bit_length('\x123456'::bytea) → 24 |
octet_length ( bytea ) → integer | 返回二进制字符串中的字节数。 | octet_length('\x123456'::bytea) → 3 |
overlay ( bytes bytea PLACING newsubstring bytea FROM start integer [ FOR count integer ] ) → bytea | 用 newsubstring 替换从第 start 个字节开始并延伸 count 个字节的 bytes 的子字符串。如果省略 count,则默认为 newsubstring 的长度。 | overlay('\x1234567890'::bytea placing '\002\003'::bytea from 2 for 3) → \x12020390 |
position ( substring bytea IN bytes bytea ) → integer | 返回指定的 substring 在 bytes 中的第一个起始索引,如果不存在则返回零。 | position('\x5678'::bytea in '\x1234567890'::bytea) → 3 |
substring ( bytes bytea [ FROM start integer ] [ FOR count integer ] ) → bytea | 提取从第 start 个字节开始的 bytes 的子字符串,如果指定了,则在 count 个字节后停止。提供 start 和 count 中的至少一个。 | substring('\x1234567890'::bytea from 3 for 2) → \x5678 |
trim ( [ LEADING | TRAILING | BOTH ] bytesremoved bytea FROM bytes bytea ) → bytea | ||
trim ( [ LEADING | TRAILING | BOTH ] [ FROM ] bytes bytea, bytesremoved bytea ) → bytea |
还有其他可用的二进制字符串操作函数,列在表 其他二进制字符串函数中。其中一些用于内部实现列在表 SQL 二进制字符串函数和操作符中的 SQL 标准字符串函数。
| 函数 | 描述 | 示例 |
|---|---|---|
bit_count ( bytes bytea ) → bigint | 返回二进制字符串中设置的位数(也称为“popcount”)。 | bit_count('\x1234567890'::bytea) → 15 |
btrim ( bytes bytea, bytesremoved bytea ) → bytea | 从 bytes 的开头和结尾中删除仅包含在 bytesremoved 中的字节的最长字符串。 | btrim('\x1234567890'::bytea, '\x9012'::bytea) → \x345678 |
get_bit ( bytes bytea, n bigint ) → integer | 从二进制字符串中提取第 n 位。 | get_bit('\x1234567890'::bytea, 30) → 1 |
get_byte ( bytes bytea, n integer ) → integer | 从二进制字符串中提取第 n 个字节。 | get_byte('\x1234567890'::bytea, 4) → 144 |
length ( bytea ) → integer | 返回二进制字符串中的字节数。 | length('\x1234567890'::bytea) → 5 |
length ( bytes bytea, encoding name ) → integer | 返回二进制字符串中的字符数,假设它是给定 encoding 的文本。 | length('jose'::bytea, 'UTF8') → 4 |
ltrim ( bytes bytea, bytesremoved bytea ) → bytea | 从 bytes 的开头删除包含 bytesremoved 中的字节的最长字符串。 | ltrim('\x1234567890'::bytea, '\x9012'::bytea) → \x34567890 |
md5 ( bytea ) → text | 计算二进制字符串的 MD5 哈希,并将结果以十六进制形式写入。 | md5('Th\000omas'::bytea) → 8ab2d3c9689aaf18b4958c334c82d8b1 |
rtrim ( bytes bytea, bytesremoved bytea ) → bytea | 从 bytes 的末尾删除包含 bytesremoved 中的字节的最长字符串。 | rtrim('\x1234567890'::bytea, '\x9012'::bytea) → \x12345678 |
set_bit ( bytes bytea, n bigint, newvalue integer ) → bytea | 将二进制字符串中的第 n 位设置为新值。 | set_bit('\x1234567890'::bytea, 30, 0) → \x1234563890 |
set_byte ( bytes bytea, n bigint, newvalue integer ) → bytea | 将二进制字符串中的第 n 位设置为新值。 | set_byte('\x1234567890'::bytea, 4, 64) → \x1234567840 |
sha224 ( bytea ) → bytea | 计算二进制字符串的 SHA-224 哈希值。 | sha224('abc'::bytea) → \x23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7 |
sha256 ( bytea ) → bytea | 计算二进制字符串的 SHA-256 哈希值。 | sha256('abc'::bytea) → \xba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad |
sha384 ( bytea ) → bytea | 计算二进制字符串的 SHA-384 哈希值。 | sha384('abc'::bytea) → \xcb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 |
sha512 ( bytea ) → bytea | 计算二进制字符串的 SHA-512 哈希值。 | sha512('abc'::bytea) → \xddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f |
substr ( bytes bytea, start integer [, count integer ] ) → bytea | 提取从第 start 个字节开始,长度为 count 个字节的 bytes 子字符串。 | substr('\x1234567890'::bytea, 3, 2) → \x5678 |
函数 get_byte 和 set_byte 将二进制字符串的第一个字节编号为字节 0。函数 get_bit 和 set_bit 在每个字节内从右侧编号位;例如,位 0 是第一个字节的最低有效位,位 15 是第二个字节的最高有效位。
由于历史原因,函数 md5 返回类型为 text 的十六进制编码值,而 SHA-2 函数返回类型为 bytea。使用函数 encode 和 decode 在两者之间进行转换。例如,写 encode(sha256('abc'), 'hex') 以获得十六进制编码的文本表示,或 decode(md5('abc'), 'hex') 以获得 bytea 值。
将字符串在不同字符集(编码)之间转换的函数,以及用文本形式表示任意二进制数据的函数,如表 文本/二进制字符串转换函数所示。对于这些函数,类型为 text 的参数或结果以数据库的默认编码表示,而类型为 bytea 的参数或结果则以另一个参数命名的编码表示。
| 函数 | 描述 | 示例 |
|---|---|---|
convert ( bytes bytea, src_encoding name, dest_encoding name ) → bytea | 将以 src_encoding 编码表示的文本的二进制字符串转换为以 dest_encoding 编码表示的二进制字符串。 | convert('text_in_utf8', 'UTF8', 'LATIN1') → \x746578745f696e5f75746638 |
convert_from ( bytes bytea, src_encoding name ) → text | 将以 src_encoding 编码表示的文本的二进制字符串转换为 text 类型的字符串。将 src_encoding 编码的内容转换为数据库编码的 text。 | convert_from('text_in_utf8', 'UTF8') → text_in_utf8 |
convert_to ( text text, dest_encoding name ) → bytea | 将数据库编码的 text 字符串转换为以编码 dest_encoding 编码的二进制字符串。 | convert_to('some_text', 'UTF8') → \x736f6d655f74657874 |
encode ( bytes bytea, format text ) → text | 将二进制数据编码为文本表示形式;支持的 format 值为:base64、escape、hex。 | encode('123\000\001', 'base64') → MTIzAAE= |
decode ( string text, format text ) → bytea | 从文本表示形式解码二进制数据;支持的 format 值与 encode 相同。 | decode('MTIzAAE=', 'base64') → \x3132330001 |
bin ( numeric N ) → text | 返回数字 N 的二进制字符串。 | bin(5) → 101 |
encode 和 decode 函数支持以下文本格式:
-
base64:
base64格式是 RFC 2045 第 6.8 节的格式。根据 RFC,编码行在 76 个字符处中断。但是,换行符只用于行末,而不是 MIME CRLF 行末标记。decode函数忽略回车符、换行符、空格和制表符。否则,当decode提供无效的 base64 数据时,包括尾随填充不正确时,会引发错误。 -
escape:
escape转义格式将零字节和高位设置的字节转换为八进制转义序列(\nnn),并加倍反斜杠。其他字节值按字面表示。如果反斜杠后面没有跟第二个反斜杠或三个八进制数字,则decode函数将引发一个错误;它接受其他字节值保持不变。 -
hex:
hex格式将每 4 位数据表示为一个十六进制数字,0到f,先写入每个字节的高位数字。encode函数以小写形式输出a-f十六进制数字。因为最小的数据单位是 8 位,所以encode始终返回偶数个字符。decode函数接受a-f字符的大写或小写形式。当decode给出无效的十六进制数据时(包括给出奇数个字符时),将引发错误。
另请参见聚合函数中的 string_agg。
7. 位串函数和操作符
本节介绍用于检查和操作位串的函数和操作符,即类型 bit 和 bit varying 的值。(虽然这些表中只提到了 bit 类型,但 bit varying 类型的值可以互换使用。)位串支持表 比较操作符中显示的常规比较操作符,以及表 位串操作符中显示的操作符。
| 操作符 | 说明 | 示例 |
|---|---|---|
bit || bit → bit | 连接 | B'10001' || B'011' → 10001011 |
bit & bit → bit | 按位与(输入必须具有相等的长度) | B'10001' & B'01101' → 00001 |
bit | bit → bit | 按位或(输入必须具有相等的长度) | B'10001' | B'01101' → 11101 |
bit # bit → bit | 按位异或(输入必须具有相等的长度) | B'10001' # B'01101' → 11100 |
~ bit → bit | 按位取反 | ~ B'10001' → 01110 |
bit << integer → bit | 按位左移(字符串长度保持不变) | B'10001' << 3 → 01000 |
bit >> integer → bit | 按位右移(字符串长度保持不变) | B'10001' >> 2 → 00100 |
一些适用于二进制字符串的函数也适用于位字符串,如表 位字符串函数所示。
| 函数 | 描述 | 示例 |
|---|---|---|
bit_count ( bit ) → bigint | 返回位字符串中设置的位数(也称为“popcount”)。 | bit_count(B'10111') → 4 |
bit_length ( bit ) → integer | 返回位字符串中的位数。 | bit_length(B'10111') → 5 |
length ( bit ) → integer | 返回位字符串中的位数。 | length(B'10111') → 5 |
octet_length ( bit ) → integer | 返回位字符串中的字节数。 | octet_length(B'1011111011') → 2 |
overlay ( bits bit PLACING newsubstring bit FROM start integer [ FOR count integer ] ) → bit | 用 newsubstring 替换从第 start 位开始并延伸 count 位的 bits 子字符串。如果省略 count,则默认为 newsubstring 的长度。 | overlay(B'01010101010101010' placing B'11111' from 2 for 3) → 0111110101010101010 |
position ( substring bit IN bits bit ) → integer | 返回指定的 substring 在 bits 中的第一个起始索引,如果不存在,则返回零。 | position(B'010' in B'000001101011') → 8 |
substring ( bits bit [ FROM start integer ] [ FOR count integer ] ) → bit | 提取从第 start 位开始的 bits 子字符串,如果指定,则在 count 位后停止。提供至少一个 start 和 count。 | substring(B'110010111111' from 3 for 2) → 00 |
get_bit ( bits bit, n integer ) → integer | 从位字符串中提取第 n 位;第一个(最左边)位为第 0 位。 | get_bit(B'101010101010101010', 6) → 1 |
set_bit ( bits bit, n integer, newvalue integer ) → bit | 将位字符串中的第 n 位设置为 newvalue;第一个(最左边的)位是位 0。 | set_bit(B'101010101010101010', 6, 0) → 101010001010101010 |
此外,可以将整数值强制转换为类型 bit。将整数转换为 bit(n) 会复制最右边的 n 位。将整数转换为比整数本身宽的位字符串将在左侧进行符号扩展。一些例子:
44::bit(10) 0000101100
44::bit(3) 100
cast(-44 as bit(12)) 111111010100
'1110'::bit(4)::integer 14
请注意,仅强制转换为“bit”意味着转换为 bit(1),因此仅会提供整数的最低有效位。
8. 模式匹配
UXsinoDB 提供了三种不同的模式匹配方法:传统的 SQL LIKE 操作符、较新的 SIMILAR TO 操作符(在 SQL:1999 中添加),以及 POSIX 风格的正则表达式。除了基本的“这个字符串是否与这个模式匹配?”操作符外,还有可用于提取或替换匹配子字符串以及在匹配位置拆分字符串的函数。
提示
如果您的模式匹配需求超出了这个范围,请考虑使用 Perl 或 Tcl 编写用户定义函数。
注意
虽然大多数正则表达式搜索可以非常快速地执行,但是可以构造需要任意量的时间和内存来处理的正则表达式。谨慎接受来自敌对来源的正则表达式搜索模式。如果必须这样做,建议设置语句超时。
使用 SIMILAR TO 模式进行搜索具有相同的安全风险,因为 SIMILAR TO 提供了与 POSIX 风格的正则表达式相同的功能。
与其他两个选项相比,LIKE 搜索更简单,因此在可能存在敌对模式来源的情况下更安全。
所有三种类型的模式匹配操作符都不支持非确定性排序规则。如果需要,请将不同的排序规则应用于表达式以解决此限制。
8.1. LIKE
string LIKE pattern [ESCAPE escape-character]
string NOT LIKE pattern [ESCAPE escape-character]
LIKE 表达式返回 true,如果 string 与提供的 pattern 匹配。(如预期的,如果 LIKE 返回 true,则 NOT LIKE 表达式返回 false,反之亦然。等价的表达式是 NOT (string LIKE pattern)。)
如果 pattern 不包含百分号或下划线,则该模式仅表示字符串本身;在这种情况下,LIKE 的作用类似于等于操作符。下划线(_)在 pattern 中代表(匹配)任何单个字符;百分号(%)匹配任何零个或多个字符的序列。
一些例子:
'abc' LIKE 'abc' true
'abc' LIKE 'a%' true
'abc' LIKE '_b_' true
'abc' LIKE 'c' false
LIKE 模式匹配始终覆盖整个字符串。因此,如果希望在字符串的任何位置匹配序列,则模式必须以百分号开头和结尾。
要匹配字面下划线或百分号而不匹配其他字符,必须在 pattern 中的相应字符之前加上转义字符。默认的转义字符是反斜杠,但可以通过使用 ESCAPE 子句选择不同的转义字符。要匹配转义字符本身,请写两个转义字符。
注意
如果您关闭了standard_conforming_strings,则在文本字符串常量中编写的任何反斜杠都需要加倍。
还可以通过编写 ESCAPE '' 来选择不使用转义字符。这实际上禁用了转义机制,这使得无法关闭模式中下划线和百分号的特殊含义。
根据 SQL 标准,省略 ESCAPE 意味着没有转义字符(而不是默认为反斜杠),并且不允许使用长度为零的 ESCAPE 值。UXsinoDB 在这方面的行为因此略有不同于标准。
关键字 ILIKE 可以用来代替 LIKE,根据活动语言环境使匹配不区分大小写。这不是 SQL 标准,但是是 UXsinoDB 的扩展。
操作符 ~~ 等同于 LIKE,~~* 对应于 ILIKE。还有 !~~ 和 !~~* 操作符,分别表示 NOT LIKE 和 NOT ILIKE。所有这些操作符都是 UXsinoDB 特有的。您可能会在 EXPLAIN 输出和类似的地方看到这些操作符名称,因为解析器实际上将 LIKE 等转换为这些操作符。
在 UXsinoDB 语法中,短语 LIKE、ILIKE、NOT LIKE 和 NOT ILIKE 通常被视为操作符;例如,它们可以在 expression operator ANY (subquery) 构造中使用,尽管 ESCAPE 子句不能在其中包含。在某些晦涩的情况下,可能需要使用底层操作符名称。
还请参阅以 ^@ 开头的操作符和相应的 starts_with() 函数,它们在需要仅匹配字符串开头的情况下非常有用。
表 LIKE 支持参数类型
| 参数一(string) | 参数二(pattern) | 返回值 |
|---|---|---|
| 字符类型 | 日期类型(日期、时间戳) | 布尔类型 |
| 字符类型 | 时间类型 | 布尔类型 |
| 字符类型 | 时间间隔类型 | 布尔类型 |
| 字符类型 | 字符类型 | 布尔类型 |
| 字符类型 | 数字类型 | 布尔类型 |
| 数字类型 | 字符类型 | 布尔类型 |
| 数字类型 | 数字类型 | 布尔类型 |
| 日期类型(日期、时间戳) | 字符类型 | 布尔类型 |
| 日期类型(日期、时间戳) | 日期类型(日期、时间戳) | 布尔类型 |
| 时间类型 | 字符类型 | 布尔类型 |
| 时间类型 | 时间类型 | 布尔类型 |
| 时间间隔类型 | 字符类型 | 布尔类型 |
| 时间间隔类型 | 时间间隔类型 | 布尔类型 |
bytea 类型 | bytea 类型 | 布尔类型 |
8.2. SIMILAR TO 正则表达式
string SIMILAR TO pattern [ESCAPE escape-character]
string NOT SIMILAR TO pattern [ESCAPE escape-character]
SIMILAR TO 操作符根据其模式是否与给定字符串匹配返回 true 或 false。它类似于 LIKE,但它使用 SQL 标准的正则表达式定义来解释模式。SQL 正则表达式是 LIKE 符号和常见(POSIX)正则表达式符号之间的奇特交叉。
与 LIKE 一样,SIMILAR TO 操作符仅在其模式与整个字符串匹配时才成功;这与常见的正则表达式行为不同,其中模式可以匹配字符串的任何部分。与 LIKE 一样,SIMILAR TO 使用 _ 和 % 作为通配符字符,分别表示任何单个字符和任何字符串(这些与 POSIX 正则表达式中的 . 和 .* 相当)。
除了从 LIKE 借用的这些设施外,SIMILAR TO 还支持从 POSIX 正则表达式中借用的这些模式匹配元字符:
|表示交替(两个备选项之一)。*表示重复前一个项目零次或多次。+表示重复前一个项目一次或多次。?表示前一个字符重复零次或一次。{m}表示前一个字符重复m次。{m,}表示前一个字符重复m次或更多次。{m,n}表示前一个字符至少重复m次,但不超过n次。- 括号
()可以用于将项分组为单个逻辑项。 - 方括号
[...]指定一个字符类,就像在 POSIX 正则表达式中一样。
请注意,句点(.)不是 SIMILAR TO 的元字符。
与 LIKE 一样,反斜杠可以禁用任何这些元字符的特殊含义。可以使用不同的转义字符指定 ESCAPE,或者通过编写 ESCAPE '' 来禁用转义功能。
根据 SQL 标准,省略 ESCAPE 表示没有转义字符(而不是默认为反斜杠),并且不允许使用零长度的 ESCAPE 值。因此,UXsinoDB 在这方面的行为略有不同。
另一个非标准扩展是,在转义字符后面跟一个字母或数字可以访问为 POSIX 正则表达式定义的转义序列;请参见表 正则表达式字符转义、表 正则表达式类别缩写转义和表 正则表达式约束转义。
一些示例:
'abc' SIMILAR TO 'abc' true
'abc' SIMILAR TO 'a' false
'abc' SIMILAR TO '%(b|d)%' true
'abc' SIMILAR TO '(b|c)%' false
'-abc-' SIMILAR TO '%\mabc\M%' true
'xabcy' SIMILAR TO '%\mabc\M%' false
带有三个参数的 substring 函数提供了匹配 SQL 正则表达式模式的子字符串提取。该函数可以按照标准 SQL 语法编写:
substring(string similar pattern escape escape-character)
或使用现已过时的 SQL:1999 语法:
substring(string from pattern for escape-character)
也可以使用三个参数的普通函数形式:
substring(string, pattern, escape-character)
与 SIMILAR TO 一样,指定的模式必须完全匹配数据字符串,否则函数将失败并返回 null。为了指示匹配数据子字符串感兴趣的模式部分,模式应包含两个转义字符后跟双引号(")。成功匹配时返回在这些分隔符之间的模式部分的文本匹配。转义双引号分隔符实际上将 substring 的模式分成三个独立的正则表达式;例如,在任何三个部分中的竖线(|)仅影响该部分。此外,当有关数据字符串匹配哪个模式的多少存在任何歧义时,这三个正则表达式中的第一个和第三个被定义为匹配最小可能的文本,而不是最大可能的文本。(在 POSIX 术语中,第一个和第三个正则表达式被强制为非贪婪的。)
作为 SQL 标准的扩展,UXsinoDB 允许只有一个转义双引号分隔符,在这种情况下,第三个正则表达式被视为空;或没有分隔符,在这种情况下,第一个和第三个正则表达式被视为空。
以下是一些示例,其中 #" 用于分隔返回字符串:
substring('foobar' similar '%#"o_b#"%' escape '#') oob
substring('foobar' similar '#"o_b#"%' escape '#') NULL
8.3. POSIX 正则表达式
表 正则表达式匹配操作符列出了使用 POSIX 正则表达式进行模式匹配的可用操作符。
| 操作符 | 描述 | 示例 |
|---|---|---|
text ~ text → boolean | 字符串与正则表达式匹配,区分大小写。 | 'thomas' ~ 't.*ma' → t |
text ~* text → boolean | 字符串与正则表达式匹配,不区分大小写。 | 'thomas' ~* 'T.*ma' → t |
text !~ text → boolean | 字符串与正则表达式不匹配,区分大小写。 | 'thomas' !~ 't.*max' → t |
text !~* text → boolean | 字符串与正则表达式不匹配,不区分大小写。 | 'thomas' !~* 'T.*ma' → f |
POSIX 正则表达式提供了比 LIKE 和 SIMILAR TO 操作符更强大的模式匹配方式。许多 Unix 工具,如 egrep、sed 或 awk 使用与此处描述的类似的模式匹配语言。
正则表达式是一个字符序列,是一组字符串(一个正则集)的缩写定义。如果一个字符串是由正则表达式描述的正则集的成员,则称该字符串与正则表达式匹配。与 LIKE 一样,除非它们是正则表达式语言中的特殊字符,否则模式字符与字符串字符完全匹配,但正则表达式使用不同于 LIKE 的特殊字符。与 LIKE 模式不同的是,正则表达式允许匹配字符串中的任何位置,除非正则表达式明确地锚定到字符串的开头或结尾。
一些例子:
'abcd' ~ 'bc' true
'abcd' ~ 'a.c' true — 点号匹配任何字符
'abcd' ~ 'a.*d' true — * 重复前面的模式项
'abcd' ~ '(b|x)' true — | 表示或,括号分组
'abcd' ~ '^a' true — ^ 锚定到字符串的开头
'abcd' ~ '^(b|c)' false — 除了锚定,会匹配
POSIX 模式语言在下面有更详细的描述。
带有两个参数的 substring 函数 substring(string from *pattern* ) 提供了提取与 POSIX 正则表达式模式匹配的子字符串。如果没有匹配,则返回 null,否则返回匹配模式的文本的第一部分。但是,如果模式包含任何括号,则返回匹配第一个括号子表达式(左括号最先出现的子表达式)的文本部分。如果您想在其中使用括号而不触发此异常,可以将括号放在整个表达式周围。如果您需要在要提取的子表达式之前在模式中使用括号,请参见下面描述的非捕获括号。
一些例子:
substring('foobar' from 'o.b') oob
substring('foobar' from 'o(.)b') o
regexp_count 函数计算 POSIX 正则表达式模式在字符串中匹配的次数。它的语法为 regexp_count(string, pattern [, start [, flags ]])。pattern 在 string 中进行搜索,通常从字符串的开头开始,但如果提供了 start 参数,则从该字符索引开始。flags 参数是一个可选的文本字符串,其中包含零个或多个单字母标志,可以更改函数的行为。例如,在 flags 中包含 i 指定不区分大小写匹配。支持的标志在表 ARE 嵌入选项字母中描述。
一些例子:
regexp_count('ABCABCAXYaxy', 'A.') 3
regexp_count('ABCABCAXYaxy', 'A.', 1, 'i') 4
regexp_instr 函数返回 POSIX 正则表达式模式与字符串匹配的第 N 个匹配的起始或结束位置,如果没有这样的匹配,则返回零。它的语法为 regexp_instr(string, pattern [, start [, N [, endoption [, flags [, subexpr ]]]]])。pattern 在 string 中进行搜索,通常从字符串的开头开始,但如果提供了 start 参数,则从该字符索引开始。如果指定了 N,则定位模式的第 N 个匹配,否则定位第一个匹配。如果省略 endoption 参数或将其指定为零,则函数返回匹配的第一个字符的位置。否则,endoption 必须为一,函数返回匹配后面的字符的位置。flags 参数是一个可选的文本字符串,其中包含零个或多个单字母标志,可以更改函数的行为。支持的标志在表 ARE 嵌入选项字母中描述。对于包含括号子表达式的模式,subexpr 是一个整数,指示感兴趣的子表达式:结果标识与该子表达式匹配的子字符串的位置。子表达式按其前导括号的顺序编号。当省略或设置为零时,subexpr 的结果将标识整个匹配的位置,而不考虑括号子表达式。
以下是一些示例:
regexp_instr('number of your street, town zip, FR', '[^,]+', 1, 2) → 23
regexp_instr('ABCDEFGHI', '(c..)(...)', 1, 1, 0, 'i', 2) → 6
regexp_like 函数检查 POSIX 正则表达式模式是否在字符串中出现匹配,返回布尔值 true 或 false。它的语法为 regexp_like(string, pattern [, flags ])。flags 参数是一个可选的文本字符串,包含零个或多个单字母标志,用于更改函数的行为。支持的标志在表 ARE 嵌入选项字母中描述。如果未指定标志,则此函数与 ~ 操作符具有相同的结果。如果仅指定了 i 标志,则其结果与 ~* 操作符相同。
以下是一些示例:
regexp_like('Hello World', 'world') false
regexp_like('Hello World', 'world', 'i') true
regexp_match 函数返回一个文本数组,其中包含与字符串中 POSIX 正则表达式模式的第一个匹配项相匹配的子字符串。它的语法为 regexp_match(string, pattern [, flags ])。如果没有匹配项,则结果为 NULL。如果找到匹配项,并且 pattern 不包含括号子表达式,则结果是一个包含与整个模式匹配的子字符串的单个元素文本数组。如果找到匹配项,并且 pattern 包含括号子表达式,则结果是一个文本数组,其中第 n 个元素是与 pattern 的第 n 个括号子表达式匹配的子字符串(不包括“非捕获”括号;有关详细信息,请参见下文)。flags 参数是一个可选的文本字符串,包含零个或多个单字母标志,用于更改函数的行为。支持的标志在表 ARE 嵌入选项字母中描述。
以下是一些示例:
SELECT regexp_match('foobarbequebaz', 'bar.*que');
regexp_match
--------------
{barbeque}
(1 row)
SELECT regexp_match('foobarbequebaz', '(bar)(beque)');
regexp_match
--------------
{bar,beque}
(1 row)
提示
在通常情况下,如果您只想要整个匹配的子字符串或无匹配项的NULL,最好的解决方案是使用regexp_substr()。但是,regexp_substr()仅存在于 UXsinoDB 2122 及以上版本中。在旧版本中工作时,您可以提取第一个元素。regexp_match()的结果,例如:SELECT (regexp_match('foobarbequebaz', 'bar.*que'))[1]; regexp_match -------------- barbeque (1 row)
regexp_matches 函数返回一个文本数组集合,其中包含与 POSIX 正则表达式模式匹配的子字符串的匹配。它具有与 regexp_match 相同的语法。如果没有匹配,则此函数不返回行,如果有匹配且未给出 g 标志,则返回一行,如果有 N 个匹配并且给出了 g 标志,则返回 N 行。每个返回的行都是一个文本数组,其中包含整个匹配的子字符串或与 pattern 的括号子表达式匹配的子字符串,就像上面为 regexp_match 所描述的那样。regexp_matches 接受在表 ARE 嵌入选项字母中显示的所有标志,以及命令它返回所有匹配项而不仅仅是第一个匹配项的 g 标志。
一些例子:
SELECT regexp_matches('foo', 'not there');
regexp_matches
----------------
(0 rows)
SELECT regexp_matches('foobarbequebazilbarfbonk', '(b[^b]+)(b[^b]+)', 'g');
regexp_matches
----------------
{bar,beque}
{bazil,barf}
(2 rows)
提示
在大多数情况下,应使用带有g标志的regexp_matches(),因为如果您只想要第一个匹配项,则使用regexp_match()更容易和更有效。但是,regexp_match()仅存在于 UXsinoDB 版本 2112 及以上版本中。在旧版本中工作时,常见的技巧是将regexp_matches()调用放在子选择中,例如:SELECT col1, (SELECT regexp_matches(col2, '(bar)(beque)')) FROM tab;如果有匹配,则会产生文本数组,如果没有匹配,则会产生
NULL,与regexp_match()的行为相同。如果没有子选择,则对于没有匹配的表行,此查询将根本不产生输出,这通常不是所需的行为。
regexp_replace 函数提供了对与 POSIX 正则表达式模式匹配的子字符串进行替换的新文本的替换。它的语法为 regexp_replace(source, pattern, replacement [, start [, N ]] [, flags ])。(请注意,除非指定了 start,否则无法指定 N,但可以在任何情况下给出 flags。)如果没有与 pattern 匹配的内容,则返回 source 字符串。如果有匹配,则返回 source 字符串,其中 replacement 字符串替换了匹配的子字符串。replacement 字符串可以包含 \n,其中 n 是 1 到 9,指示应插入与模式的第 n 个括号子表达式匹配的源子字符串,并且它可以包含 \& 以指示应插入与整个模式匹配的子字符串。如果需要在替换文本中放置文字反斜杠,请写 \\。在字符串中搜索模式 pattern,通常从字符串开头开始,但如果提供了 start 参数,则从该字符索引开始。默认情况下,仅替换模式的第一个匹配项。如果指定了 N 并且大于零,则替换模式的第 N 个匹配项。如果给出了 g 标志,或者如果指定的 N 为零,则替换从 start 位置或之后的所有匹配项。(当指定 N 时,g 标志被忽略。)flags 参数是一个可选的文本字符串,其中包含零个或多个单字母标志,这些标志改变函数的行为。支持的标志(尽管不包括 g)在表 ARE 嵌入选项字母中描述。
一些例子:
regexp_replace('foobarbaz', 'b..', 'X')
fooXbaz
regexp_replace('foobarbaz', 'b..', 'X', 'g')
fooXX
regexp_replace('foobarbaz', 'b(..)', 'X\1Y', 'g')
fooXarYXazY
regexp_replace('A UXsinoDB function', 'a|e|i|o|u', 'X', 1, 0, 'i')
X UXsXnXDB fXnctXXn
regexp_replace('A UXsinoDB function', 'a|e|i|o|u', 'X', 1, 3, 'i')
A UXsinXDB function
regexp_split_to_table 函数使用 POSIX 正则表达式模式作为分隔符来拆分字符串。它的语法为 regexp_split_to_table(string, pattern[, flags])。如果没有与模式匹配的内容,则函数返回字符串。如果至少有一个匹配项,对于每个匹配项,它返回从最后一个匹配项(或字符串的开头)到匹配项的开头的文本。当没有更多匹配项时,它返回从最后一个匹配项的结尾到字符串的结尾的文本。flags 参数是一个可选的文本字符串,其中包含零个或多个单字母标志,这些标志改变函数的行为。regexp_split_to_table 支持在表 ARE 嵌入选项字母中描述的标志。
regexp_split_to_array 函数的行为与 regexp_split_to_table 相同,只是 regexp_split_to_array 将其结果作为 text 数组返回。它的语法为 regexp_split_to_array(string, pattern[, flags])。参数与 regexp_split_to_table 相同。
以下是一些示例:
SELECT foo FROM regexp_split_to_table('the quick brown fox jumps over the lazy dog', '\s+') AS foo;
foo
-------
the
quick
brown
fox
jumps
over
the
lazy
dog
(9 rows)
SELECT regexp_split_to_array('the quick brown fox jumps over the lazy dog', '\s+');
regexp_split_to_array
-----------------------------------------------
{the,quick,brown,fox,jumps,over,the,lazy,dog}
(1 row)
SELECT foo FROM regexp_split_to_table('the quick brown fox', '\s*') AS foo;
foo
-----
t
h
e
q
u
i
c
k
b
r
o
w
n
f
o
x
(16 rows)
正如最后一个示例所示,regexp 分割函数会忽略出现在字符串开头或结尾或紧接在前一个匹配项之后的零长度匹配项。这与其他 regexp 函数实现的严格匹配定义相反,但在实践中通常是最方便的行为。其他软件系统(如 Perl)使用类似的定义。
regexp_substr 函数返回与 POSIX 正则表达式模式匹配的子字符串,如果没有匹配,则返回 NULL。它的语法是 regexp_substr(string, pattern [, start [, N [, flags [, subexpr ]]]])。在 string 中搜索 pattern,通常从字符串开头开始,但如果提供了 start 参数,则从该字符索引开始。如果指定了 N,则返回模式的第 N 个匹配项,否则返回第一个匹配项。flags 参数是一个可选的文本字符串,包含零个或多个单字母标志,用于更改函数的行为。支持的标志在表 ARE 嵌入选项字母中描述。对于包含括号子表达式的模式,subexpr 是一个整数,表示感兴趣的子表达式:结果是匹配该子表达式的子字符串。子表达式按其前导括号的顺序编号。当省略或为零时,结果是整个匹配项,而不考虑括号子表达式。
以下是一些示例:
regexp_substr('number of your street, town zip, FR', '[^,]+', 1, 2) → 'town zip'
regexp_substr('ABCDEFGHI', '(c..)(...)', 1, 1, 'i', 2) → 'FGH'
8.3.1. 正则表达式细节
正则表达式是使用 Henry Spencer 编写的软件包实现的。下面的正则表达式描述大部分是从他的手册中直接复制的。
UXsinoDB 的正则表达式使用 POSIX 1003.2 定义的两种形式:扩展正则表达式或 ERE(大致与 egrep 相同),以及基本的正则表达式或 BRE(大致与 ed 相同)。UXsinoDB 支持这两种形式,并实现了一些不在 POSIX 标准中的扩展,但由于它们在编程语言(如 Perl 和 Tcl)中的可用性而变得广泛使用。在这份文档中,使用这些非 POSIX 扩展的正则表达式称为高级正则表达式或 ARE。ARE 几乎是 ERE 的一个完全超集,但 BRE 有几个符号不兼容(以及更加有限)。我们首先描述 ARE 和 ERE 形式,注意仅适用于 ARE 的功能,然后描述 BRE 的区别。
注意
UXsinoDB 始终最初假定正则表达式遵循 ARE 规则。但是,可以通过在 RE 模式前面添加嵌入选项来选择更有限的 ERE 或 BRE 规则,如正则表达式元语法所述。这对于与期望完全符合 POSIX 1003.2 规则的应用程序兼容非常有用。
正则表达式定义为一个或多个由 | 分隔的分支。它匹配与分支之一匹配的任何内容。
一个分支是零个或多个量化的原子或约束条件,串联在一起。它匹配第一个的匹配,后跟第二个的匹配等等;空分支匹配空字符串。
量化原子是一个可能后跟单个量化器的原子。没有量化器,它匹配原子的匹配。使用量化器时,它可以匹配一些原子的匹配。原子可以是表 正则表达式原子中显示的任何可能性。
约束条件匹配空字符串,但仅在满足特定条件时匹配。约束条件可以在可以使用原子的地方使用,但不能后跟量化器。简单的约束条件如表 正则表达式约束条件所示;稍后将描述一些其他约束条件。
| 原子 | 描述 |
|---|---|
( re ) | (其中 re 是任何正则表达式)匹配一个对 re 的匹配,匹配将为可能的报告被记下 |
(?: re ) | 同上,但是匹配不会为了报告而被记下(一个“非捕获”圆括号集)(只对 ARE) |
. | 匹配任意单个字符 |
[ chars ] | 一个方括号表达式,匹配 chars 中的任意一个 |
\ k | (其中 k 是一个非字母数字字符)匹配一个被当作普通字符看待的特定字符,例如,\\ 匹配一个反斜线字符 |
\ c | 其中 c 是一个字母数字(可能跟着其它字符),它是一个逃逸,(仅对 ARE;在 ERE 和 BRE 中,它匹配 c) |
{ | 如果后面跟着一个字符,而不是数字,那么就匹配左花括弧 {;如果跟着一个数字,那么它是 range 的开始(见下文) |
x | 其中 x 是一个没有其它意义的单个字符,则匹配该字符 |
RE 不能以反斜杠(\)结尾。
注意
如果您关闭了standard_conforming_strings,您在文字字符串常量中编写的任何反斜杠都需要加倍。
表 正则表达式量词
| 量词 | 匹配 |
|---|---|
* | 原子的 0 个或多个匹配序列 |
+ | 原子的 1 个或多个匹配序列 |
? | 原子的 0 个或 1 个匹配序列 |
{ m } | 原子的确切 m 个匹配序列 |
{ m ,} | 原子的 m 个或更多匹配序列 |
{ m , n } | 原子的 m 到 n 的序列(包括)匹配;m 不能超过 n |
*? | 非贪婪模式的 * |
+? | 非贪婪模式的 + |
?? | 非贪婪模式的 ? |
{ m }? | 非贪婪模式的 { m } |
{ m ,}? | 非贪婪模式的 { m ,} |
{ m , n }? | 非贪婪模式的 { m , n } |
使用 {...} 的形式被称为边界。边界中的数字 m 和 n 是无符号十进制整数,其可取值范围为 0 到 255(包括 0 和 255)。
非贪婪量词(仅在 ARE 中可用)匹配与其对应的普通(贪婪)量词相同的可能性,但是它们更喜欢匹配最少的次数而不是最多的次数。
注意
量词不能紧接着另一个量词,例如,**是无效的。量词不能开始一个表达式或子表达式,也不能跟在^或|后面。
| 约束条件 | 描述 |
|---|---|
^ | 匹配字符串的开头 |
$ | 匹配字符串的结尾 |
(?= re ) | 正向预查 在任何匹配 re 的子字符串开始的地方匹配(仅在 ARE 中可用) |
(?! re ) | 负向预查 在任何不匹配 re 的子字符串开始的地方匹配(仅在 ARE 中可用) |
(?<= re ) | 正向回顾 在任何匹配 re 的子字符串结束的地方匹配(仅在 ARE 中可用) |
(?<! re ) | 负向回顾 在任何不匹配 re 的子字符串结束的地方匹配(仅在 ARE 中可用) |
前瞻和后顾约束不能包含反向引用(参见正则表达式转义),并且其中的所有括号都被视为非捕获。
8.3.2. 括号表达式
括号表达式是一个包含在 [] 中的字符列表。它通常匹配列表中的任何单个字符(参见下文)。如果列表以 ^ 开头,则匹配列表中其余部分中的任何单个字符不是。如果列表中的两个字符被 - 分隔,则这是这两个字符之间(包括)的所有字符的完整范围的简写,例如,在 ASCII 中,[0-9] 匹配任何十进制数字。两个范围共享一个端点是非法的,例如,a-c-e。范围非常依赖于排序顺序,因此可移植程序应避免依赖它们。
要在列表中包含文字 ],请将其作为第一个字符(在使用 ^ 的情况下)。要包含文字 -,请将其作为第一个或最后一个字符,或作为范围的第二个端点。要将文字 - 用作范围的第一个端点,请将其括在 [. 和 .] 中,使其成为排序元素(见下文)。除了这些字符、一些使用 [ 的组合(见下一段)和转义(仅适用于 AREs)之外,所有其他特殊字符在括号表达式中失去其特殊意义。特别地,在遵循 ERE 或 BRE 规则时,\ 不是特殊的,尽管在 AREs 中它是特殊的(作为引入转义)。
在括号表达式中,用 [. 和 .] 括起来的排序元素(一个字符、一个按照单个字符排序的多字符序列或一个排序序列名称)代表该排序元素的字符序列。该序列被视为括号表达式列表的单个元素。这允许包含多字符排序元素的括号表达式匹配多个字符,例如,如果排序序列包括一个 ch 排序元素,则 RE [[.ch.]]*c 匹配 chchcc 的前五个字符。
注意
UXsinoDB 目前不支持多字符排序元素。此信息描述了可能的未来行为。
在括号表达式中,用 [= 和 =] 括起来的排序元素是一个等价类,代表所有等价于该元素的所有排序元素的字符序列,包括它本身。(如果没有其他等价的排序元素,则处理方式就像封闭分隔符是 [. 和 .]。)例如,如果 o 和 ^ 是等价类的成员,则 [[=o=]]、[[=^=]] 和 [o^] 都是同义词。一个等价类不能作为范围的端点。
在方括号表达式中,用 [: 和 :] 括起来的字符类名称表示属于该类的所有字符的列表。字符类不能用作范围的端点。POSIX 标准定义了这些字符类名称:alnum(字母和数字)、alpha(字母)、blank(空格和制表符)、cntrl(控制字符)、digit(数字)、graph(可打印字符,不包括空格)、lower(小写字母)、print(可打印字符,包括空格)、punct(标点符号)、space(任何空格)、upper(大写字母)和 xdigit(十六进制数字)。这些标准字符类的行为通常在 7 位 ASCII 字符集中的字符在各个平台上保持一致。给定的非 ASCII 字符是否被认为属于这些类取决于用于正则表达式函数或操作符的排序,或默认情况下取决于数据库的 LC_CTYPE 区域设置。非 ASCII 字符的分类在不同名称的区域设置中甚至在不同平台上也可能有所不同。(但 C 区域设置从不认为任何非 ASCII 字符属于这些类。)除了这些标准字符类之外,UXsinoDB 定义了 word 字符类,它与 alnum 加下划线(_)字符相同,以及 ascii 字符类,其中包含完全 7 位 ASCII 集。
有两种特殊情况的括号表达式:[[:<:]] 和 [[:>:]] 是约束条件,分别在单词的开头和结尾匹配空字符串。单词定义为不以单词字符为前导或后继的单词字符序列。单词字符是属于 word 字符类的任何字符,即任何字母、数字或下划线。这是一种扩展,与但不指定为 POSIX 1003.2 兼容,并且应谨慎在旨在可移植到其他系统的软件中使用。下面描述的约束条件转义通常更可取;它们不更标准,但更容易输入。
8.3.3. 正则表达式转义
转义是以 \ 开头,后跟字母数字字符的特殊序列。转义有几种类型:字符输入,类简写,约束条件转义和反向引用。\ 后跟字母数字字符但不构成有效转义的是 ARE 中不合法的。在 ERE 中,没有转义:在方括号表达式之外,\ 后跟字母数字字符仅表示该字符作为普通字符,而在方括号表达式之内,\ 是普通字符。(这是 ERE 和 ARE 之间唯一的实际不兼容性。)
字符转义用于更轻松地在正则表达式中指定非打印和其他不方便的字符。它们在表 正则表达式字符转义中列出。
类别缩写转义提供了一些常用字符类别的缩写。它们在表 正则表达式类别缩写转义中列出。
约束转义是一个约束,如果满足特定条件,则匹配空字符串,写成一个转义符。它们在表 正则表达式约束转义中列出。
反向引用(\n)匹配与前一个括号子表达式匹配的相同字符串,该括号子表达式由数字 n 指定(请参见表 正则表达式反向引用)。例如,([bc])\1 匹配 bb 或 cc,但不匹配 bc 或 cb。子表达式必须完全在反向引用之前出现在 RE 中。子表达式按其前导括号的顺序编号。非捕获括号不定义子表达式。反向引用仅考虑由引用的子表达式匹配的字符串字符,而不考虑其中包含的任何约束。例如,(^\d)\1 将匹配 22。
| 转义符 | 描述 |
|---|---|
\a | 警报(响铃)字符,如 C 语言 |
\b | 退格,如 C 语言 |
\B | 反斜杠(\)的同义词,以帮助减少反斜杠的重复使用 |
\cX | (其中 X 是任何字符)其低 5 位与 X 相同,其他位都为零的字符 |
\e | 其排序序列名称为 ESC 的字符,否则为八进制值为 033 的字符 |
\f | 换页符,如 C 语言 |
\n | 换行符,如 C 语言 |
\r | 回车符,如 C 语言 |
\t | 水平制表符,如 C 语言 |
\uwxyz | (其中 wxyz 正好是四个十六进制数字)其十六进制值为 0xwxyz |
\Ustuvwxyz | (其中 stuvwxyz 正好是八个十六进制数字)十六进制值为 0xstuvwxyz 的字符 |
\v | 垂直制表符,如 C 语言中 |
\xhhh | (其中 hhh 是任意一串十六进制数字)十六进制值为 0xhhh 的字符(无论使用多少个十六进制数字,都只表示一个字符) |
\0 | 值为 0(空字节)的字符 |
\xy | (其中 xy 是两个八进制数字,且不是反向引用)八进制值为 0xy 的字符 |
\xyz | (其中 xyz 是三个八进制数字,且不是反向引用)八进制值为 0xyz 的字符 |
十六进制数字为 0-9,a-f,A-F。八进制数字为 0-7。
指定 ASCII 范围(0-127)之外的数值的数字字符转义在数据库编码上有不同的含义。当编码为 UTF-8 时,转义值等同于 Unicode 代码点,例如 \u1234 表示字符 U+1234。对于其他多字节编码,字符转义通常只指定字符的字节值的串联。如果转义值在数据库编码中没有对应的合法字符,则不会引发错误,但它永远不会匹配任何数据。
字符转义始终被视为普通字符。例如,\135 在 ASCII 中表示 ],但 \135 不会终止括号表达式。
| 转义 | 描述 |
|---|---|
\d | 匹配任何数字,如 [[:digit:]] |
\s | 匹配任何空格字符,如 [[:space:]] |
\w | 匹配任何单词字符,如 [[:word:]] |
\D | 匹配任何非数字,如 [^[:digit:]] |
\S | 匹配任何非空格字符,如 [^[:space:]] |
\W | 匹配任何非单词字符,如 [^[:word:]] |
类别速记转义也适用于括号表达式,尽管上面显示的定义在该上下文中不完全符合语法规则。例如,[a-c\d] 等价于 [a-c[:digit:]]。
| 转义符 | 描述 |
|---|---|
\A | 仅匹配字符串的开头 |
\m | 仅匹配单词的开头 |
\M | 仅匹配单词的结尾 |
\y | 仅匹配单词的开头或结尾 |
\Y | 仅匹配不是单词开头或结尾的位置 |
\Z | 仅匹配字符串的结尾 |
单词的定义如 [[:<:]] 和 [[:>:]] 规范中所述。约束转义符不能在括号表达式中使用。
| 转义符 | 描述 |
|---|---|
\ m | (其中 m 是一个非零数字)反向引用第 m 个子表达式 |
\ mnn | (其中 m 是一个非零数字,nn 是一些数字,且十进制值 mnn 不大于到目前为止看到的闭合捕获括号的数量)反向引用第 mnn 个子表达式 |
注意
八进制字符输入转义符和反向引用之间存在固有的歧义,可以通过以下启发式方法解决,如上所示。前导零始终表示八进制转义符。单个非零数字,后面没有其他数字,始终被视为反向引用。不以零开头的多位数字序列,如果在适当的子表达式之后出现(即数字在反向引用的合法范围内),则被视为反向引用,否则被视为八进制转义符。
8.3.4. 正则表达式元语法
除了上面描述的主要语法之外,还有一些特殊形式和杂项语法设施可用。
正则表达式可以以两个特殊的指示符前缀之一开头。如果正则表达式以 ***: 开头,则其余部分被视为 ARE。(在 UXsinoDB 中,这通常没有影响,因为假定正则表达式是 ARE。)但是如果在正则表达式函数的 flags 参数中指定了 ERE 或 BRE 模式,则会产生影响。如果一个 RE 以 ***= 开头,则 RE 的其余部分被视为一个字面字符串,其中所有字符都被视为普通字符。
一个 ARE 可以以嵌入选项开头:一个序列 (?xyz)(其中 xyz 是一个或多个字母字符)指定影响 RE 其余部分的选项。这些选项覆盖了先前确定的任何选项,特别是它们可以覆盖由正则表达式操作符暗示的大小写敏感行为,或者正则表达式函数的 flags 参数。可用的选项字母在表 ARE 嵌入选项字母中显示。请注意,这些相同的选项字母用于正则表达式函数的 flags 参数。
| 选项 | 描述 |
|---|---|
b | RE 的其余部分是 BRE |
c | 区分大小写匹配(覆盖操作符类型) |
e | RE 的其余部分是 ERE |
i | 不区分大小写匹配(覆盖操作符类型) |
m | n 的历史同义词 |
n | 换行符敏感匹配 |
p | 部分换行符敏感匹配 |
q | RE 的其余部分是一个字面(“引用”)字符串,所有普通字符 |
s | 非换行符敏感匹配(默认) |
t | 紧凑语法(默认;见下文) |
w | 反向部分换行符敏感(“奇怪的”)匹配 |
x | 扩展语法(见下文) |
嵌入选项在终止序列的 ) 处生效。它们只能出现在 ARE 的开头(在任何 ***: 指示符之后,如果有的话)。
除了通常的 RE 语法,其中所有字符都是重要的,还有一种扩展的语法,可以通过指定嵌入的 x 选项来使用。在扩展语法中,RE 中的空格字符被忽略,所有在 # 和下一个换行符之间的字符也被忽略。以下换行符(或 RE 的结尾)允许对复杂的 RE 进行分段和注释。基本规则有三个例外:
- 以反斜杠
\为前缀的空格字符或#会被保留。 - 方括号表达式中的空格或
#会被保留。 - 多字符符号(如
(?:)中不能出现空格和注释。
为此,空格字符包括空格、制表符、换行符和属于 space 字符类的任何字符。
最后,在 ARE 中,除了方括号表达式外,序列 (?#ttt)(其中 ttt 是不包含 ) 的任何文本)是一个注释,完全被忽略。同样,这在多字符符号(如 (?:)的字符之间是不允许的。这些注释更多地是历史遗留物而不是有用的设施,它们的使用已被弃用;请改用扩展语法。
如果初始的 ***= 指示符指定将用户的输入视为字面字符串而不是 RE,则这些元语法扩展都不可用。
8.3.5. 正则表达式匹配规则
如果一个 RE 可以匹配给定字符串的多个子字符串,则 RE 匹配最早出现在字符串中的子字符串。如果 RE 可以匹配从该点开始的多个子字符串,则取最长可能的匹配或最短可能的匹配,具体取决于 RE 是贪婪的还是非贪婪的。
RE 是贪婪还是非贪婪由以下规则确定:
- 大多数原子和所有约束都没有贪婪属性(因为它们无法匹配可变数量的文本)。
- 在 RE 周围添加括号不会改变其贪婪性。
- 具有固定重复量子化器(
{m}或{m}?)的量化原子具有与原子本身相同的贪婪性(可能没有)。 - 具有其他正常量化器的量化原子(包括
{m,n},其中m等于n)是贪婪的(偏爱最长匹配)。 - 具有非贪婪量化器的量化原子(包括
{m,n}?,其中m等于n)是非贪婪的(偏爱最短匹配)。 - 分支——即没有顶层
|操作符的 RE——具有与其中第一个具有贪婪属性的量化原子相同的贪婪性。 - 由两个或更多分支连接的 RE,使用
|操作符总是贪婪的。
以上规则不仅将贪婪属性与单个量化原子相关联,还将贪婪属性与包含量化原子的分支和整个 RE 相关联。这意味着匹配是以使分支或整个 RE 匹配最长或最短的子字符串作为整体的方式进行的。一旦确定了整个匹配的长度,匹配任何特定子表达式的部分是基于该子表达式的贪婪属性确定的,其中在 RE 中较早开始的子表达式优先于后面开始的子表达式。
以下是这意味着什么的示例:
SELECT SUBSTRING('XY1234Z', 'Y*([0-9]{1,3})');
Result: 123
SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
Result: 1
在第一种情况下,RE 作为整体是贪婪的,因为 Y* 是贪婪的。它可以从 Y 开始匹配,并匹配从那里开始的最长可能字符串,即 Y123。输出是其中括号部分,即 123。在第二种情况下,RE 作为整体是非贪婪的,因为 Y*? 是非贪婪的。它可以从 Y 开始匹配,并匹配从那里开始的最短可能字符串,即 Y1。子表达式 [0-9]{1,3} 是贪婪的,但它不能改变关于整个匹配长度的决定;因此,它被迫只匹配 1。
简而言之,当一个 RE 包含贪婪和非贪婪子表达式时,总匹配长度要么尽可能长,要么尽可能短,具体取决于分配给整个 RE 的属性。分配给子表达式的属性仅影响它们相对于彼此允许“吃掉”的匹配量。
量词符 {1,1} 和 {1,1}? 可用于分别强制子表达式或整个 RE 的贪婪或非贪婪。当您需要整个 RE 具有与其元素推导出的贪婪属性不同的贪婪属性时,这非常有用。例如,假设我们正在尝试将包含一些数字的字符串分离为数字和它们之前和之后的部分。我们可以尝试像这样做:
SELECT regexp_match('abc01234xyz', '(.*)(\d+)(.*)');
Result: {abc0123,4,xyz}
这没用:第一个 .* 是贪婪的,因此它尽可能多地“吃掉”,留下 \d+ 在最后一个可能的位置匹配,即最后一个数字。我们可以尝试通过使其非贪婪来修复它:
SELECT regexp_match('abc01234xyz', '(.*?)(\d+)(.*)');
Result: {abc,0,""}
这也不起作用,因为现在整个 RE 都是非贪婪的,因此它尽可能快地结束整个匹配。我们可以通过强制整个 RE 为贪婪来获得我们想要的结果:
SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}');
Result: {abc,01234,xyz}
单独控制 RE 的整体贪婪性和其组件的贪婪性允许在处理可变长度模式时具有很大的灵活性。
在决定什么是更长或更短的匹配时,匹配长度是以字符为单位而不是排序元素来衡量的。空字符串被认为比没有匹配更长。例如:bb* 匹配 abbbc 的三个中间字符;(week|wee)(night|knights) 匹配 weeknights 的所有十个字符;当 (.*).* 与 abc 匹配时,括号内的子表达式匹配所有三个字符;当 (a*)* 与 bc 匹配时,整个 RE 和括号内的子表达式都匹配一个空字符串。
如果指定了不区分大小写的匹配,则其效果就像字母表中所有大小写区分都消失了一样。当一个存在于多个大小写中的字母作为普通字符出现在方括号表达式之外时,它实际上被转换为包含两个大小写的方括号表达式,例如,x 变成了 [xX]。当它出现在方括号表达式中时,它的所有大小写对应项都被添加到方括号表达式中,例如,[x] 变成了 [xX],[^x] 变成了 [^xX]。
如果指定了对换行符敏感的匹配,则 . 和使用 ^ 的方括号表达式将永远不会匹配换行符(因此匹配不会跨越行,除非 RE 显式包括换行符),并且 ^ 和 $ 将在换行符之后和之前匹配一个空字符串,除了在字符串的开头和结尾匹配。但是,ARE 转义 \A 和 \Z 仍然只匹配字符串的开头或结尾。此外,字符类简写 \D 和 \W 将匹配换行符,而不管此模式如何。(在 UXsinoDB 之前版本中,它们在对换行符敏感的模式下不匹配换行符。写 [^[:digit:]] 或 [^[:word:]] 以获得旧行为。)
如果指定了部分对换行符敏感的匹配,则与对换行符敏感的匹配一样,这会影响 . 和方括号表达式,但不会影响 ^ 和 $。
如果指定了反向部分对换行符敏感的匹配,则与对换行符敏感的匹配一样,这会影响 ^ 和 $,但不会影响 . 和方括号表达式。这不是非常有用,但提供对称性。
8.3.6. 限制和兼容性
在此实现中,没有对 RE 的长度施加特定的限制。然而,旨在高度可移植的程序不应使用超过 256 字节的 RE,因为符合 POSIX 标准的实现可能会拒绝接受这样的 RE。
ARE 与 POSIX ERE 实际上不兼容的唯一特性是,它在括号表达式中不失其特殊意义。所有其他 ARE 特性使用的语法在 POSIX ERE 中是非法的,或者具有未定义或未指定的效果;同样,BRE 和 ERE 的控制器的 *** 语法也在 POSIX 语法之外。
许多 ARE 扩展是从 Perl 借来的,但是一些已经被更改以清除它们,还有一些 Perl 扩展不存在。值得注意的不兼容性包括 \b、\B、缺乏对尾部换行的特殊处理,对受换行敏感匹配影响的内容添加补括号表达式,对前向/后向约束中的括号和后向引用的限制,以及最长/最短匹配(而不是首次匹配)匹配语义。
8.3.7. 基本正则表达式
BRE 与 ERE 在几个方面不同。在 BRE 中,|、+ 和 ? 是普通字符,没有相应的功能。边界的分隔符是 \{ 和 \},{ 和 } 本身是普通字符。用于嵌套子表达式的括号是 \( 和 \),( 和 ) 本身是普通字符。^ 是普通字符,除非在 RE 的开头或括号化的子表达式的开头,$ 是普通字符,除非在 RE 的结尾或括号化的子表达式的结尾,如果 * 出现在 RE 的开头或括号化的子表达式的开头(在可能的前导 ^ 之后),则是普通字符。最后,可以使用单个数字反向引用,\< 和 \> 是 [[:<:]] 和 [[:>:]] 的同义词;在 BRE 中不提供其他转义。
8.3.8. 与 XQuery 的区别 (LIKE_REGEX)
自 SQL:2008 以来,SQL 标准包括正则表达式操作符和函数,根据 XQuery 正则表达式标准执行模式匹配:
LIKE_REGEXOCCURRENCES_REGEXPOSITION_REGEXSUBSTRING_REGEXTRANSLATE_REGEX
UXsinoDB 目前不实现这些操作符和函数。您可以在表 正则表达式函数对应关系中显示的每种情况下获得近似等效的功能。(在此表中,双方的各种可选子句已被省略。)
| SQL 标准 | UXsinoDB |
|---|---|
string LIKE_REGEX pattern | regexp_like(string, pattern) 或 string ~ pattern |
OCCURRENCES_REGEX(pattern IN string) | regexp_count(string, pattern) |
POSITION_REGEX(pattern IN string) | regexp_instr(string, pattern) |
SUBSTRING_REGEX(pattern IN string) | regexp_substr(string, pattern) |
TRANSLATE_REGEX(pattern IN string WITH replacement) | regexp_replace(string, pattern, replacement) |
类似于 UXsinoDB 提供的正则表达式函数也可在许多其他 SQL 实现中使用,而 SQL 标准函数则没有被广泛实现。每个实现中正则表达式语法的一些细节可能会有所不同。
SQL 标准操作符和函数使用 XQuery 正则表达式,这与上面描述的 ARE 语法非常接近。现有基于 POSIX 的正则表达式功能与 XQuery 正则表达式之间的显着差异包括:
- 不支持 XQuery 字符类减法。使用以下内容仅匹配英语辅音字母的示例:
[a-z-[aeiou]]。 - 不支持 XQuery 字符类速记符
\c、\C、\i和\I。 - 不支持使用
\p{UnicodeProperty}或反向\P{UnicodeProperty}的 XQuery 字符类元素。 - POSIX 根据当前语言环境(可以通过将
COLLATE子句附加到操作符或函数来控制)解释字符类,例如\w(请参见表 正则表达式类别缩写转义)。XQuery 通过引用 Unicode 字符属性来指定这些类,因此只有在使用相同的语言环境时才能获得等效的行为。遵循 Unicode 规则的语言环境。 - SQL 标准(不是 XQuery 本身)试图为比 POSIX 更多的“换行符”变体提供服务。上面描述的敏感换行匹配选项仅将 ASCII NL(
\n)视为换行符,但是 SQL 要求我们将 CR(\r)、CRLF(\r\n)(Windows 风格的换行符)以及一些仅限于 Unicode 的字符(如 LINE SEPARATOR(U+2028))也视为换行符。值得注意的是,根据 SQL,.和\s应将\r\n视为一个字符而不是两个字符。 - 在表 正则表达式字符转义中描述的字符输入转义中,XQuery 仅支持
\n、\r和\t。 - XQuery 不支持方括号表达式中的字符类的
[:name:]语法。 - XQuery 没有前瞻或后顾约束,也没有在表 正则表达式约束转义中描述的任何约束转义。
- 在正则表达式元语法中描述的元语法形式在 XQuery 中不存在。
- XQuery 定义的正则表达式标志字母与 POSIX 的选项字母相关但不相同表 ARE 嵌入选项字母。虽然
i和q选项的行为相同,但其他选项则不同:- XQuery 的
s(允许点匹配换行符)和m(允许^和$在换行符处匹配)标志提供了与 POSIX 的n、p和w标志相同的行为,但它们与 POSIX 的s和m标志的行为不匹配。特别要注意的是,在 POSIX 中,点匹配换行符是默认行为,但在 XQuery 中不是。 - XQuery 的
x(忽略模式中的空格)标志与 POSIX 的扩展模式标志明显不同。POSIX 的x标志还允许#在模式中开始注释,并且 POSIX 不会忽略反斜杠后的空格字符。
- XQuery 的
8.4. REGEXP 和 RLIKE 正则表达式
string REGEXP pattern
string NOT REGEXP pattern
string RLIKE pattern
string NOT RLIKE pattern
如果该 string 匹配了提供的 pattern,那么 REGEXP(或 RLIKE)表达式返回真(和预期的一样,如果 REGEXP(或 RLIKE)返回真,那么 NOT REGEXP(或 RLIKE)表达式返回假,反之亦然。一个等效的表达式是 NOT (string REGEXP(或 RLIKE) pattern)。
如果 pattern 不包含百分号或者下划线,那么该模式只代表它本身的串;这时候 REGEXP 的行为就象等号操作符。在 pattern 里的下划线(_)代表(匹配)任何单个字符;而一个百分号(%)匹配任何零或更多个字符的序列。
示例如下所示。
'Michael!' REGEXP '.*' true
'new*\n*line' REGEXP 'new\\*.\\*line' false
'a' REGEXP '^[a-d]' true
注意
string和pattern为空串时进行regexp,mysql模式下会报错,结果如下所示。uxdb=# select 1 regexp ''; ERROR: Got error 'empty (sub)expression' from pattern
9. 数据类型格式化函数
UXsinoDB 格式化函数提供了一组强大的工具,用于将各种数据类型(日期/时间、整数、浮点数、数值)转换为格式化字符串,并将格式化字符串转换为特定的数据类型。表 格式化函数列出了这些函数。这些函数都遵循一个通用的调用约定:第一个参数是要格式化的值,第二个参数是定义输出或输入格式的模板。
| 函数 | 描述 | 示例 |
|---|---|---|
to_char ( text ) → text | 将 text/varchar 参数的文本格式转化为字符串 | to_char('test varchar'::varchar); → test varchar |
to_char ( varchar ) → text | 将 varchar 参数的文本格式转化为字符串 | to_char('1.1'::text); → 1.1 |
to_char ( timestamp, text ) → textto_char ( timestamp with time zone, text ) → text | 将时间戳按照给定的格式转换为字符串。 | to_char(timestamp '2002-04-20 17:31:12.66', 'HH12:MI:SS') → 05:31:12 |
to_char ( interval, text ) → text | 将时间间隔按照给定的格式转换为字符串。 | to_char(interval '15h 2m 12s', 'HH24:MI:SS') → 15:02:12 |
to_char ( numeric_type, text ) → text | 根据给定的格式将数字转换为字符串;适用于 integer、bigint、numeric、real、double precision。 | to_char(125, '999') → 125to_char(125.8::real, '999D9') → 125.8to_char(-125.8, '999D99S') → 125.80- |
to_date ( timestamp without time zone ) → date | 将不带时区的时间戳转化为 date。 | to_date('2022-08-17 12:15:35'::timestamp) → 2022-08-17 12:15:35 |
to_date ( timestamp with time zone ) → date | 将带时区的时间戳转化为 date。 | to_date('2022-08-17 12:15:35'::timestamptz) → 2022-08-17 12:15:35 |
to_date ( text, text ) → date | 根据给定的格式将字符串转换为日期。 | to_date('05 Dec 2000', 'DD Mon YYYY') → 2000-12-05 |
to_date ( text default text on conversion error, text ) → date | 把第一个参数和 default 子句中的参数分别与指定格式进行匹配,返回对应的值。 | select to_date('2013-02-03' default '2023-01-01' on conversion error,'yyyy-mm-dd') from dual; |
to_date ( text default text on conversion error ) → date | 不指定格式,把第一个参数和 default 子句中的参数按照默认格式进行匹配,返回对应的值。 | select to_date('2013-02-03 12:12:36' default '2013-11-25 15:25:49' on conversion error) from dual; |
to_number ( text, text ) → numeric | 根据给定的格式将字符串转换为数字。 | to_number('12,454.8-', '99G999D9S') → -12454.8 |
to_timestamp ( text, text ) → timestamp with time zone | 根据给定的格式将字符串转换为时间戳。 | to_timestamp('05 Dec 2000', 'DD Mon YYYY') → 2000-12-05 00:00:00-05 |
to_number ( double precision ) → numeric | 双精度浮点型转化为数字。 | SELECT to_number(123.456::double precision); → 123.456 |
to_number ( numeric, numeric ) → numeric | 数字按照指定数字的格式转化为数字。 | SELECT to_number(1210.73::numeric, 9999.99::numeric); → 1210.73 |
to_number ( text, numeric ) → numeric | 文本按照指定数字的格式转化为数字。 | SELECT TO_NUMBER(2222.22::text, 999); → 222 |
to_number ( numeric, text ) → numeric | 数字按照指定文本格式转化为数字。 | SELECT to_number(1210.73::numeric, 9999.99::text); → 1210.73 |
to_number ( text, text ) → numeric | 把字符串转成数字。 | to_number('12,454.8-', '99G999D9S') |
to_number ( expr1, fmt ) → numeric | 将输入的 expr1 按照 fmt 格式输出,将十六进制字符和数字转化为十进制数字。 | to_number('1,234', 'XXXX') |
to_number ( double precision, numeric ) → numeric | 双精度浮点数按照指定数字的格式转化为数字。 | SELECT to_number(1210.73::double precision, 9999.99::numeric); → 1210.73 |
to_number ( double precision, text ) → numeric | 双精度浮点型数按照指定文本的格式转化为数字。 | SELECT to_number(1210.73::double precision, 9999.99::text); → 1210.73 |
to_timestamp_tz ( c[, format] ) → timestamptz | 将符合日期/时间格式化模式的字符串,根据 format 指定格式转换为带时区的时间戳。 | to_timestamp_tz('2022-10-13 17:13:18 +07','YYYY-MM-DD HH24:MI:SS TZH:TZM') |
rand ( [numeric] ) → double | 将返回一个 [0,1] 之间一个随机浮点数。 | rand(-9223372036854775808) |
to_dsinterval ( strings ) → interval day to second | 将字符串转换为 INTERVAL DAY TO SECOND 类型(得到一个时间间隔,几天几小时几分几秒)。strings 可支持 char、nchar、varchar、varchar2、nvarchar2、text 等类型。支持默认值,格式是 DEFAULT 'xxx' ON CONVERSION ERROR,默认值类型和参数类型相同,默认值只能是字符串,不能使用函数返回值,表的列值。 | to_dsinterval('10 00:00:01')to_dsinterval( 'xxxx' DEFAULT 'xxxx' ON CONVERSION ERROR ) |
validate_conversion ( expr AS typename ) → numericvalidate_conversion ( expr AS typename, fmt ) → numeric | 判断是否可以将 expr 转换为指定的数据类型,若能被成功转换为指定类型,则返回 1,否则返回 0。其中 typename 支持的类型有 DATE、INTERVAL DAY TO SECOND、INTERVAL YEAR TO MONTH、NUMBER、TIMESTAMP、TIMESTAMP WITH TIME ZONE。 | select validate_conversion('2023/12/1' as date) from dual; → 1select validate_conversion('16-Feb-09' as date, 'DD-Mon-YY') from dual; → 1 |
提示
to_timestamp和to_date存在的目的是处理无法通过简单转换进行转换的输入格式。对于大多数标准日期/时间格式,只需将源字符串强制转换为所需的数据类型即可,这样做更容易。同样,对于标准数字表示,to_number是不必要的。
在 to_char 输出模板字符串中,有一些模式会被识别并根据给定的值替换为适当格式的数据。任何不是模板模式的文本都会被简单地复制。同样,在输入模板字符串(用于其他函数)中,模板模式标识要由输入数据字符串提供的值。如果模板字符串中有字符不是模板模式,则输入数据字符串中相应的字符会被简单地跳过(无论它们是否等于模板字符串字符)。
表 日期/时间格式化的模板模式显示了可用于格式化日期和时间值的模板模式。
| 模式 | 描述 |
|---|---|
HH | 小时(01-12) |
HH12 | 小时(01-12) |
HH24 | 小时(00-23) |
MI | 分钟(00-59) |
SS | 秒(00-59) |
MS | 毫秒(000-999) |
US | 微秒(000000-999999) |
FF1 | 十分之一秒(0-9) |
FF2 | 百分之一秒(00-99) |
FF3 | 毫秒(000-999) |
FF4 | 十分之一毫秒(0000-9999) |
FF5 | 百分之一毫秒(00000-99999) |
FF6 | 微秒(000000-999999) |
SSSS,SSSSS | 距午夜的秒数(0-86399) |
AM,am,PM 或 pm | 上午/下午指示符(无句号) |
A.M.,a.m.,P.M. 或 p.m. | 上午/下午指示符(有句号) |
Y,YYY | 年(4 位或更多位数字),带逗号 |
YYYY | 年(4 位或更多位数字) |
YYY | 年的最后 3 位数字 |
YY | 年的最后 2 位数字 |
Y | 年的最后 1 位数字 |
IYYY | ISO 8601 年份(4 位或更多位数字) |
IYY | ISO 8601 年份的最后 3 位数字 |
IY | ISO 8601 年份的最后 2 位数字 |
I | ISO 8601 年份的最后 1 位数字 |
BC,bc,AD 或 ad | 纪元指示符(无句号) |
B.C.,b.c.,A.D. 或 a.d. | 纪元指示符(有句号) |
MONTH | 全大写月份名称(空格填充至 9 个字符) |
Month | 首字母大写的月份名称(空格填充至 9 个字符) |
month | 全小写月份名称(空格填充至 9 个字符) |
MON | 缩写的全大写月份名称(英文为 3 个字符,本地化长度不同) |
Mon | 缩写的首字母大写月份名称(英文为 3 个字符,本地化长度不同) |
mon | 缩写的全小写月份名称(英文为 3 个字符,本地化长度不同) |
MM | 月份数字(01-12) |
DAY | 全大写的星期几名称(空格填充至 9 个字符) |
Day | 首字母大写的星期几名称(空格填充至 9 个字符) |
day | 全小写的星期名称(左侧填充空格至 9 个字符) |
DY | 缩写的大写星期名称(英语为 3 个字符,本地化长度可能不同) |
Dy | 缩写的首字母大写星期名称(英语为 3 个字符,本地化长度可能不同) |
dy | 缩写的小写星期名称(英语为 3 个字符,本地化长度可能不同) |
DDD | 一年中的第几天(001-366) |
IDDD | ISO 8601 周编号年中的第几天(001-371;一年的第一天是第一个 ISO 周的星期一) |
DD | 月中的第几天(01-31) |
D | 星期几,从星期日(1)到星期六(7) |
ID | ISO 8601 星期几,从星期一(1)到星期日(7) |
W | 月中的第几周(1-5)(第一周从月份的第一天开始) |
WW | 年中的第几周(1-53)(第一周从年份的第一天开始) |
IW | ISO 8601 周编号年中的第几周(01-53;一年的第一个星期四在第 1 周) |
CC | 世纪(2 位数)(21 世纪从 2001-01-01 开始) |
J | 儒略日(自公元前 4714 年 11 月 24 日当地午夜起的整数天数) |
Q | 季度 |
RM | 大写罗马数字月份(I-XII;I 表示 1 月) |
rm | 小写罗马数字月份(i-xii;i 表示 1 月) |
TZ | 大写时区缩写(仅在 to_char 中支持) |
tz | 小写时区缩写(仅在 to_char 中支持) |
TZH | 时区小时数 |
TZM | 时区分钟数 |
OF | 与 UTC 的时区偏移量(仅在 to_char 中支持) |
SYYYY | 用字符 s 匹配公元前后 +、- 标志 |
可以对任何模板模式应用修饰符以改变其行为。例如,FMMonth 是带有 FM 修饰符的 Month 模式。表 日期/时间格式化的模板模式修饰符显示了日期/时间格式化的修饰符模式。
| 修饰符 | 描述 | 示例 |
|---|---|---|
FM 前缀 | 填充模式(抑制前导零和填充空格) | FMMonth |
TH 后缀 | 大写序数后缀 | DDTH,例如 12TH |
th 后缀 | 小写序数后缀 | DDth,例如 12th |
FX 前缀 | 固定格式全局选项 | FX Month DD Day |
TM 前缀 | 翻译模式(根据 lc_time 使用本地化的日期和月份名称) | TMMonth |
SP 后缀 | 拼写模式(未实现) | DDSP |
日期/时间格式化的使用说明:
-
FM抑制前导零和尾随空格,否则会添加以使模式的输出成为固定宽度。在 UXsinoDB 中,FM仅修改下一个规范,而在 Oracle 中,FM影响所有后续规范,并且重复的FM修饰符切换填充模式的开关。 -
TM抑制尾随空格,无论是否指定了FM。 -
to_timestamp和to_date忽略输入中的字母大小写;因此,例如MON、Mon和mon都接受相同的字符串。使用TM修饰符时,大小写折叠按照函数输入排序规则执行。 -
to_timestamp和to_date跳过输入字符串开头和日期时间值周围的多个空格,除非使用了FX选项。例如,to_timestamp(' 2000 JUN', 'YYYY MON')和to_timestamp('2000 - JUN', 'YYYY-MON')可行,但to_timestamp('2000 JUN', 'FXYYYY MON')返回错误,因为to_timestamp仅期望单个空格。必须将FX指定为模板中的第一项。 -
to_timestamp和to_date中模板字符串中的分隔符(空格或非字母/非数字字符)匹配输入字符串中的任何单个分隔符或跳过,除非使用FX选项。例如,to_timestamp('2000JUN', 'YYYY///MON')和to_timestamp('2000/JUN', 'YYYY MON')可行,但to_timestamp('2000//JUN', 'YYYY/MON')返回错误,因为输入字符串中的分隔符数量超过模板中的分隔符数量。如果指定了
FX,则模板字符串中的分隔符在输入字符串中精确匹配一个字符。但请注意,输入字符串字符不必与模板字符串中的分隔符相同。例如,to_timestamp('2000/JUN','FXYYYY MON')可行,但to_timestamp('2000/JUN', 'FXYYYY MON')返回错误,因为模板字符串中的第二个空格消耗了输入字符串中的第二个空格。 -
to_timestamp_tz和to_timestamp的功能相同,输出的时区信息为默认的会话时区,时间为输出的时间转化为会话时区的时间,暂不支持NLS_TIMESTAMP_TZ_FORMAT参数来控制输出,在 uxdb 标准模式下不支持带时区('20031213181318-8:00')或不带时区('20031213181318')日期时间格式字符串输出,兼容模式下可以正常输出不带时区的字符串,如:'20031213181318',当参数一与参数二的时间格式字符不完全匹配时,如参数一缺少日的格式,输出时会自动补 1(年月日)和补 0(时分秒),会输出错误结果,不建议此类用法,如下所示。uxdb=# select to_timestamp_tz('2022-10-13 17:13:18','YYYY-MM HH24:MI:SS'); to_timestamp_tz ------------------------ 2022-10-01 13:17:13-07 (1 row) -
TZH模板模式可以匹配带符号的数字。如果没有FX选项,减号可能会有歧义,并且可能会被解释为分隔符。解决这种歧义的方法如下:如果模板字符串中TZH前的分隔符数量小于输入字符串中减号前的分隔符数量,则减号被解释为TZH的一部分。否则,减号被视为值之间的分隔符。例如,to_timestamp('2000 -10', 'YYYY TZH')将-10匹配到TZH,但是to_timestamp('2000 -10', 'YYYY TZH')将10匹配到TZH。 -
to_char模板中允许普通文本,并且会直接输出。您可以将子字符串放在双引号中,以强制将其解释为文字文本,即使它包含模板模式。例如,在'"Hello Year "YYYY'中,YYYY将被年份数据替换,但是Year中的单个Y不会被替换。在to_date、to_number和to_timestamp中,文字文本和双引号字符串会导致跳过包含在字符串中的字符数;例如"XX"跳过两个输入字符(无论它们是否为XX)。提示
在 UXsinoDB 之前版本中,可以使用非字母或非数字字符跳过输入字符串中的任意文本。例如,to_timestamp('2000y6m1d','yyyy-MM-DD')曾经可以工作。现在,您只能使用字母字符来实现这个目的。例如,to_timestamp('2000y6m1d','yyyytMMtDDt')和to_timestamp('2000y6m1d', 'yyyy"y"MM"m"DD"d"')跳过y、m和d。 -
如果要在输出中包含双引号,必须在其前面加上反斜杠,例如
'\"YYYYMonth\"'。反斜杠在双引号字符串之外不起作用。在双引号字符串中,反斜杠会导致下一个字符被直接取出,无论它是什么(但是,除非下一个字符是双引号或另一个反斜杠,否则这没有特殊效果)。 -
在
to_timestamp和to_date中,如果年份格式规范少于四位数字,例如YYY,并且提供的年份少于四位数字,则年份将调整为最接近 2020 年的年份,例如95变成 1995。 -
在
to_timestamp和to_date中,负数年份被视为公元前。如果同时写入负数年份和显式的BC字段,则再次得到公元后。年份为零的输入被视为公元前 1 年。 -
在
to_timestamp和to_date中,YYYY转换在处理超过 4 位数字的年份时有限制。您必须在YYYY后使用一些非数字字符或模板,否则年份始终被解释为 4 位数字。例如(使用年份 20000):to_date('200001131','YYYYMMDD')将被解释为一个 4 位数的年份;相反,使用年份后的非数字分隔符,如to_date('20000-1131','YYYY-MMDD')或to_date('20000Nov31', 'YYYYMonDD')。 -
在
to_timestamp和to_date中,如果有YYY、YYYY或Y,YYY字段,则接受但忽略CC(世纪)字段。如果将CC与YY或Y一起使用,则结果将计算为指定世纪的那一年。如果指定了世纪但没有年份,则假定为该世纪的第一年。 -
在
to_timestamp和to_date中,接受工作日名称或数字(DAY、D和相关字段类型),但在计算结果时将其忽略。季度(Q)字段也是如此。 -
在
to_timestamp和to_date中,可以用两种方式指定 ISO 8601 周编号日期(与公历日期不同):- 年份、周数和工作日:例如,
to_date('2006-42-4', 'IYYY-IW-ID')返回日期2006-10-19。如果省略工作日,则假定为 1(星期一)。 - 年份和年内日数:例如,
to_date('2006-291','IYYY-IDDD')也返回2006-10-19。
尝试使用 ISO 8601 周编号字段和公历日期字段的混合输入日期是不合理的,会导致错误。ISO 8601 周编号年的上下文中,“月”或“月中日”这样的概念是没有意义的。在公历年的上下文中,ISO 周没有意义。
注意
虽然to_date会拒绝混合使用公历和 ISO 周编号日期字段,但to_char不会,因为输出格式规范(如YYYY-MM-DD (IYYY-IDDD))可能很有用。但是要避免编写类似于IYYY-MM-DD的内容;这会在年初产生令人惊讶的结果。(有关更多信息,请参见 EXTRACT, date_part。) - 年份、周数和工作日:例如,
-
在
to_timestamp中,毫秒(MS)或微秒(US)字段用作小数点后的秒数位。例如,to_timestamp('12.3','SS.MS')不是 3 毫秒,而是 300,因为转换将其视为 12 + 0.3 秒。因此,对于格式SS.MS,输入值12.3、12.30和12.300指定了相同数量的毫秒。要获得三毫秒,必须编写12.003,转换将其视为 12 + 0.003 = 12.003 秒。以下是一个更复杂的示例:to_timestamp('15:12:02.020.001230','HH24:MI:SS.MS.US')是 15 小时 12 分钟 2 秒 + 20 毫秒 + 0.001230 秒 1230 微秒 = 2.021230 秒。 -
to_char(...,'ID')的星期几编号与extract(isodow from...)函数相匹配,但to_char(...,'D')的星期几编号与extract(dow from...)函数不匹配。 -
to_char(interval)将HH和HH12格式化为 12 小时制,例如零小时和 36 小时都输出为12,而HH24输出完整的小时值,可以超过interval值中的 23。
表 数字格式化的模板模式显示了可用于格式化数字值的模板模式。
| 模式 | 描述 |
|---|---|
9 | 数字位置(如果不重要,则可以删除) |
0 | 数字位置(即使不重要,也不会被删除) |
.(句点) | 小数点 |
,(逗号) | 组(千位)分隔符 |
PR | 用尖括号括起来的负值 |
S | 锚定到数字的符号(使用区域设置) |
L | 货币符号(使用区域设置) |
D | 小数点(使用区域设置) |
G | 组分隔符(使用区域设置) |
MI | 指定位置的减号(如果数字小于 0) |
PL | 指定位置的加号(如果数字大于 0) |
SG | 指定位置的加/减号 |
RN | 罗马数字(输入介于 1 和 3999 之间) |
TH 或 th | 序数后缀 |
V | 移位指定数量的数字(见注释) |
EEEE | 科学计数法的指数 |
数字格式化的使用说明:
-
0指定将始终打印的数字位置,即使它包含前导/尾随零。9也指定数字位置,但如果它是前导零,则将其替换为空格,而如果它是尾随零并且指定了填充模式,则将其删除。(对于to_number(),这两个模式字符是等效的。) -
模式字符
S、L、D和G表示当前区域设置定义的符号、货币符号、小数点和千位分隔符字符。和lc_numeric一起使用。模式字符 period 和 comma 表示这些确切的字符,具有小数点和千位分隔符的含义,不考虑语言环境。 -
如果在
to_char()的模式中没有明确指定符号,一个列将被保留用于符号,并且它将被锚定到(出现在)数字的左侧。如果S出现在某些9的左侧,它也将被锚定到数字上。 -
使用
SG、PL或MI格式化的符号不会锚定到数字上;例如,to_char(-12, 'MI9999')会产生'- 12',但to_char(-12, 'S9999')会产生' -12'。(Oracle 实现不允许在9之前使用MI,而是要求9在MI之前。) -
TH不会转换小于零的值,也不会转换小数。 -
PL、SG和TH是 UXsinoDB 的扩展。 -
在
to_number中,如果使用了非数据模板模式,如L或TH,则相应数量的输入字符将被跳过,无论它们是否匹配模板模式,除非它们是数据字符(即数字、符号、小数点或逗号)。例如,TH将跳过两个非数据字符。 -
V与to_char一起,将输入值乘以10^n,其中n是V后面的数字的数量。使用to_number的V以类似的方式进行除法运算。to_char和to_number不支持将V与小数点组合使用(例如,不允许使用99.9V99)。 -
EEEE(科学计数法)不能与除数字和小数点模式之外的任何其他格式化模式或修饰符组合使用,并且必须位于格式字符串的末尾(例如,9.99EEEE是一个有效的模式)。
可以对任何模板模式应用某些修饰符以改变其行为。例如,FM99.99 是带有 FM 修饰符的 99.99 模式。
表 数字格式化的模板模式修饰符显示了数字格式化的修饰符模式。
| 修饰符 | 描述 | 示例 |
|---|---|---|
FM 前缀 | 填充模式(去除尾随零和填充空格) | FM99.99 |
TH 后缀 | 大写序数后缀 | 999TH |
th 后缀 | 小写序数后缀 | 999th |
表 to_char 示例显示了一些使用 to_char 函数的示例。
| 表达式 | 结果 |
|---|---|
to_char(current_timestamp, 'Day, DD HH12:MI:SS') | 'Tuesday , 06 05:39:18' |
to_char(current_timestamp, 'FMDay, FMDD HH12:MI:SS') | 'Tuesday, 6 05:39:18' |
to_char(-0.1, '99.99') | ' -.10' |
to_char(-0.1, 'FM9.99') | '-.1' |
to_char(-0.1, 'FM90.99') | '-0.1' |
to_char(0.1, '0.9') | ' 0.1' |
to_char(12, '9990999.9') | ' 0012.0' |
to_char(12, 'FM9990999.9') | '0012.' |
to_char(485, '999') | ' 485' |
to_char(-485, '999') | '-485' |
to_char(485, '9 9 9') | ' 4 8 5' |
to_char(1485, '9,999') | ' 1,485' |
to_char(1485, '9G999') | ' 1 485' |
to_char(148.5, '999.999') | ' 148.500' |
to_char(148.5, 'FM999.999') | '148.5' |
to_char(148.5, 'FM999.990') | '148.500' |
to_char(148.5, '999D999') | ' 148,500' |
to_char(3148.5, '9G999D999') | ' 3 148,500' |
to_char(-485, '999S') | '485-' |
to_char(-485, '999MI') | '485-' |
to_char(485, '999MI') | '485 ' |
to_char(485, 'FM999MI') | '485' |
to_char(485, 'PL999') | '+485' |
to_char(485, 'SG999') | '+485' |
to_char(-485, 'SG999') | '-485' |
to_char(-485, '9SG99') | '4-85' |
to_char(-485, '999PR') | '<485>' |
to_char(485, 'L999') | 'DM 485' |
to_char(485, 'RN') | ' CDLXXXV' |
to_char(485, 'FMRN') | 'CDLXXXV' |
to_char(5.2, 'FMRN') | 'V' |
to_char(482, '999th') | ' 482nd' |
to_char(485, '"Good number:"999') | 'Good number: 485' |
to_char(485.8, '"Pre:"999" Post:" .999') | 'Pre: 485 Post: .800' |
to_char(12, '99V999') | ' 12000' |
to_char(12.4, '99V999') | ' 12400' |
to_char(12.45, '99V9') | ' 125' |
to_char(0.0004859, '9.99EEEE') | ' 4.86e-04' |
10. 日期/时间函数和操作符
表 日期/时间函数显示了可用于日期/时间值处理的函数,详细信息在以下子节中。表 日期/时间操作符说明了基本算术操作符(+、* 等)的行为。有关格式化函数,请参见数据类型格式化函数。
此外,表 比较操作符中显示的常规比较操作符也适用于日期/时间类型。日期和时间戳(带或不带时区)都是可比较的,而时间(带或不带时区)和间隔只能与相同数据类型的其他值进行比较。当将不带时区的时间戳与带时区的时间戳进行比较时,前者的值被假定为给定的时区。TimeZone 配置参数被假定为本地时间,并被转换为 UTC 以与 UTC 内部值进行比较。同样,当比较日期值与时间戳时,日期值被假定为当天的午夜在 TimeZone 时区。下面所描述的所有函数和操作符都有两个变体:一个接受带有时区的 time 或 timestamp 输入,另一个接受不带时区的 time 或 timestamp 输入。为了简洁起见,这些变体没有分别显示。此外,+ 和 * 操作符成对出现(例如,date + integer 和 integer + date);我们只显示这样一对中的一个。
| 操作符 | 描述 | 示例 |
|---|---|---|
date + integer → date | 将日期增加几天 | date '2001-09-28' + 7 → 2001-10-05 |
date + interval → timestamp | 向日期添加间隔 | date '2001-09-28' + interval '1 hour' → 2001-09-28 01:00:00 |
date + time → timestamp | 在日期中添加一个时间 | date '2001-09-28' + time '03:00' → 2001-09-28 03:00:00 |
interval + interval → interval | 加上间隔 | interval '1 day' + interval '1 hour' → 1 day 01:00:00 |
timestamp + interval → timestamp | 向时间戳添加间隔 | timestamp '2001-09-28 01:00' + interval '23 hours' → 2001-09-29 00:00:00 |
time + interval → time | 将间隔添加到时间 | time '01:00' + interval '3 hours' → 04:00:00 |
- interval → interval | 取消间隔 | - interval '23 hours' → -23:00:00 |
date - date → integer | 减去日期,生成所经过的天数 | date '2001-10-01' - date '2001-09-28' → 3 |
date - integer → date | 从日期中减去几天 | date '2001-10-01' - 7 → 2001-09-24 |
date - interval → timestamp | 从日期中减去间隔 | date '2001-09-28' - interval '1 hour' → 2001-09-27 23:00:00 |
time - time → interval | 减去时间 | time '05:00' - time '03:00' → 02:00:00 |
time - interval → time | 从时间中减去间隔 | time '05:00' - interval '2 hours' → 03:00:00 |
timestamp - interval → timestamp | 从时间戳中减去间隔 | timestamp '2001-09-28 23:00' - interval '23 hours' → 2001-09-28 00:00:00 |
interval - interval → interval | 减去间隔 | interval '1 day' - interval '1 hour' → 1 day -01:00:00 |
timestamp - timestamp → interval | 减去时间戳(将 24 小时间隔转换为天,类似于 justify_hours()) | timestamp '2001-09-29 03:00' - timestamp '2001-07-27 12:00' → 63 days 15:00:00 |
interval * double precision → interval | 将一个时间间隔乘以一个标量 | interval '1 second' * 900 → 00:15:00interval '1 day' * 21 → 21 daysinterval '1 hour' * 3.5 → 03:30:00 |
interval / double precision → interval | 用一个标量除以一个间隔 | interval '1 hour' / 1.5 → 00:40:00 |
| 函数 | 描述 | 示例 |
|---|---|---|
age ( timestamp, timestamp ) → interval | 计算两个时间戳之间的时间差,返回一个使用年和月的“符号性”结果,而不仅仅是天数 | age(timestamp '2001-04-10', timestamp '1957-06-13') → 43 years 9 mons 27 days |
age ( timestamp ) → interval | 计算给定时间戳与当前日期(午夜)之间的时间差 | age(timestamp '1957-06-13') → 62 years 6 mons 10 days |
clock_timestamp ( ) → timestamp with time zone | 当前日期和时间(在语句执行期间更改) | clock_timestamp() → 2019-12-23 14:39:53.662522-05 |
current_date → date | 当前日期 | current_date → 2019-12-23 |
current_time → time with time zone | 当前时间 | current_time → 14:39:53.662522-05 |
current_time ( integer ) → time with time zone | 当前时间,精度有限 | current_time(2) → 14:39:53.66-05 |
current_timestamp → timestamp with time zone | 当前日期和时间(当前事务的开始) | current_timestamp → 2019-12-23 14:39:53.662522-05 |
current_timestamp ( integer ) → timestamp with time zone | 当前日期和时间(当前事务的开始),精度有限 | current_timestamp(0) → 2019-12-23 14:39:53-05 |
dayofweek ( date ) → int | 返回输入日期所对应的星期数(1=Sunday,2=Monday...7=Saturday),这些索引值是基于 ODBC 标准来确定的 | SELECT DAYOFWEEK('2007-02-03') → 7 |
dayofyear ( date ) → int | 返回输入日期所对应的当前年份的日历天,范围在 1-366 之间 | SELECT DAYOFYEAR('2007-02-03') → 34 |
date_bin ( interval, timestamp, timestamp ) → timestamp | 将输入分成指定间隔并与指定原点对齐 | date_bin('15 minutes', timestamp '2001-02-16 20:38:40', timestamp '2001-02-16 20:05:00') → 2001-02-16 20:35:00 |
date_part ( text, timestamp ) → double precision | 获取时间戳子字段(等同于 extract) | date_part('hour', timestamp '2001-02-16 20:38:40') → 20 |
date_part ( text, interval ) → double precision | 获取间隔子字段(等同于 extract) | date_part('month', interval '2 years 3 months') → 3 |
date_trunc ( text, timestamp ) → timestamp | 截断到指定精度 | date_trunc('hour', timestamp '2001-02-16 20:38:40') → 2001-02-16 20:00:00 |
date_trunc ( text, timestamp with time zone, text ) → timestamp with time zone | 在指定的时区中截断到指定的精度 | date_trunc('day', timestamptz '2001-02-16 20:38:40+00', 'Australia/Sydney') → 2001-02-16 13:00:00+00 |
date_trunc ( text, interval ) → interval | 截断到指定精度 | date_trunc('hour', interval '2 days 3 hours 40 minutes') → 2 days 03:00:00 |
extract ( field from timestamp ) → numeric | 获取时间戳子字段 | extract(hour from timestamp '2001-02-16 20:38:40') → 20 |
extract ( field from interval ) → numeric | 获取间隔子字段 | extract(month from interval '2 years 3 months') → 3 |
from_unixtime ( double precision ) → timestamp | 将 unix 时间戳参数转化为对应的时间并返回 | select from_unixtime(0); |
from_unixtime ( double precision, text ) → varchar | 指定格式,将时间戳对应的时间按照时间日期格式控制参数要求输出。时间日期格式控制参数参见“表 date_format 说明符” | select from_unixtime(0, '%Y-%m-%d'); |
isfinite ( date ) → boolean | 测试日期是否有限(不是 +/-infinity) | isfinite(date '2001-02-16') → true |
isfinite ( timestamp ) → boolean | 测试时间戳是否有限(不是 +/-infinity) | isfinite(timestamp 'infinity') → false |
isfinite ( interval ) → boolean | 测试间隔是否有限(目前始终为真) | isfinite(interval '4 hours') → true |
justify_days ( interval ) → interval | 调整间隔,使 30 天的时间段表示为月份 | justify_days(interval '35 days') → 1 mon 5 days |
justify_hours ( interval ) → interval | 调整间隔,使 24 小时的时间段表示为天数 | justify_hours(interval '27 hours') → 1 day 03:00:00 |
justify_interval ( interval ) → interval | 使用 justify_days 和 justify_hours 调整间隔,并进行附加符号调整 | justify_interval(interval '1 mon -1 hour') → 29 days 23:00:00 |
localtime → time | 当前时间 | localtime → 14:39:53.662522 |
localtime ( integer ) → time | 当前时间,精度有限 | localtime(0) → 14:39:53 |
localtimestamp → timestamp | 当前日期和时间(当前事务的开始) | localtimestamp → 2019-12-23 14:39:53.662522 |
localtimestamp ( integer ) → timestamp | 当前日期和时间(当前事务的开始),精度有限 | localtimestamp(2) → 2019-12-23 14:39:53.66 |
make_date ( year int, month int, day int ) → date | 从年、月和日字段创建日期(负数年表示公元前) | make_date(2013, 7, 15) → 2013-07-15 |
make_interval ( [ years int [ , months int [ , weeks int [ , days int [ , hours int [ , mins int [ , secs double precision ] ] ] ] ] ] ] ) → interval | 从年、月、周、日、小时、分钟和秒字段创建间隔,每个字段都可以默认为零 | make_interval(days => 10) → 10 days |
make_time ( hour int, min int, sec double precision ) → time | 从小时、分钟和秒字段创建时间 | make_time(8, 15, 23.5) → 08:15:23.5 |
make_timestamp ( year int, month int, day int, hour int, min int, sec double precision ) → timestamp | 从年、月、日、小时、分钟和秒字段创建时间戳(负年份表示公元前)。 | make_timestamp(2013, 7, 15, 8, 15, 23.5) → 2013-07-15 08:15:23.5 |
make_timestamptz ( year int, month int, day int, hour int, min int, sec double precision [ , timezone text ] ) → timestamp with time zone | 从年、月、日、小时、分钟和秒字段创建带有时区的时间戳(负年份表示公元前)。如果未指定 timezone,则使用当前时区;示例假定会话时区为 Europe/London。 | make_timestamptz(2013, 7, 15, 8, 15, 23.5) → 2013-07-15 08:15:23.5+01make_timestamptz(2013, 7, 15, 8, 15, 23.5, 'America/New_York') → 2013-07-15 13:15:23.5+01 |
months_between ( date1 timestamp, date2 timestamp ) → numeric | 返回 date1 与 date2 之间的月份的差值(即用 date1 - date2),结果可以为整数也可以为小数。 | SELECT months_between ('2008-02-29', '2008-03-31') → -1 |
now ( ) → timestamp with time zone | 当前日期和时间(当前事务的开始) | now() → 2019-12-23 14:39:53.662522-05 |
statement_timestamp ( ) → timestamp with time zone | 当前日期和时间(当前语句的开始) | systimestamp → 2019-12-23 14:39:53.662522-05 |
systimestamp → timestamptz | 获取到系统的当前时间,包含时区信息,精确到微秒 | select systimestamp; → 2022-07-21 16:53:42.664272+08 |
timeofday ( ) → text | 当前日期和时间(类似于 clock_timestamp,但返回 text 字符串) | timeofday() → Mon Dec 23 14:39:53.662522 2019 EST |
transaction_timestamp ( ) → timestamp with time zone | 当前日期和时间(当前事务的开始时间) | transaction_timestamp() → 2019-12-23 14:39:53.662522-05 |
to_timestamp ( double precision ) → timestamp with time zone | 将 Unix 纪元(自 1970-01-01 00:00:00+00 以来的秒数)转换为带有时区的时间戳 | to_timestamp(1284352323) → 2010-09-13 04:32:03+00 |
date_format ( date, format ) → text | 将日期值格式化为特定格式 | date_format('2022-05-16 14:24:09.024727','%W %D %M %Y') |
round ( date, fmt ) → 与 date 相同类型 | 将 date 按照公历规则四舍五入到 fmt 单位。如果没有明确 fmt 则舍去到最近一天 | select round(timestamptz '2004-10-19 05:35:25+02','hh'); → 2004-10-19 12:00:00 |
str_to_date ( text, text ) → timestamp | 将时间格式的字符串,按照格式转换为 timestamp 类型的值 | str_to_date('2022-05-26 11:30:00','%Y-%m-%d %H:%i:%s') → 2022-05-26 11:30:00 |
to_yminterval ( text ) → interval year to month | 将日期字符串转换为 interval year to month 类型输出 | to_yminterval(' 2019-01') → 2019 years 1 mon |
last_day ( date ) → date | 返回指定日期对应月份的最后一天。 date 支持以下类型:date, timestamp, timestamptz, text, char, varchar, varchar2, nvarchar2, name, bpchar, clob | select last_day(timestamptz '2004-10-19 05:35:25+02'); → 2004-10-31 11:35:25 |
from_days ( n ) → date | 根据给定的数字 N 计算出距离公元前 0001-01-01 N 天的日期 | from_days(100) → 0001-04-10 00:00:00 BC |
sys_extract_utc ( timestamp with time zone ) → timestamp | 将从带有时区偏移或时区区域名称的日期时间值中提取 UTC(协调世界时,以前为格林威治标准时间)。如果未指定时区,则输出时间会根据默认会话时区转换 | sys_extract_utc(timestamptz '2000-03-28 11:30:00.00-08:00') → 2000-03-28 19:30:00 |
to_days ( date ) → int | 根据给定的日期计算出距离公元前 0001-01-01 0 的天数差值 | to_days('2023-01-01') → 738886 |
adddate ( date, expr unit ) → timestampadddate ( timestamp, INTERVAL expr unit ) → timestampadddate ( timestamptz, INTERVAL expr unit ) → timestampadddate ( time, INTERVAL expr unit ) → timeadddate ( timetz, INTERVAL expr unit ) → timetz | 返回日期时间加间隔的值,与 date_add 互为同义函数。unit 为间隔单位,参见 interval 类型的 fields 短语 | adddate('2023-04-14 14:55:32', interval '1' year) → 2024-04-14 14:55:32+08 |
adddate ( date, days ) → timestampadddate ( timestamp, days ) → timestampadddate ( timestamptz, days ) → timestamptzadddate ( time, days ) → timeadddate ( timetz, days ) → timetz | 返回日期时间加间隔的值,days 为数字或者字符类型,表示间隔的天数 | adddate('2023-04-14 14:55:32', 1) → 2023-04-15 14:55:32+08 |
date_sub ( date, INTERVAL expr unit ) → timestampdate_sub ( timestamp, INTERVAL expr unit ) → timestampdate_sub ( timestamptz, INTERVAL expr unit ) → timestamptzdate_sub ( time, INTERVAL expr unit ) → timedate_sub ( timetz, INTERVAL expr unit ) → timetz | 返回日期时间减去间隔的值,与 subdate 互为同义函数。unit 为间隔单位,参见 interval 类型的 fields 短语 | date_sub('2023-04-14 14:55:32', interval '1' year) → 2022-04-14 14:55:32+08 |
date_sub ( date, days ) → timestampdate_sub ( timestamp, days ) → timestampdate_sub ( timestamptz, days ) → timestamptzdate_sub ( time, days ) → timedate_sub ( timetz, days ) → timetz | 返回日期时间减去间隔的值,days 为数字或者字符类型,表示间隔的天数 | subdate('2023-04-14 14:55:32', 1) → 2023-04-13 14:55:32+08 |
datediff ( date1, date2 ) → bigint | 计算两个日期间隔的天数,返回 date1 - date2 | datediff('2023-4-4', '2023-3-1') → 34 |
timestampdiff ( unit, datetime_expr1, datetime_expr2 ) → bigint | 计算日期时间指定单位的时间差,unit 为间隔单位,可为:MICROSECOND,SECOND,MINUTE,HOUR,DAY,WEEK,MONTH,QUARTER,YEAR。根据 unit 返回 datetime_expr2 - datetime_expr1 的值 | timestampdiff(day, '2023-4-4', '2023-3-1') → -34 |
year ( date ) → integer | 返回给定日期的年份 | year('2023/12/31 13:22:00') → 2023 |
quarter ( date ) → integer | 返回给定日期所在当年的季度。返回值的范围是 1 到 4 | quarter('2023-4-4') → 2 |
month ( date ) → integer | 返回给定日期所在的月份,返回值的范围是 1 到 12 | month('2023-4-4') → 4 |
week ( date[, mode] ) → integer | 返回给定日期所在的周数。该函数的双参数形式允许指定一周是从星期天开始还是星期一开始,以及返回值应该在 0 到 53 还是 1 到 53 的范围内。如果省略 mode 参数,则使用 default_week_format 系统变量的值。mode 参数参见表 “weekdate 函数 mode 参数说明” | week('2023-4-4') → 14 |
dayofmonth ( date ) → integer | 返回给定日期在月份中的天数,返回的结果范围是 1 到 31。DAY 是 DAYOFMONTH 的同义词,两者功能相同 | dayofmonth('2023/12/31 13:22:00') → 31 |
hour ( time ) → integer | 返回给定时间的小时数,返回的结果的范围是 0 到 24 | hour('2023/12/31 24:00:00') → 24 |
minute ( time ) → integer | 返回给定时间的分钟数,返回的结果的范围是 0 到 59 | minute('2023/12/31 0:22:00') → 22 |
second ( time ) → integer | 返回给定时间的秒数,返回的结果的范围是 0 到 59 | second('10:00:59') → 59 |
microsecond ( time ) → integer | 返回给定时间的微秒数,返回的结果的范围是 0 到 999999 | microsecond('20:22:33.123') → 123000 |
curdate() → date | 返回当前日期 | curdate() → 2023-04-07 |
current_date() → date | 返回当前日期 | current_date() → 2023-04-07 |
current_time() → timetz | 返回当前时间,默认精度为 0 | |
current_time( fsp ) → timetz | 返回当前时间,fsp 指定毫秒精度。其中,fsp 的类型为 int,范围 0-6,默认精度为 0(不显示毫秒) | |
curtime() → timetz | 返回当前时间,默认精度为 0 | |
curtime( fsp ) → timetz | 返回当前时间,fsp 指定毫秒精度。其中,fsp 的类型为 int,范围 0-6,默认精度为 0(不显示毫秒) | curtime(3) → 13:50:21.737+08 |
current_timestamp() → timestamptz | 返回当前时间戳,默认精度为 0 | |
current_timestamp( fsp ) → timestamptz | 返回当前时间戳,fsp 指定毫秒精度。其中,fsp 的类型为 int,范围 0-6,默认精度为 0(不显示毫秒) | current_timestamp(3) → 2023-04-07 13:50:43.159+08 |
now( fsp ) → timestamptz | 返回当前时间戳,fsp 指定毫秒精度。其中,fsp 的类型为 int,范围 0-6,默认精度为 0(不显示毫秒) | now('3') → 2023-04-07 13:50:54.335+08 |
unix_timestamp ( timestamp with time zone ) → numeric | 返回给定日期时间(带时区)的 unix 时间戳 | select unix_timestamp('2023-08-17 00:00:00.123'::timestamp with time zone); → 1692201600.123 |
unix_timestamp ( timestamp without time zone ) → numeric | 返回给定日期时间(不带时区)的 unix 时间戳 | |
unix_timestamp ( time with time zone ) → numeric | 返回当前日期给定时间(带时区)的 unix 时间戳 | |
unix_timestamp ( time without time zone ) → numeric | 返回当前日期给定时间(不带时区)的 unix 时间戳 | |
unix_timestamp ( text ) → numeric | 将日期时间格式的字符串,转换成相应的 unix 时间戳 | |
unix_timestamp ( binary ) → numeric | 返回 binary 值对应的日期时间的 unix 时间戳 | |
unix_timestamp ( varbinary ) → numeric | 返回 varbinary 值对应的日期时间的 unix 时间戳 | |
unix_timestamp () → numeric | 返回当前日期时间(带时区)的 unix 时间戳 | |
weekofyear ( date ) → int | 返回输入日期所对应的当前年份的日历周,是一种兼容性等效于 week(date,3) 的函数 | SELECT WEEKOFYEAR('2008-02-20') → 8 |
ADD_DAYS ( date/timestamp, int ) → date | 返回日期 date 加上相应天数 n 后的日期值。 | add_days('2024-02-18', 2) → 2024-02-20add_days(0,2958463) → 9999-12-31 |
ADD_WEEKS ( date/timestamp, int ) → date | 返回日期 date 加上相应星期数 n 后的日期值。 | add_weeks('2024-02-01', 1) → 2024-02-08add_weeks(0, 1) → 1900-01-08 |
表 weekdate 函数 mode 参数说明
| 模式 | 一周的第一天 | 范围 | 说明 |
|---|---|---|---|
| 0 | 星期天 | 0-53 | 遇到本年的第一个星期天开始,是第一周。前面的计算为第 0 周。 |
| 1 | 星期一 | 0-53 | 假如第一周能超过 3 天,那么计算为本年的第一周。否则为第 0 周。 |
| 2 | 星期天 | 1-53 | 遇到本年的第一个星期天开始,是第一周。 |
| 3 | 星期一 | 1-53 | 假如第一周能超过 3 天,那么计算为本年的第一周。否则为上年度的第 5x 周。 |
| 4 | 星期天 | 0-53 | 假如第一周能超过 3 天,那么计算为本年的第一周。否则为第 0 周。 |
| 5 | 星期一 | 0-53 | 遇到本年的第一个星期一开始,是第一周。 |
| 6 | 星期天 | 1-53 | 假如第一周能超过 3 天,那么计算为本年的第一周。否则为上年度的第 5x 周。 |
| 7 | 星期一 | 1-53 | 遇到本年的第一个星期一开始,是第一周。 |
除了这些函数外,还支持 SQL 的 OVERLAPS 操作符:
(start1, end1) OVERLAPS (start2, end2)
(start1, length1) OVERLAPS (start2, length2)
当两个时间段(由它们的端点定义)重叠时,此表达式返回 true,否则返回 false。端点可以指定为日期、时间或时间戳对;或者作为日期、时间或时间戳后跟一个间隔。当提供一对值时,可以先写入开始或结束;OVERLAPS 自动将该对的较早值作为开始。每个时间段被认为表示半开区间 start <= time < end,除非 start 和 end 相等,在这种情况下它表示单个时间点。这意味着例如,只有一个端点相同的两个时间段不重叠。
SELECT (DATE '2001-02-16', DATE '2001-12-21') OVERLAPS
(DATE '2001-10-30', DATE '2002-10-30');
Result: true
SELECT (DATE '2001-02-16', INTERVAL '100 days') OVERLAPS
(DATE '2001-10-30', DATE '2002-10-30');
Result: false
SELECT (DATE '2001-10-29', DATE '2001-10-30') OVERLAPS
(DATE '2001-10-30', DATE '2001-10-31');
Result: false
SELECT (DATE '2001-10-30', DATE '2001-10-30') OVERLAPS
(DATE '2001-10-30', DATE '2001-10-31');
Result: true
当向具有时区值的时间戳添加(或从中减去)一个时间间隔时,天组件将 timestamp with time zone 提前或减去指定的天数,使一天的时间保持不变。在夏时制变化时(当会话时区设置为识别夏令时的时区时),这意味着间隔“1 天”不一定等于间隔“24 小时”。例如,会话时区设置为 America/Denver:
SELECT timestamp with time zone '2005-04-02 12:00:00-07' + interval '1 day';
Result: 2005-04-03 12:00:00-06
SELECT timestamp with time zone '2005-04-02 12:00:00-07' + interval '24 hours';
Result: 2005-04-03 13:00:00-06
这是因为由于时区“America/Denver”中的夏令时更改,在 2005-04-03 02:00:00 时跳过了一个小时。
请注意,由于不同的月份具有不同数量的天数,因此“age”函数返回的“months”字段可能存在歧义。UXsinoDB 的方法在计算部分月份时使用两个日期中较早的月份。例如,“age('2004-06-01','2004-04-30')”使用 4 月份得出“1 mon 1 day”,而使用 5 月份则会得出“1 mon 2 days”,因为 5 月份有 31 天,而 4 月份只有 30 天。
日期和时间戳的减法也可以很复杂。一个概念上简单的方法是使用 EXTRACT(EPOCH FROM...) 将每个值转换为秒数,然后减去结果;这将调整每个月的天数、时区更改和夏令时调整。使用 - 操作符减去日期或时间戳值返回值之间的天数(24 小时)、小时/分钟/秒数,进行相同的调整。函数 age 返回年、月、日和小时/分钟/秒数,执行逐字段减法,然后调整负字段值。以下查询说明了这些方法的差异。样本结果是使用 timezone='US/Eastern' 生成的;在使用的两个日期之间有一个夏令时更改:
SELECT EXTRACT(EPOCH FROM timestamptz '2013-07-01 12:00:00') -
EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00');
Result: 10537200
SELECT (EXTRACT(EPOCH FROM timestamptz '2013-07-01 12:00:00') -
EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00'))
/ 60 / 60 / 24;
Result: 121.958333333333
SELECT timestamptz '2013-07-01 12:00:00' - timestamptz '2013-03-01 12:00:00';
Result: 121 days 23:00:00
SELECT age(timestamptz '2013-07-01 12:00:00', timestamptz '2013-03-01 12:00:00');
Result: 4 mons
10.1. EXTRACT,date_part
EXTRACT(field FROM source)
extract 函数从日期/时间值中检索子字段,例如年份或小时数。source 必须是类型为 timestamp、time 或 interval 的值表达式。(类型为 date 的表达式会被转换为 timestamp,因此也可以使用。)field 是一个标识符或字符串,用于选择从源值中提取的字段。extract 函数返回类型为 numeric 的值。以下是有效的字段名称:
-
century世纪SELECT EXTRACT(CENTURY FROM TIMESTAMP '2000-12-16 12:21:13'); Result: 20 SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 21第一个世纪始于公元 0001-01-01 00:00:00,尽管当时人们并不知道。这个定义适用于所有格里高利历国家。没有世纪编号 0,你从 -1 世纪到 1 世纪。
-
day对于timestamp值,表示日期(1-31);对于interval值,表示天数SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 16 SELECT EXTRACT(DAY FROM INTERVAL '40 days 1 minute'); Result: 40 -
decade年份除以 10 的结果SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 200 -
dow星期几,从星期日(0)到星期六(6)SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 5请注意,
extract的星期几编号与to_char(..., 'D')函数的编号不同。 -
doy一年中的第几天(1-365/366)SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 47 -
epoch对于带有时区的timestamp值,表示自 1970-01-01 00:00:00 UTC 以来的秒数(时间戳早于此时间的秒数为负数);对于date和timestamp值,以 1970-01-01 00:00:00 为基准的秒数,不考虑时区或夏令时规则;对于interval值,是时间间隔中的总秒数。SELECT EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40.12-08'); Result: 982384720.12 SELECT EXTRACT(EPOCH FROM TIMESTAMP '2001-02-16 20:38:40.12'); Result: 982355920.12 SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours'); Result: 442800您可以使用
to_timestamp将时代值转换回timestamp with time zone:SELECT to_timestamp(982384720.12); Result: 2001-02-17 04:38:40.12+00请注意,将
to_timestamp应用于从date或timestamp值中提取的时代可能会产生误导性的结果:结果将有效地假定原始值已在 UTC 中给出,这可能不是实际情况。 -
hour小时字段(0-23)SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 20 -
isodow星期几,从星期一(1)到星期日(7)SELECT EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40'); Result: 7这与
dow相同,除了星期日。这与 ISO 8601 星期几编号相匹配。 -
isoyear日期所在的 ISO 8601 周编号年份(不适用于时间间隔)SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01'); Result: 2005 SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02'); Result: 2006每个 ISO 8601 周编号年从包含 1 月 4 日的星期一开始,因此在 1 月初或 12 月末,ISO 年可能与公历年不同。
-
julian与日期或时间戳相对应的儒略日(不适用于时间间隔)。不是当地午夜的时间戳会导致小数值。SELECT EXTRACT(JULIAN FROM DATE '2006-01-01'); Result: 2453737 SELECT EXTRACT(JULIAN FROM TIMESTAMP '2006-01-01 12:00'); Result: 2453737.50000000000000000000 -
microseconds秒数字段,包括小数部分,乘以 1,000,000;注意这包括整秒。SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5'); Result: 28500000 -
millennium千年SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 31900 年代的年份属于第二个千年。第三个千年从 2001 年 1 月 1 日开始。
-
milliseconds秒数字段,包括小数部分,乘以 1,000;注意这包括整秒。SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28.5'); Result: 28500 -
minute分钟字段(0-59)SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 38 -
month对于时间戳值,表示一年中的月份(1-12);对于间隔值,表示月数模 12(0-11)SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 2 SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months'); Result: 3 SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months'); Result: 1 -
quarter一年中的季度(1-4)SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 1 -
second秒数字段,包括任何小数秒。SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 40 SELECT EXTRACT(SECOND FROM TIME '17:12:28.5'); Result: 28.5 -
timezone与 UTC 的时区偏移,以秒为单位。正值对应于 UTC 东部的时区,负值对应于 UTC 西部的时区。(严格来说,UXsinoDB 不使用 UTC,因为不处理闰秒。) -
timezone_hour时区偏移的小时部分。 -
timezone_minute时区偏移的分钟部分。 -
weekISO 8601 周编号年的周数。根据定义,ISO 周从星期一开始,一年的第一周包含该年的 1 月 4 日。换句话说,一年的第一个星期四在该年的第一周。在 ISO 周编号系统中,1 月初的日期可能属于上一年的第 52 或第 53 周,而 12 月底的日期可能属于下一年的第一周。例如,2005 年 1 月 1 日属于 2004 年的第 53 周,2006 年 1 月 1 日属于 2005 年的第 52 周,而 2012 年 12 月 31 日属于 2013 年的第一周。建议使用 isoyear 字段和 week 字段一起使用以获得一致的结果。
SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 7 -
year年份字段。请记住,没有“公元前 0 年”,因此应谨慎地从“公元后”年份中减去“公元前”年份。SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 2001注意
当输入值为 +/-Infinity 时,extract对于单调递增字段(epoch、julian、year、isoyear、decade、century和millennium)返回 +/-Infinity。对于其他字段,返回 NULL。
extract 函数主要用于计算处理。有关格式化日期/时间值以供显示的信息,请参见数据类型格式化函数。
date_part 函数是基于传统的 Ingres 等效函数 extract 的模型:
date_part('field', source)
请注意,这里的 field 参数需要是字符串值,而不是名称。对于 date_part,有效的字段名称与 extract 相同。由于历史原因,date_part 函数返回 double precision 类型的值。在某些用途中,这可能会导致精度损失。建议改用 extract。
SELECT date_part('day', TIMESTAMP '2001-02-16 20:38:40');
Result: 16
SELECT date_part('hour', INTERVAL '4 hours 3 minutes');
Result: 4
10.2. date_trunc
函数 date_trunc 在概念上类似于数字的 trunc 函数。
date_trunc(field, source [, time_zone ])
source 是 timestamp、timestamp with time zone 或者 interval 表达式。(类型 date 和 time 的值分别自动转换为 timestamp 或 interval。)field 选择截断输入值的精度。返回值类似于 timestamp、timestamp with time zone 或者 interval 的类型,并且它包含所有比选定的字段设置为零(或者日和月的一个字段)更小的字段。
field 的有效值为:
microseconds
milliseconds
second
minute
hour
day
week
month
quarter
year
decade
century
millennium
当输入值为类型为 timestamp with time zone 时,截断是相对于特定时区进行的;例如,截断到 day 会产生一个在该时区中午夜的值。默认情况下,截断是相对于当前的 TimeZone 设置进行的,但是可以提供可选的 time_zone 参数来指定不同的时区。
在处理 timestamp without time zone 或 interval 输入时不能指定时区。这些始终按面值处理。
示例(假设本地时区为 America/New_York):
SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40');
Result: 2001-02-16 20:00:00
SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40');
Result: 2001-01-01 00:00:00
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00');
Result: 2001-02-16 00:00:00-05
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00', 'Australia/Sydney');
Result: 2001-02-16 08:00:00-05
SELECT date_trunc('hour', INTERVAL '3 days 02:47:33');
Result: 3 days 02:00:00
10.3. date_bin
函数 date_bin 将输入的时间戳“分组”到指定的间隔(步幅),并与指定的起点对齐。
date_bin(stride, source, origin)
source 是类型为 timestamp 或 timestamp with time zone 的值表达式。(类型为 date 的值会自动转换为 timestamp。)stride 是类型为 interval 的值表达式。返回值同样是类型为 timestamp 或 timestamp with time zone,并标记了 source 所在的分组的开头。
示例:
SELECT date_bin('15 minutes', TIMESTAMP '2020-02-11 15:44:17', TIMESTAMP '2001-01-01');
Result: 2020-02-11 15:30:00
SELECT date_bin('15 minutes', TIMESTAMP '2020-02-11 15:44:17', TIMESTAMP '2001-01-01 00:02:30');
Result: 2020-02-11 15:32:30
在完整单位(1 分钟,1 小时等)的情况下,它给出与类似的 date_trunc 调用相同的结果,但不同之处在于 date_bin 可以截断到任意间隔。
stride 间隔必须大于零,不能包含月份或更大的单位。
10.4. AT TIME ZONE
AT TIME ZONE 操作符将没有时区的时间戳转换为带有时区的时间戳,反之亦然,并将 time with time zone 值转换为不同的时区。表 AT TIME ZONE 变体显示了它的变体。
| 操作符 | 描述 | 示例 |
|---|---|---|
timestamp without time zone AT TIME ZONE zone → timestamp with time zone | 将给定的没有时区的时间戳转换为带有时区的时间戳,假设给定的值在指定的时区中。 | timestamp '2001-02-16 20:38:40' at time zone 'America/Denver' → 2001-02-17 03:38:40+00 |
timestamp with time zone AT TIME ZONE zone → timestamp without time zone | 将给定的带有时区的时间戳转换为在该时区中显示的没有时区的时间戳。 | timestamp with time zone '2001-02-16 20:38:40-05' at time zone 'America/Denver' → 2001-02-16 18:38:40 |
time with time zone AT TIME ZONE zone → time with time zone | 将带有时区的给定时间转换为新的时区。由于没有提供日期,这将使用指定目标区域的当前活动 UTC 偏移量。 | time with time zone '05:34:17-05' at time zone 'UTC' → 10:34:17+00 |
在这些表达式中,所需的时区 zone 可以指定为文本值(例如 'America/Los_Angeles')或间隔(例如 INTERVAL '-08:00')。例如(假设当前的 TimeZone 设置为 America/Los_Angeles)。
一些例子(假设当前的 TimeZone 设置为 America/Los_Angeles):
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'America/Denver';
Result: 2001-02-16 19:38:40-08
SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'America/Denver';
Result: 2001-02-16 18:38:40
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'Asia/Tokyo' AT TIME ZONE 'America/Chicago';
Result: 2001-02-16 05:38:40
第一个示例为缺少时区的值添加时区,并使用当前的 TimeZone 设置显示该值。第二个示例将带有时区的时间戳值移动到指定的时区,并返回没有时区的值。这允许存储和显示与当前 TimeZone 设置不同的值。第三个示例将东京时间转换为芝加哥时间。
函数 timezone(zone, timestamp) 等效于符合 SQL 的构造 timestamp AT TIME ZONE zone。
10.5. 当前日期/时间
UXDB 提供了许多返回当前日期和时间的函数。这些 SQL 标准的函数全部都按照当前事务的开始时刻返回值:
CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP
CURRENT_TIME(precision)
CURRENT_TIMESTAMP(precision)
LOCALTIME
LOCALTIMESTAMP
LOCALTIME(precision)
LOCALTIMESTAMP(precision)
CURRENT_TIME 和 CURRENT_TIMESTAMP 传递带有时区的值;LOCALTIME 和 LOCALTIMESTAMP 传递的值不带时区。
CURRENT_TIME、CURRENT_TIMESTAMP、LOCALTIME 和 LOCALTIMESTAMP 可以有选择地接受一个精度参数,该精度导致结果的秒域被圆整为指定小数位。如果没有精度参数,结果将被给予所能得到的全部精度。
一些例子:
SELECT CURRENT_TIME;
Result: 14:39:53.662522-05
SELECT CURRENT_DATE;
Result: 2019-12-23
SELECT CURRENT_TIMESTAMP;
Result: 2019-12-23 14:39:53.662522-05
SELECT CURRENT_TIMESTAMP(2);
Result: 2019-12-23 14:39:53.66-05
SELECT LOCALTIMESTAMP;
Result: 2019-12-23 14:39:53.662522
由于这些函数返回当前事务的开始时间,因此它们的值在事务期间不会更改。这被认为是一个特性:其目的是允许单个事务具有“当前”时间的一致概念,从而使同一事务中的多个修改具有相同的时间戳。
注意
其他数据库系统可能更频繁地推进这些值。
UXsinoDB 还提供了函数返回当前语句的开始时间,以及实际的在调用函数时的当前时间。完整列表非 SQL 标准时间函数是:
transaction_timestamp()
statement_timestamp()
clock_timestamp()
timeofday()
now()
transaction_timestamp() 等效于 CURRENT_TIMESTAMP,但命名为清晰反映它返回的内容。statement_timestamp() 返回当前的开始时间语句(更具体地说,是最新命令的接收时间来自客户端的消息)。statement_timestamp() 和 transaction_timestamp() 在事务的第一个命令期间返回相同的值,但可能会在后续命令期间不同。clock_timestamp 返回实际的当前时间,和因此其值甚至在单个 SQL 命令中也会发生变化。timeofday() 是一个历史 UXsinoDB 函数。像 clock_timestamp() 一样,它返回实际的当前时间,但作为格式化的 text 字符串而不是 timestamp 带有时区的值。now() 是传统的 UXsinoDB 等同于 transaction_timestamp()。
所有日期/时间数据类型也接受特殊的文字值使用 now 指定当前日期和时间(再次解释为事务开始时间)。因此,以下三个都返回相同的结果:
SELECT CURRENT_TIMESTAMP;
SELECT now();
SELECT TIMESTAMP 'now'; -- 但请参见下面的提示
提示
在指定稍后要评估的值时,请勿使用第三种形式,例如表列的DEFAULT子句。系统将now转换为timestamp,一旦解析常量,因此在需要默认值时,将使用表创建的时间!前两种形式将不会被评估,直到使用默认值,因为它们是函数调用。因此,它们将提供所需的默认行插入时间的行为。
10.6. 延迟执行
以下函数可用于延迟服务器进程的执行:
ux_sleep ( double precision )
ux_sleep_for ( interval )
ux_sleep_until ( timestamp with time zone )
ux_sleep 使当前会话的进程休眠,直到经过给定的秒数。可以指定小数秒延迟。ux_sleep_for 是一个方便的函数,允许将睡眠时间指定为 interval。ux_sleep_until 是一个方便的函数,用于需要特定唤醒时间的情况。例如:
SELECT ux_sleep(1.5);
SELECT ux_sleep_for('5 minutes');
SELECT ux_sleep_until('tomorrow 03:00');
注意
睡眠间隔的有效分辨率因平台而异;0.01 秒是常见的值。睡眠延迟将至少与指定的时间一样长。它可能会更长,具体取决于诸如服务器负载之类的因素。特别是,ux_sleep_until不能保证在指定的时间精确唤醒,但它不会提前唤醒。
警告
在调用ux_sleep或其变体时,请确保您的会话不持有比必要更多的锁。否则,其他会话可能必须等待您的睡眠进程,从而减慢整个系统的速度。
10.7. date_format
-
功能
date_format 将日期值格式化为特定格式,将参数 1(日期值)按照参数 2(特定格式语法结构)进行格式化。
-
函数
date_format(date, format); -
参数
表 date_format 参数说明
参数 说明 date 要格式化的有效日期值,如 2022-05-16 14:24:09.024727。 format 由预定义的说明符组成的格式字符串,每个说明符前面都有一个百分比字符 (%),如 %Y、%a。支持的说明符如下表所示。 表 date_format 说明符
限定符 含义 %a 三个字符缩写的工作日名称,例如:Mon、Tue、Wed 等 %b 三个字符缩写的月份名称,例如:Jan、Feb、Mar 等 %c 以数字表示的月份值,例如:1、2、3...12 %D 英文后缀,例如:0th、1st、2nd 等的一个月之中的第几天 %d 如果是 1 个数字(小于 10),那么一个月之中的第几天表示为加前导加 0,例如:00、01、02...31 %e 无前导 0 的月份的日子,例如:1、2...31 %f 微秒,范围在 000000...999999 %H 24 小时格式的小时,前导加 0,例如:00、01...23 %h 12 小时格式的小时,前导加 0,例如:01、02...12 %I 与 %h 相同 %i 分钟,前导加 0,例如:00、01...59 %j 一年中的第几天,前导加 0,例如:001、002...366 %k 24 小时格式的小时,无前导 0,例如:0、1、2...23 %l 12 小时格式的小时,无前导 0,例如:0、1、2...12 %M 月份全名称,例如:January、February...December %m 前导加 0 的月份名称,例如:00、01、02...12 %p AM 或 PM,取决于其他时间说明符 %r 表示时间,12 小时格式 hh:mm:ss AM 或 PM %S 表示秒,前导加 0,例如:00、01...59 %s 与 %S 相同 %T 表示时间,24 小时格式 hh:mm:ss %U 周的第一天是星期日,前导加 0 的周数,例如:00、01、02...53 %u 周的第一天是星期一,前导加 0 的周数,例如:00、01、02...53 %V 与 %U 相同,与 %X 一起使用 %v 与 %u 相同,与 %x 一起使用 %W 工作日的全程,例如:Sunday、Monday...Saturday %w 以数字表示工作日(0=星期日,1=星期一...6=星期六) %X 周的四位数表示年份,第一天是星期日,常与 %V 一起使用 %x 周的四位数表示年份,第一天是星期一,常与 %v 一起使用 %Y 表示年份,四位数,例如:2000、2001 等 %y 表示年份,两位数,例如:00、01 等 %%将百分比(%)字符添加到输出 -
返回值
返回
text类型。 -
示例
select date_format('2022-05-16 14:24:09.024727','%W %D %M %Y'); select date_format(now(),'%W %D %M %Y'); select DATE_FORMAT(now(),'%a %b %d %f %H %h %I %i %j %M %m %p %S %s %W %Y %y %c %D %e %k %l %r %T %U %u %V %v %w %X %x'); select date_format(now(),'%W - %D - %M - %Y test 123');
10.8. monthname
-
功能
monthname(DATETIME)函数用于从给定的时间日期参数中抽取月份并返回对应的月份名称。返回结果由参数 lc_time 控制,返回本地语言版的月份名称结果。 -
函数
monthname(DATETIME) -
示例
uxdb=# show lc_time; lc_time ------------- en_US.UTF-8 uxdb=# select monthname('2023-11-11'); monthname ----------- November通过设置 lc_time 的值可以更改返回结果的显示方式。
uxdb=# set lc_time='zh_CN.UTF8'; SET再次查询可以得到如下结果。
uxdb=# select monthname('2023-11-11'); monthname ----------- 十一月
10.9. round
-
功能
将 date 按照公历规则四舍五入到 fmt 单位。如果没有明确 fmt 则舍去到最近一天。
-
函数
round(date, fmt) -
参数
表 round 参数说明
参数 说明 date 有效日期值,如 2022-05-16 14:24:09.024727。支持以下类型:timestamp (timestamp without time zone),timestamptz (timestamp with time zone),date,timetz (time with time zone),time (time without time zone) fmt 指定处理格式,支持格式参见表 fmt 格式 表 fmt 格式
格式 舍入或截断单位 CCSCC一个大于四位数年份的前两位 SYYYYYYYYYEARSYEARYYYYYY年份(7 月 1 日四舍五入) IYYYIYYIYIISO 8601 标准定义的包含日历周的年份 Q季度(在本季度第二个月的第 16 天进行四舍五入) MONTHMONMMRM月份(第 16 天四舍五入) WW按每年的 1 月 1 日的作为第一周第一天 IW与 ISO 8601 标准定义的日历周的第一天相同的一周中的一天,即星期一 W按月份 1 日的第一天作为每周第一天 DDDDDJ天 DAYDYD一周的开始日期 HHHH12HH24小时 MI分钟 -
示例
select round(timestamptz '2004-10-19 05:35:25+02','hh'); round ----------- 2004-10-19 12:00:00 select round('2004-10-19'::timestamp,'Year'); round ----------- 2005-01-01 00:00:00
10.10. str_to_date
-
功能
将时间格式的
string,按照format格式转换为TIMESTAMP类型的值。仅在 mysql 运行模式下支持。 -
函数
str_to_date(string, format) -
参数
表 str_to_date 参数说明
参数 说明 string 时间格式字符串或数字。 format 支持格式,请参见表 str_to_date format 说明符。 表 str_to_date format 说明符
限定符 含义 %a 三个字符缩写的工作日名称,例如:Mon、Tue、Wed 等 %b 三个字符缩写的月份名称,例如:Jan、Feb、Mar 等 %Y 表示年份,四位数,例如:2000, 2001, … 等 %y 表示年份,两位数,例如:00, 01, … 等 %d 以数值表示月份中的某天,如果是小于 10 的数字,该数字需要加前导 0,例如:00, 01, 02, … 31 %H 24 小时格式的小时,前导加 0,例如:00, 01 … 23 %h 12 小时格式的小时,前导加 0,例如:00, 01 … 12 %j 一年中的的第几天,前导加 0,例如:001, 002, … 366 %M 月份全名称,例如:January, February … December %m 以数值形式显示的月份名称,前导加 0,例如:01, 02, … 12 %p AM 或 PM,取决于其他时间说明符 %S 秒(00-59) %s 与 %S 相同 %W 工作日的全称,例如:Sunday, Monday, …, Saturday %T 表示时间,24 小时格式 hh:mm:ss %r 表示时间,12 小时格式 hh:mm:ss AM/PM %f 微秒 %I 小时(01-12) %i 分钟,数值(00-59) %e 月的天,数值(0-31) %c 月,数值(1-12) %l 小时(1-12) %k 小时(0-23) %D 带有英文后缀(0th, 1st, 2nd, 3rd, …) %x 年,其中的星期一是周的第一天,4 位,与 %v 使用 %X 年,其中的星期日是周的第一天,4 位,与 %V 使用 %w 周的天(0=星期日,6=星期六) %u 周(00..53),其中星期一是一周的第一天 %U 周(00..53),其中星期日是一周的第一天 %v 周(01..53),其中星期一是一周的第一天,必须携带 %x %V 周(01..53),其中星期日是一周的第一天,必须携带 %X -
示例
select str_to_date('2023-03-22','%Y-%m-%d'); str_to_date --------------------- 2023-03-22 00:00:00 select str_to_date('2022-05-26 11:30:00','%Y-%m-%d %H:%i:%s'); str_to_date --------------------- 2022-05-26 11:30:00 (1 row) select str_to_date(20220526113000,'%Y%m%d%H%i%s'); str_to_date --------------------- 2022-05-26 11:30:00 (1 row)
10.11. to_yminterval
-
功能
将日期字符串转换为
interval year to month类型输出。 -
函数
to_yminterval(text) -
参数
表 to_yminterval 参数说明
参数 说明 text 参数类型:char、nchar、varchar、varchar2、nvarchar2。 参数格式要求如下所示。
-
'y-m(数字-数字)':y 范围:0-999999999(最大为 9 位数),m 范围:0-11,前面可以带正负号,不带默认为正。正负号含义与数学的正负号相同。'1-1' 格式的字符串,其间可以任意带空格,如:'1 - 1'。
-
'PyYmMdDThHmiMsS (P数字Y数字M数字DT数字H数字M数字S)':以字母 P 开头,字母 T 用于定义时间单位。如果需要带上时分秒(H、M、S)需要用字母 T 连接;年月日时分秒这些单位可以任意组合,如:P1Y1M(一年一月)、P1MT1H(一月一小时)、PT1H(一小时)。y、m、d、h、mi 的范围:0-999999999(最大为 9 位数),s 的范围:可以是整数也可以是小数,整数范围为 0 - 999999999(最大为 9 位数),小数范围:0.0 - 999999999.999999999(最大为 9 位数)。'P' 前面可以带负号,不带负号默认为正,不可以带正号。字母 P 或者如果是带负号的话,负号前面可以带空格,其他位置不能有空格,如:'p1Y1M' 或者 '-P1Y1M'。月份值大于 11 会进位为 1 年,即:1Y13M 返回 2 年 1 月,返回值会将字符串中的天(D)、时(H)、分(M)、秒(S)的值忽略。
-
返回默认值,固定格式为:TO_YMINTERVAL( 'xxxx' DEFAULT 'x-x' ON CONVERSION ERROR )。
-
-
示例
-
仅传入一个参数
a. 传入参数为 SQL 格式
SELECT TO_YMINTERVAL(' 2019-01'); to_yminterval ------------------ 2019 years 1 mon (1 row) SELECT TO_YMINTERVAL(' - 2019 - 01 '); to_yminterval --------------------- -2019 years -1 mons (1 row)b. 传入参数为 ISO 格式
SELECT TO_YMINTERVAL(' P2Y1M'); to_yminterval --------------- 2 years 1 mon (1 row) SELECT TO_YMINTERVAL('- P2Y1M'); to_yminterval ------------------ -2 years -1 mons (1 row) -
传入一个参数,并附带默认值
a. 默认值为 SQL 格式
SELECT TO_YMINTERVAL('- 2019 - 01' DEFAULT '2019-01' ON CONVERSION ERROR); to_yminterval --------------------- -2019 years -1 mons (1 row) SELECT TO_YMINTERVAL('2019AA - 01' DEFAULT '2019-01' ON CONVERSION ERROR); to_yminterval ------------------ 2019 years 1 mon (1 row) SELECT TO_YMINTERVAL('2019-01' DEFAULT '2019-0AAA1' ON CONVERSION ERROR); ERROR: invalid input syntax for type interval: "2019-0AAA1" SELECT TO_YMINTERVAL('2019AA - 01' DEFAULT '2019-01' ON CONVERSION ERROR); to_yminterval ------------------ 2019 years 1 mon (1 row) SELECT TO_YMINTERVAL('2019AA - 01' DEFAULT '+2019-01' ON CONVERSION ERROR); to_yminterval ------------------ 2019 years 1 mon (1 row) SELECT TO_YMINTERVAL('2019AA - 01' DEFAULT '-2019-01' ON CONVERSION ERROR); to_yminterval --------------------- -2019 years -1 mons (1 row)b. 默认值为 ISO 格式
SELECT TO_YMINTERVAL('2019AA - 01' DEFAULT 'P2Y1M' ON CONVERSION ERROR); to_yminterval --------------- 2 years 1 mon (1 row) SELECT TO_YMINTERVAL('2019-01' DEFAULT 'P2YAAAAAAAAAAAA1M' ON CONVERSION ERROR); ERROR: invalid input syntax for type interval: "P2YAAAAAAAAAAAA1M" SELECT TO_YMINTERVAL('2019AA - 01' DEFAULT '+P2Y1M' ON CONVERSION ERROR); ERROR: invalid input syntax for type interval: "+P2Y1M" SELECT TO_YMINTERVAL('2019AA - 01' DEFAULT '-P2Y1M' ON CONVERSION ERROR); to_yminterval ------------------ -2 years -1 mons (1 row) -
传入参数为空值或 NULL 值
SELECT TO_YMINTERVAL('') to_yminterval --------------- (1 row) SELECT TO_YMINTERVAL(NULL); to_yminterval --------------- (1 row)
-
10.12. mysql 关键字 INTERVAL
-
功能
MySQL 模式内的 INTERVAL 关键字主要用于处理日期和时间之间的间隔。
- 计算日期和时间之间的间隔
- 在查询中执行日期和时间的加减运算
- 在日期和时间函数中使用
-
语法
INTERVAL expr unit -
参数
表 INTERVAL 参数说明
参数 说明 expr 表达式或值,用于指定间隔的数量。 unit 表示间隔的单位,可以是以下之一。 表 unit 参数说明
unit MICROSECOND SECOND MINUTE HOUR DAY WEEK MONTH QUARTER YEAR SECOND_MICROSECOND MINUTE_MICROSECOND MINUTE_SECOND HOUR_MICROSECOND HOUR_SECOND HOUR_MINUTE DAY_MICROSECOND DAY_SECOND DAY_MINUTE DAY_HOUR YEAR_MONTH -
示例
计算日期和时间之间的间隔:
SELECT INTERVAL 5 DAY; -- 返回一个间隔为 5 天的时间段 SELECT INTERVAL 2 HOUR; -- 返回一个间隔为 2 小时的时间段在查询中执行日期和时间的加减运算:
SELECT NOW() + INTERVAL 1 WEEK; -- 返回当前日期时间加上 1 周后的结果 SELECT CURDATE() - INTERVAL 1 MONTH; -- 返回当前日期减去 1 个月后的结果在日期和时间函数中使用:
SELECT DATE_ADD(NOW(), INTERVAL 3 MONTH); -- 返回当前日期时间加上 3 个月后的结果 SELECT DATE_SUB(NOW(), INTERVAL 1 HOUR); -- 返回当前日期时间减去 1 小时后的结果 -
注意
INTERVAL表达式中的 expr 可以是正数,列名以及表达式。INTERVAL表达式中的 unit 可以与日期和时间函数一起使用,以进行更复杂的计算。INTERVAL表达式可以与日期和时间类型的列进行运算。
10.13. sessiontimezone
-
功能
SESSIONTIMEZONE返回当前会话的时区。返回类型是时区偏移量(格式 '[+|-]TZH:TZM')或时区区域名称,可以使用set timezone和alter system set timezone实现。例如set timezone = '+8:00'; alter system set timezone = '+8:00';。 -
语法
SELECT SESSIONTIMEZONE FROM DUAL;
10.14. weekday()
-
功能
weekday 函数返回输入日期类型参数对应的星期数索引值。
-
返回值
- 星期一 :0
- 星期二 :1
- 星期三 :2
- 星期四 :3
- 星期五 :4
- 星期六 :5
- 星期日 :6
-
示例
uxdb=# select weekday('2024/2/27'); weekday --------- 1 (1 row) uxdb=# select weekday('2024/2/26'); weekday --------- 0 (1 row) uxdb=# select weekday('2024/2/25'); weekday --------- 6 (1 row)
11. Enum 支持函数
对于枚举类型,有几个函数可以在不硬编码特定枚举类型值的情况下进行更清晰的编程。这些函数列在表 Enum 支持函数中。示例假设创建了一个枚举类型:
CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple');
| 函数 | 描述 | 示例 |
|---|---|---|
enum_first ( anyenum ) → anyenum | 返回输入枚举类型的第一个值。 | enum_first(null::rainbow) → red |
enum_last ( anyenum ) → anyenum | 返回输入枚举类型的最后一个值。 | enum_last(null::rainbow) → purple |
enum_range ( anyenum ) → anyarray | 返回输入枚举类型的所有值的有序数组。 | enum_range(null::rainbow) → {red,orange,yellow,green,blue,purple} |
enum_range ( anyenum, anyenum ) → anyarray | 返回两个给定枚举值之间的范围,以有序数组的形式表示。这些值必须来自同一枚举类型。如果第一个参数为 null,则结果将以枚举类型的第一个值开始。如果第二个参数为 null,则结果将以枚举类型的最后一个值结束。 | enum_range('orange'::rainbow, 'green'::rainbow) → {orange,yellow,green}enum_range(NULL, 'green'::rainbow) → {red,orange,yellow,green}enum_range('orange'::rainbow, NULL) → {orange,yellow,green,blue,purple} |
请注意,除了 enum_range 的两个参数形式之外,这些函数都会忽略传递给它们的特定值;它们只关心其声明的数据类型。可以传递 null 或特定类型的值,结果相同。通常将这些函数应用于表列或函数参数,而不是像示例中使用硬编码的类型名称。
12. 几何函数和操作符
几何类型 point、box、lseg、line、path、polygon 和 circle 有一大套本地支持函数和操作符,如表表 几何操作符、表 几何函数和表 几何类型转换函数中所示。
| 操作符 | 描述 | 示例 |
|---|---|---|
geometric_type + point → geometric_type | 将第二个 point 的坐标添加到第一个参数的每个点的坐标中,从而执行平移。适用于 point、box、path、circle。 | box '(1,1),(0,0)' + point '(2,0)' → (3,1),(2,0) |
path + path → path | 连接两个开放路径(如果任一路径为封闭路径,则返回 NULL)。 | path '[(0,0),(1,1)]' + path '[(2,2),(3,3),(4,4)]' → [(0,0),(1,1),(2,2),(3,3),(4,4)] |
geometric_type - point → geometric_type | 从第二个参数的坐标中减去第一个参数中每个点的坐标,从而执行平移操作。适用于 point、box、path、circle。 | box '(1,1),(0,0)' - point '(2,0)' → (-1,1),(-2,0) |
geometric_type * point → geometric_type | 将第一个参数中的每个点乘以第二个参数的 point(将点视为由实部和虚部表示的复数,并执行标准复数乘法)。如果将第二个 point 解释为向量,则相当于将对象的大小和距离从原点缩放为向量的长度,并将其逆时针旋转到向量从 x 轴的角度。适用于 point、box、path、circle。 | path '((0,0),(1,0),(1,1))' * point '(3.0,0)' → ((0,0),(3,0),(3,3))path '((0,0),(1,0),(1,1))' * point(cosd(45), sind(45)) → ((0,0),(0.7071067811865475,0.7071067811865475),(0,1.414213562373095)) |
geometric_type / point → geometric_type | 将第一个参数中的每个点除以第二个参数的 point(将点视为由实部和虚部表示的复数,并执行标准复数除法)。如果将第二个 point 解释为向量,则相当于将对象的大小和距离从原点缩小为向量的长度,并将其顺时针旋转到向量从 x 轴的角度。适用于 point、box、path、circle。 | path '((0,0),(1,0),(1,1))' / point '(2.0,0)' → ((0,0),(0.5,0),(0.5,0.5))path '((0,0),(1,0),(1,1))' / point(cosd(45), sind(45)) → ((0,0),(0.7071067811865476,-0.7071067811865476),(1.4142135623730951,0)) |
@-@ geometric_type → double precision | 计算总长度。适用于 lseg、path。 | @-@ path '[(0,0),(1,0),(1,1)]' → 2 |
@@ geometric_type → point | 计算中心点。适用于 box、lseg、polygon、circle。 | @@ box '(2,2),(0,0)' → (1,1) |
# geometric_type → integer | 返回点的数量。适用于 path、polygon。 | # path '((1,0),(0,1),(-1,0))' → 3 |
geometric_type # geometric_type → point | 计算交点,如果没有则返回 NULL。适用于 lseg、line。 | lseg '[(0,0),(1,1)]' # lseg '[(1,0),(0,1)]' → (0.5,0.5) |
box # box → box | 计算两个框的交集,如果没有则返回 NULL。 | box '(2,2),(-1,-1)' # box '(1,1),(-2,-2)' → (1,1),(-1,-1) |
geometric_type ## geometric_type → point | 计算第一个对象在第二个对象上的最近点。适用于以下类型对: (point, box), (point, lseg), (point, line), (lseg, box), (lseg, lseg), (line, lseg)。 | point '(0,0)' ## lseg '[(2,0),(0,2)]' → (1,1) |
geometric_type <-> geometric_type → double precision | 计算对象之间的距离。适用于所有七种几何类型,对于 point 与另一种几何类型的所有组合,以及以下附加类型对: (box, lseg), (lseg, line), (polygon, circle)(以及交换器情况)。 | circle '<(0,0),1>' <-> circle '<(5,0),1>' → 3 |
geometric_type @> geometric_type → boolean | 第一个对象是否包含第二个对象? 适用于以下类型对: (box, point), (box, box), (path, point), (polygon, point), (polygon, polygon), (circle, point), (circle, circle). | circle '<(0,0),2>' @> point '(1,1)' → t |
geometric_type <@ geometric_type → boolean | 第一个对象是否包含在第二个对象中或在其上面? 可用于以下类型对:(point,box),(point,lseg),(point,line),(point,path),(point,polygon),(point,circle),(box,box),(lseg,box),(lseg,line),(polygon,polygon),(circle,circle)。 | point '(1,1)' <@ circle '<(0,0),2>' → t |
geometric_type && geometric_type → boolean | 这些对象是否重叠?(有一个共同点即为真。) 可用于 box,polygon,circle。 | box '(1,1),(0,0)' && box '(2,2),(0,0)' → t |
geometric_type << geometric_type → boolean | 第一个对象是否严格在第二个对象左侧? 可用于 point,box,polygon,circle。 | circle '<(0,0),1>' << circle '<(5,0),1>' → t |
geometric_type >> geometric_type → boolean | 第一个对象是否严格在第二个对象右侧? 可用于 point,box,polygon,circle。 | circle '<(5,0),1>' >> circle '<(0,0),1>' → t |
geometric_type &< geometric_type → boolean | 第一个对象是否不向右延伸到第二个对象? 可用于 box,polygon,circle。 | box '(1,1),(0,0)' &< box '(2,2),(0,0)' → t |
geometric_type &> geometric_type → boolean | 第一个对象是否不延伸到第二个对象的左侧? 可用于 box、polygon、circle。 | box '(3,3),(0,0)' &> box '(2,2),(0,0)' → t |
geometric_type <<| geometric_type → boolean | 第一个对象是否严格在第二个对象下方? 可用于 point、box、polygon、circle。 | box '(3,3),(0,0)' <<| box '(5,5),(3,4)' → t |
geometric_type |>> geometric_type → boolean | 第一个对象是否严格在第二个对象上方? 可用于 point、box、polygon、circle。 | box '(5,5),(3,4)' |>> box '(3,3),(0,0)' → t |
geometric_type &<| geometric_type → boolean | 第一个对象是否不延伸到第二个对象上方? 可用于 box、polygon、circle。 | box '(1,1),(0,0)' &<| box '(2,2),(0,0)' → t |
geometric_type |&> geometric_type → boolean | 第一个对象是否不延伸到第二个对象下方? 可用于 box、polygon、circle。 | box '(3,3),(0,0)' |&> box '(2,2),(0,0)' → t |
box <^ box → boolean | 第一个对象是否在第二个对象下方(允许边缘相接)? | box '((1,1),(0,0))' <^ box '((2,2),(1,1))' → t |
box >^ box → boolean | 第一个对象是否在第二个对象上方(允许边缘相接)? | box '((2,2),(1,1))' >^ box '((1,1),(0,0))' → t |
geometric_type ?# geometric_type → boolean | 这些对象是否相交? 可用于以下类型对: (box, box),(lseg, box), (lseg, lseg), (lseg, line), (line, box), (line, line), (path, path). | lseg '[(-1,0),(1,0)]' ?# box '(2,2),(-2,-2)' → t |
?- line → boolean?- lseg → boolean | 线是否水平? | ?- lseg '[(-1,0),(1,0)]' → t |
point ?- point → boolean | 点是否水平对齐(即具有相同的 y 坐标)? | point '(1,0)' ?- point '(0,0)' → t |
?| line → boolean?| lseg → boolean | 线是否垂直? | ?| lseg '[(-1,0),(1,0)]' → f |
point ?| point → boolean | 点是否垂直对齐(即具有相同的 x 坐标)? | point '(0,1)' ?| point '(0,0)' → t |
line ?-| line → booleanlseg ?-| lseg → boolean | 线是否垂直? | lseg '[(0,0),(0,1)]' ?-| lseg '[(0,0),(1,0)]' → t |
line ?|| line → booleanlseg ?|| lseg → boolean | 线是否平行? | lseg '[(-1,0),(1,0)]' ?|| lseg '[(-1,2),(1,2)]' → t |
geometric_type ~= geometric_type → boolean | 这些对象是否相同? 适用于 point、box、 polygon、circle。 | polygon '((0,0),(1,1))' ~= polygon '((1,1),(0,0))' → t |
[a] |
注意
请注意,“同”操作符~=表示point、box、polygon和circle类型的通常相等概念。一些几何类型也有一个=操作符,但=仅比较相等的面积。其他标量比较操作符(如<=等),如果适用于这些类型,也会比较面积。
在 UXsinoDB 之前版本,点的严格下/上比较操作符 point <<| point 和 point |>> point 分别称为 <^ 和 >^。这些名称仍然可用,但已被弃用,并最终将被删除。
| 函数 | 描述 | 示例 |
|---|---|---|
area ( geometric_type ) → double precision | 计算面积。适用于 box、path、circle。输入的 path 必须是封闭的,否则返回 NULL。此外,如果 path 自相交,则结果可能是无意义的。 | area(box '(2,2),(0,0)') → 4 |
center ( geometric_type ) → point | 计算中心点。适用于 box、circle。 | center(box '(1,2),(0,0)') → (0.5,1) |
diagonal ( box ) → lseg | 提取盒子的对角线作为线段(与 lseg(box) 相同)。 | diagonal(box '(1,2),(0,0)') → [(1,2),(0,0)] |
diameter ( circle ) → double precision | 计算圆的直径。 | diameter(circle '<(0,0),2>') → 4 |
height ( box ) → double precision | 计算框的垂直大小。 | height(box '(1,2),(0,0)') → 2 |
isclosed ( path ) → boolean | 路径是否闭合? | isclosed(path '((0,0),(1,1),(2,0))') → t |
isopen ( path ) → boolean | 路径是否开放? | isopen(path '[(0,0),(1,1),(2,0)]') → t |
length ( geometric_type ) → double precision | 计算总长度。适用于 lseg,path。 | length(path '((-1,0),(1,0))') → 4 |
npoints ( geometric_type ) → integer | 返回点数。适用于 path,polygon。 | npoints(path '[(0,0),(1,1),(2,0)]') → 3 |
pclose ( path ) → path | 将路径转换为闭合形式。 | pclose(path '[(0,0),(1,1),(2,0)]') → ((0,0),(1,1),(2,0)) |
popen ( path ) → path | 将路径转换为开放形式。 | popen(path '((0,0),(1,1),(2,0))') → [(0,0),(1,1),(2,0)] |
radius ( circle ) → double precision | 计算圆的半径。 | radius(circle '<(0,0),2>') → 2 |
slope ( point, point ) → double precision | 计算通过两个点的线的斜率。 | slope(point '(0,0)', point '(2,1)') → 0.5 |
width ( box ) → double precision | 计算盒子的水平大小。 | width(box '(1,2),(0,0)') → 1 |
| 函数 | 描述 | 示例 |
|---|---|---|
box ( circle ) → box | 计算内切于圆的盒子。 | box(circle '<(0,0),2>') → (1.414213562373095,1.414213562373095),(-1.414213562373095,-1.414213562373095) |
box ( point ) → box | 将点转换为空盒子。 | box(point '(1,0)') → (1,0),(1,0) |
box ( point, point ) → box | 将任意两个角点转换为盒子。 | box(point '(0,1)', point '(1,0)') → (1,1),(0,0) |
box ( polygon ) → box | 计算多边形的边界框。 | box(polygon '((0,0),(1,1),(2,0))') → (2,1),(0,0) |
bound_box ( box, box ) → box | 计算两个盒子的边界框。 | bound_box(box '(1,1),(0,0)', box '(4,4),(3,3)') → (4,4),(0,0) |
circle ( box ) → circle | 计算包含盒子的最小圆。 | circle(box '(1,1),(0,0)') → <(0.5,0.5),0.7071067811865476> |
circle ( point, double precision ) → circle | 从中心和半径构造圆。 | circle(point '(0,0)', 2.0) → <(0,0),2> |
circle ( polygon ) → circle | 将多边形转换为圆。圆心是多边形点的位置的平均值,半径是多边形点到该中心的平均距离。 | circle(polygon '((0,0),(1,3),(2,0))') → <(1,1),1.6094757082487299> |
line ( point, point ) → line | 将两个点转换为它们之间的直线。 | line(point '(-1,0)', point '(1,0)') → {0,-1,0} |
lseg ( box ) → lseg | 将盒子的对角线提取为线段。 | lseg(box '(1,0),(-1,0)') → [(1,0),(-1,0)] |
lseg ( point, point ) → lseg | 从两个端点构造线段。 | lseg(point '(-1,0)', point '(1,0)') → [(-1,0),(1,0)] |
path ( polygon ) → path | 将多边形转换为具有相同点列表的闭合路径。 | path(polygon '((0,0),(1,1),(2,0))') → ((0,0),(1,1),(2,0)) |
point ( double precision, double precision ) → point | 从其坐标构造点。 | point(23.4, -44.5) → (23.4,-44.5) |
point ( box ) → point | 计算盒子的中心。 | point(box '(1,0),(-1,0)') → (0,0) |
point ( circle ) → point | 计算圆的中心。 | point(circle '<(0,0),2>') → (0,0) |
point ( lseg ) → point | 计算线段的中心。 | point(lseg '[(-1,0),(1,0)]') → (0,0) |
point ( polygon ) → point | 计算多边形的中心(多边形点的位置的平均值)。 | point(polygon '((0,0),(1,1),(2,0))') → (1,0.3333333333333333) |
polygon ( box ) → polygon | 将盒子转换为 4 点多边形。 | polygon(box '(1,1),(0,0)') → ((0,0),(0,1),(1,1),(1,0)) |
polygon ( circle ) → polygon | 将圆转换为 12 个点的多边形。 | polygon(circle '<(0,0),2>') → ((-2,0),(-1.7320508075688774,0.9999999999999999),(-1.0000000000000002,1.7320508075688772),(-1.2246063538223773e-16,2),(0.9999999999999996,1.7320508075688774),(1.732050807568877,1.0000000000000007),(2,2.4492127076447545e-16),(1.7320508075688776,-0.9999999999999994),(1.0000000000000009,-1.7320508075688767),(3.673819061467132e-16,-2),(-0.9999999999999987,-1.732050807568878),(-1.7320508075688767,-1.0000000000000009)) |
polygon ( integer, circle ) → polygon | 将圆转换为 n 个点的多边形。 | polygon(4, circle '<(3,0),1>') → ((2,0),(3,1),(4,1.2246063538223773e-16),(3,-1)) |
polygon ( path ) → polygon | 将闭合路径转换为具有相同点列表的多边形。 | polygon(path '((0,0),(1,1),(2,0))') → ((0,0),(1,1),(2,0)) |
可以像数组一样使用索引 0 和 1 来访问 point 的两个组件数字。例如,如果 t.p 是 point 列,则 SELECT p[0] FROM t 检索 X 坐标,UPDATE t SET p[1] = ... 更改 Y 坐标。同样,类型为 box 或 lseg 的值可以被视为两个 point 值的数组。
13. 网络地址函数和操作符
IP 网络地址类型 cidr 和 inet 支持常见的比较操作符,如表 比较操作符所示,以及表 IP 地址操作符和表 IP 地址函数中显示的专用操作符和函数。
任何 cidr 值都可以隐式转换为 inet;因此,下面显示的在 inet 上运行的操作符和函数也适用于 cidr 值。(如果有 inet 和 cidr 的不同函数,则是因为两种情况的行为应该不同。)此外,允许将 inet 值转换为 cidr。这样做时,掩码右侧的任何位都会被静默地清零,以创建一个有效的 cidr 值。
| 操作符 | 说明 | 示例 |
|---|---|---|
inet << inet → boolean | 子网是否严格包含子网? 此操作符和接下来的四个操作符都用于测试子网包含关系。它们只考虑两个地址的网络部分(忽略掉任何在掩码右侧的位),并确定一个网络是否与另一个网络相同或是子网。 | inet '192.168.1.5' << inet '192.168.1/24' → tinet '192.168.0.5' << inet '192.168.1/24' → finet '192.168.1/24' << inet '192.168.1/24' → f |
inet <<= inet → boolean | 子网是否被包含或相等? | inet '192.168.1/24' <<= inet '192.168.1/24' → t |
inet >> inet → boolean | 子网是否严格包含子网? | inet '192.168.1/24' >> inet '192.168.1.5' → t |
inet >>= inet → boolean | 子网是否包含或相等子网? | inet '192.168.1/24' >>= inet '192.168.1/24' → t |
inet && inet → boolean | 两个子网是否相互包含或相等? | inet '192.168.1/24' && inet '192.168.1.80/28' → tinet '192.168.1/24' && inet '192.168.2.0/28' → f |
~ inet → inet | 计算按位取反。 | ~ inet '192.168.1.6' → 63.87.254.249 |
inet & inet → inet | 计算按位与。 | inet '192.168.1.6' & inet '0.0.0.255' → 0.0.0.6 |
inet | inet → inet | 计算按位或。 | inet '192.168.1.6' | inet '0.0.0.255' → 192.168.1.255 |
inet + bigint → inet | 将偏移量添加到地址。 | inet '192.168.1.6' + 25 → 192.168.1.31 |
bigint + inet → inet | 将偏移量添加到地址。 | 200 + inet '::ffff:fff0:1' → ::ffff:255.240.0.201 |
inet - bigint → inet | 从地址中减去偏移量。 | inet '192.168.1.43' - 36 → 192.168.1.7 |
inet - inet → bigint | 计算两个地址之间的差异。 | inet '192.168.1.43' - inet '192.168.1.19' → 24inet '::1' - inet '::ffff:1' → -4294901760 |
| 函数 | 描述 | 示例 |
|---|---|---|
abbrev ( inet ) → text | 创建文本的缩写显示格式。(结果与 inet 输出函数相同;只有与显式转换为 text 的结果相比,由于历史原因,它永远不会抑制掩码部分。) | abbrev(inet '10.1.0.0/32') → 10.1.0.0 |
abbrev ( cidr ) → text | 创建文本的缩写显示格式。(缩写包括在掩码右侧的所有零八位) | abbrev(cidr '10.1.0.0/16') → 10.1/16 |
broadcast ( inet ) → inet | 计算地址所在网络的广播地址。 | broadcast(inet '192.168.1.5/24') → 192.168.1.255/24 |
family ( inet ) → integer | 返回地址的协议族:IPv4 为 4,IPv6 为 6。 | family(inet '::1') → 6 |
host ( inet ) → text | 返回 IP 地址的文本形式,忽略掩码。 | host(inet '192.168.1.0/24') → 192.168.1.0 |
hostmask ( inet ) → inet | 计算地址所在网络的主机掩码。 | hostmask(inet '192.168.23.20/30') → 0.0.0.3 |
inet_merge ( inet, inet ) → cidr | 计算包含给定网络的最小网络。 | inet_merge(inet '192.168.1.5/24', inet '192.168.2.5/24') → 192.168.0.0/22 |
inet_same_family ( inet, inet ) → boolean | 测试地址是否属于同一 IP 族。 | inet_same_family(inet '192.168.1.5/24', inet '::1') → f |
masklen ( inet ) → integer | 返回掩码长度(以位为单位)。 | masklen(inet '192.168.1.5/24') → 24 |
netmask ( inet ) → inet | 计算地址网络的网络掩码。 | netmask(inet '192.168.1.5/24') → 255.255.255.0 |
network ( inet ) → cidr | 返回地址的网络部分,将掩码右侧的内容归零。(这相当于将值转换为 cidr。) | network(inet '192.168.1.5/24') → 192.168.1.0/24 |
set_masklen ( inet, integer ) → inet | 设置 inet 值的掩码长度。地址部分不会改变。 | set_masklen(inet '192.168.1.5/24', 16) → 192.168.1.5/16 |
set_masklen ( cidr, integer ) → cidr | 设置 cidr 值的掩码长度。新掩码右侧的地址位设置为零。 | set_masklen(cidr '192.168.1.0/24', 16) → 192.168.0.0/16 |
text ( inet ) → text | 返回未缩写的 IP 地址和掩码长度的文本。(这与显式转换为 text 的结果相同。) | text(inet '192.168.1.5') → 192.168.1.5/32 |
提示
abbrev、host和text函数主要用于提供易于阅读的格式,而不是进行计算。
IP 地址的备选显示格式。MAC 地址类型 macaddr 和 macaddr8 支持通常的比较操作符,如表 比较操作符所示,以及表 MAC 地址函数所示的专用函数。此外,它们还支持位逻辑操作符 ~、& 和 |(NOT、AND 和 OR),就像上面所示的 IP 地址一样。
| 函数 | 描述 | 示例 |
|---|---|---|
trunc ( macaddr ) → macaddr | 将地址的最后 3 个字节设置为零。剩余的前缀可以与特定制造商相关联(使用未包含在 UXsinoDB 中的数据)。 | trunc(macaddr '12:34:56:78:90:ab') → 12:34:56:00:00:00 |
trunc ( macaddr8 ) → macaddr8 | 将地址的最后 5 个字节设置为零。剩余的前缀可以与特定制造商相关联(使用未包含在 UXsinoDB 中的数据)。 | trunc(macaddr8 '12:34:56:78:90:ab:cd:ef') → 12:34:56:00:00:00:00:00 |
macaddr8_set7bit ( macaddr8 ) → macaddr8 | 将地址的第 7 位设置为 1,创建所谓的修改 EUI-64,用于包含在 IPv6 地址中。 | macaddr8_set7bit(macaddr8 '00:34:56:ab:cd:ef') → 02:34:56:ff:fe:ab:cd:ef |
14. 文本搜索函数和操作符
总结了用于全文搜索的函数和操作符。
表 文本搜索操作符
| 操作符 | 说明 | 示例 |
|---|---|---|
tsvector @@ tsquery → booleantsquery @@ tsvector → boolean | tsvector 是否匹配 tsquery? (参数可以以任意顺序给出。) | to_tsvector('fat cats ate rats') @@ to_tsquery('cat & rat') → t |
text @@ tsquery → boolean | 隐式调用 to_tsvector() 后,文本字符串是否匹配 tsquery? | 'fat cats ate rats' @@ to_tsquery('cat & rat') → t |
tsvector @@@ tsquery → booleantsquery @@@ tsvector → boolean | 这是 @@ 的一个已弃用的同义词。 | to_tsvector('fat cats ate rats') @@@ to_tsquery('cat & rat') → t |
tsvector || tsvector → tsvector | 连接两个 tsvector。如果两个输入都包含词元位置,则第二个输入的位置会相应地调整。 | 'a:1 b:2'::tsvector || 'c:1 d:2 b:3'::tsvector → 'a':1 'b':2,5 'c':3 'd':4 |
tsquery && tsquery → tsquery | 将两个 tsquery 进行 AND 运算,生成一个匹配两个输入查询的文档的查询。 | 'fat | rat'::tsquery && 'cat'::tsquery → ( 'fat' | 'rat' ) & 'cat' |
tsquery || tsquery → tsquery | 将两个 tsquery 进行 OR 运算,生成一个匹配任意一个输入查询的文档的查询。 | 'fat | rat'::tsquery || 'cat'::tsquery → 'fat' | 'rat' | 'cat' |
!! tsquery → tsquery | 对 tsquery 进行否定运算,生成一个匹配不包含输入查询的文档的查询。 | !! 'cat'::tsquery → !'cat' |
tsquery <-> tsquery → tsquery | 构造一个短语查询,如果两个输入查询在连续的词元处匹配,则匹配。 | to_tsquery('fat') <-> to_tsquery('rat') → 'fat' <-> 'rat' |
tsquery @> tsquery → boolean | 第一个 tsquery 是否包含第二个?(这只考虑一个查询中出现的所有词元是否出现在另一个查询中,忽略组合操作符。) | 'cat'::tsquery @> 'cat & rat'::tsquery → f |
tsquery <@ tsquery → boolean | 第一个 tsquery 是否被第二个包含?(这只考虑一个查询中出现的所有词元是否出现在另一个查询中,忽略组合操作符。) | 'cat'::tsquery <@ 'cat & rat'::tsquery → t'cat'::tsquery <@ '!cat & rat'::tsquery → t |
除了这些专用操作符外,表 比较操作符中所示的通常的比较操作符也可用于 tsVector 和 tsquery 类型。这些对于文本搜索来说不是很有用,但是允许在这些类型的列上构建唯一的索引。
表 文本搜索函数
| 函数 | 说明 | 示例 |
|---|---|---|
array_to_tsvector ( text[] ) → tsvector | 将文本字符串数组转换为 tsvector。给定的字符串按原样用作词元,不进行进一步处理。数组元素不能是空字符串或 NULL。 | array_to_tsvector('{fat,cat,rat}'::text[]) → 'cat' 'fat' 'rat' |
get_current_ts_config ( ) → regconfig | 返回当前默认文本搜索配置的 OID(由 default_text_search_config 指定)。 | get_current_ts_config() → english |
length ( tsvector ) → integer | 返回 tsvector 中词元的数量。 | length('fat:2,4 cat:3 rat:5A'::tsvector) → 3 |
numnode ( tsquery ) → integer | 返回 tsquery 中词元和操作符的数量。 | numnode('(fat & rat) | cat'::tsquery) → 5 |
plainto_tsquery ( [ config regconfig, ] query text ) → tsquery | 将文本转换为 tsquery,根据指定或默认配置规范化单词。字符串中的任何标点符号都将被忽略(它不确定查询操作符)。结果查询匹配包含文本中所有非停用词的文档。 | plainto_tsquery('english', 'The Fat Rats') → 'fat' & 'rat' |
phraseto_tsquery ( [ config regconfig, ] query text ) → tsquery | 将文本转换为 tsquery,根据指定或默认配置规范化单词。字符串中的任何标点符号都将被忽略(它不确定查询操作符)。生成的查询匹配包含文本中所有非停用词的短语。 | phraseto_tsquery('english', 'The Fat Rats') → 'fat' <-> 'rat'phraseto_tsquery('english', 'The Cat and Rats') → 'cat' <2> 'rat' |
websearch_to_tsquery ( [ config regconfig, ] query text ) → tsquery | 将文本转换为 tsquery,根据指定或默认配置规范化单词。引用的单词序列将转换为短语测试。单词“or”被理解为产生 OR 操作符,破折号产生 NOT 操作符;其他标点符号被忽略。这近似于一些常见的网络搜索工具的行为。 | websearch_to_tsquery('english', '"fat rat" or cat dog') → 'fat' <-> 'rat' | 'cat' & 'dog' |
querytree ( tsquery ) → text | 生成 tsquery 的可索引部分的表示形式。空结果或仅 T 表示不可索引的查询。 | querytree('foo & ! bar'::tsquery) → 'foo' |
setweight ( vector tsvector, weight "char" ) → tsvector | 为 vector 的每个元素分配指定的 weight。 | setweight('fat:2,4 cat:3 rat:5B'::tsvector, 'A') → 'cat':3A 'fat':2A,4A 'rat':5A |
setweight ( vector tsvector, weight "char", lexemes text[] ) → tsvector | 为列在 lexemes 中的元素分配指定的 weight。在 lexemes 中的字符串按原样作为词元,不进行进一步处理。忽略不与 vector 中任何词元匹配的字符串。 | setweight('fat:2,4 cat:3 rat:5,6B'::tsvector, 'A', '{cat,rat}') → 'cat':3A 'fat':2,4 'rat':5A,6A |
strip ( tsvector ) → tsvector | 从 tsvector 中删除位置和权重信息。 | strip('fat:2,4 cat:3 rat:5A'::tsvector) → 'cat' 'fat' 'rat' |
to_tsquery ( [ config regconfig, ] query text ) → tsquery | 将文本转换为 tsquery,根据指定或默认配置规范化单词。单词必须使用有效的 tsquery 操作符组合。 | to_tsquery('english', 'The & Fat & Rats') → 'fat' & 'rat' |
to_tsvector ( [ config regconfig, ] document text ) → tsvector | 将文本转换为 tsvector,根据指定或默认配置规范化单词。结果中包含位置信息。 | to_tsvector('english', 'The Fat Rats') → 'fat':2 'rat':3 |
to_tsvector ( [ config regconfig, ] document json ) → tsvectorto_tsvector ( [ config regconfig, ] document jsonb ) → tsvector | 将 JSON 文档中的每个字符串值转换为 tsvector,根据指定或默认配置规范化单词。然后按文档顺序将结果连接起来生成输出。位置信息的生成方式是在每对字符串值之间生成一个停用词。(请注意,当输入为 jsonb 时,JSON 对象的字段的“文档顺序”是依赖于实现的;请观察示例中的差异。) | to_tsvector('english', '{"aa": "The Fat Rats", "b": "dog"}'::json) → 'dog':5 'fat':2 'rat':3to_tsvector('english', '{"aa": "The Fat Rats", "b": "dog"}'::jsonb) → 'dog':1 'fat':4 'rat':5 |
json_to_tsvector ( [ config regconfig, ] document json, filter jsonb ) → tsvectorjsonb_to_tsvector ( [ config regconfig, ] document jsonb, filter jsonb ) → tsvector | 选择由 filter 请求的 JSON 文档中的每个项目,并将每个项目转换为 tsvector,根据指定或默认配置规范化单词。然后按文档顺序连接结果以生成输出。位置信息生成为每对选定项目之间存在一个停用词。(请注意,当输入为 jsonb 时,JSON 对象的字段的“文档顺序”取决于实现。)filter 必须是包含零个或多个以下关键字的 jsonb 数组:"string"(包括所有字符串值),"numeric"(包括所有数字值),"boolean"(包括所有布尔值),"key"(包括所有键),或 "all"(包括所有上述)。作为特殊情况,filter 也可以是这些关键字之一的简单 JSON 值。 | json_to_tsvector('english', '{"a": "The Fat Rats", "b": 123}'::json, '["string", "numeric"]') → '123':5 'fat':2 'rat':3json_to_tsvector('english', '{"cat": "The Fat Rats", "dog": 123}'::json, '"all"') → '123':9 'cat':1 'dog':7 'fat':4 'rat':5 |
ts_delete ( vector tsvector, lexeme text ) → tsvector | 从 vector 中删除给定的 lexeme 的任何出现。lexeme 字符串按原样处理为词元,无需进一步处理。 | ts_delete('fat:2,4 cat:3 rat:5A'::tsvector, 'fat') → 'cat':3 'rat':5A |
ts_delete ( vector tsvector, lexemes text[] ) → tsvector | 从 vector 中删除 lexemes 中的任何词元。lexemes 中的字符串按原样处理为词元,无需进一步处理。忽略不与 vector 中的任何词元匹配的字符串。 | ts_delete('fat:2,4 cat:3 rat:5A'::tsvector, ARRAY['fat','rat']) → 'cat':3 |
ts_filter ( vector tsvector, weights "char"[] ) → tsvector | 从 vector 中选择给定 weights 的元素。 | ts_filter('fat:2,4 cat:3b,7c rat:5A'::tsvector, '{a,b}') → 'cat':3B 'rat':5A |
ts_headline ( [ config regconfig, ] document text, query tsquery [ , options text ] ) → text | 以简略形式显示 document 中与 query 匹配的结果,document 必须是原始文本而不是 tsvector。在匹配查询之前,文档中的单词将根据指定的或默认配置进行规范化。 | ts_headline('The fat cat ate the rat.', 'cat') → The fat <b>cat</b> ate the rat. |
ts_headline ( [ config regconfig, ] document json, query tsquery [ , options text ] ) → textts_headline ( [ config regconfig, ] document jsonb, query tsquery [ , options text ] ) → text | 以简略形式显示在 JSON document 中出现的与 query 匹配的结果。 | ts_headline('{"cat":"raining cats and dogs"}'::jsonb, 'cat') → {"cat": "raining <b>cats</b> and dogs"} |
ts_rank ( [ weights real[], ] vector tsvector, query tsquery [ , normalization integer ] ) → real | 计算一个分数,显示 vector 与 query 匹配的程度。 | ts_rank(to_tsvector('raining cats and dogs'), 'cat') → 0.06079271 |
ts_rank_cd ( [ weights real[], ] vector tsvector, query tsquery [ , normalization integer ] ) → real | 使用覆盖密度算法计算一个分数,显示 vector 与 query 匹配的程度。 | ts_rank_cd(to_tsvector('raining cats and dogs'), 'cat') → 0.1 |
ts_rewrite ( query tsquery, target tsquery, substitute tsquery ) → tsquery | 在 query 中替换 target 的出现次数为 substitute。 | ts_rewrite('a & b'::tsquery, 'a'::tsquery, 'foo|bar'::tsquery) → 'b' & ( 'foo' | 'bar' ) |
ts_rewrite ( query tsquery, select text ) → tsquery | 根据执行 SELECT 命令获得的目标和替换,替换 query 的部分内容。 | SELECT ts_rewrite('a & b'::tsquery, 'SELECT t,s FROM aliases') → 'b' & ( 'foo' | 'bar' ) |
tsquery_phrase ( query1 tsquery, query2 tsquery ) → tsquery | 构造一个短语查询,在连续的词素中搜索 query1 和 query2 的匹配(与 <-> 操作符相同)。 | tsquery_phrase(to_tsquery('fat'), to_tsquery('cat')) → 'fat' <-> 'cat' |
tsquery_phrase ( query1 tsquery, query2 tsquery, distance integer ) → tsquery | 构造一个短语查询,该查询搜索与 query1 和 query2 的匹配,这两个查询恰好出现在距离词元之间。 | tsquery_phrase(to_tsquery('fat'), to_tsquery('cat'), 10) → 'fat' <10> 'cat' |
tsvector_to_array ( tsvector ) → text[] | 将 tsVector 转换为词素数组。 | tsvector_to_array('fat:2,4 cat:3 rat:5A'::tsvector) → {cat,fat,rat} |
unnest ( tsvector ) → setof record ( lexeme text, positions smallint[], weights text ) | 将 tsVector 扩展为一组行,每个词素一行。 | select * from unnest('cat:3 fat:2,4 rat:5A'::tsvector) → lexeme | positions | weights--------+-----------+---------cat | {3} | {D}fat | {2,4} | {D,D}rat | {5} | {A} |
提示
所有接受可选regconfig参数的文本搜索函数都将在省略该参数时使用default_text_search_config指定的配置。
表 文本搜索调试函数中列出的函数主要用于文本搜索配置的开发和调试。它们主要有助于开发和调试新的文本搜索配置。
| 函数 | 描述 | 示例 |
|---|---|---|
ts_debug ( [ config regconfig, ] document text ) → setof record ( alias text, description text, token text, dictionaries regdictionary[], dictionary regdictionary, lexemes text[] ) | 根据指定或默认的文本搜索配置从 document 中提取和规范化标记,并返回有关每个标记如何处理的信息。 | ts_debug('english', 'The Brightest supernovaes') → (asciiword,"Word, all ASCII",The,{english_stem},english_stem,{}) ... |
ts_lexize ( dict regdictionary, token text ) → text[] | 如果输入标记已知于字典,则返回替换词元的数组;如果标记已知于字典但是是停用词,则返回空数组;如果不是已知词,则返回 NULL。 | ts_lexize('english_stem', 'stars') → {star} |
ts_parse ( parser_name text, document text ) → setof record ( tokid integer, token text ) | 使用指定的解析器从 document 中提取标记。 | ts_parse('default', 'foo - bar') → (1,foo) ... |
ts_parse ( parser_oid oid, document text ) → setof record ( tokid integer, token text ) | 使用 OID 指定的解析器从 document 中提取标记。 | ts_parse(3722, 'foo - bar') → (1,foo) ... |
ts_token_type ( parser_name text ) → setof record ( tokid integer, alias text, description text ) | 返回一个表,描述指定解析器可以识别的每种类型的标记。 | ts_token_type('default') → (1,asciiword,"Word, all ASCII") ... |
ts_token_type ( parser_oid oid ) → setof record ( tokid integer, alias text, description text ) | 返回一个表,描述由 OID 指定的解析器可以识别的每种类型的标记。 | ts_token_type(3722) → (1,asciiword,"Word, all ASCII") ... |
ts_stat ( sqlquery text [, weights text ] ) → setof record ( word text, ndoc integer, nentry integer ) | 执行 sqlquery,必须返回单个 tsvector 列,并返回有关数据中包含的每个不同词元的统计信息。 | ts_stat('SELECT vector FROM apod') → (foo,10,15) ... |
15. UUID 函数
UXsinoDB 包括一个生成 UUID 的函数:
gen_random_uuid () → uuid
此函数返回版本 4(随机)UUID。这是最常用的 UUID 类型,适用于大多数应用程序。
uuid-ossp 模块提供了其他实现生成 UUID 的标准算法的函数。
UXsinoDB 还提供了用于 UUID 的常规比较操作符,如表 比较操作符所示。
16. XML 函数
本节中描述的函数和函数式表达式操作 xml 类型的值。用于将类型 xml 转换为和从 xmlparse 和 xmlserialize 的函数式表达式在那里记录,而不是在本节中记录。
使用这些函数中的大多数函数需要使用 UXsinoDB 构建时使用 configure --with-libxml。
16.1. 生成 XML 内容
一组函数和函数式表达式可用于从 SQL 数据生成 XML 内容。因此,它们特别适用于将查询结果格式化为 XML 文档,以在客户端应用程序中处理。
16.1.1. xmlcomment
xmlcomment ( text ) → xml
函数 xmlcomment 创建一个包含指定文本作为内容的 XML 注释的 XML 值。文本不能包含 “--” 或以 “-” 结尾,否则生成的结构将不是有效的 XML 注释。如果参数为 null,则结果为 null。
例如:
SELECT xmlcomment('hello');
xmlcomment
--------------
<!--hello-->
16.1.2. xmlconcat
xmlconcat ( xml [, ...] ) → xml
函数 xmlconcat 将一系列单独的 XML 值连接起来,创建一个包含 XML 内容片段的单个值。空值将被省略;只有在没有非空参数时,结果才为空。
例如:
SELECT xmlconcat('<abc/>', '<bar>foo</bar>');
xmlconcat
----------------------
<abc/><bar>foo</bar>
如果存在 XML 声明,则组合方式如下。如果所有参数值都具有相同的 XML 版本声明,则在结果中使用该版本,否则不使用版本。如果所有参数值都具有独立声明值 “yes”,则在结果中使用该值。如果所有参数值都具有独立声明值,并且至少有一个是 “no”,则在结果中使用该值。否则,结果将没有独立声明。如果确定结果需要独立声明但没有版本声明,则将使用版本为 1.0 的版本声明,因为 XML 要求 XML 声明包含版本声明。在所有情况下,编码声明都将被忽略和删除。
例如:
SELECT xmlconcat('<?xml version="1.1"?><foo/>', '<?xml version="1.1" standalone="no"?><bar/>');
xmlconcat
-----------------------------------
<?xml version="1.1"?><foo/><bar/>
16.1.3. xmlelement
xmlelement ( NAME name [, XMLATTRIBUTES ( attvalue [ AS attname ] [, ...] ) ] [, content [, ...]] ) → xml
xmlelement 表达式使用给定的名称、属性和内容生成 XML 元素。语法中显示的 name 和 attname 项是简单标识符,而不是值。 attvalue 和 content 项是表达式,可以产生任何 UXsinoDB 数据类型。在 XMLATTRIBUTES 中的参数生成 XML 元素的属性; content 值将被连接以形成其内容。
例如:
SELECT xmlelement(name foo);
xmlelement
------------
<foo/>
SELECT xmlelement(name foo, xmlattributes('xyz' as bar));
xmlelement
------------------
<foo bar="xyz"/>
SELECT xmlelement(name foo, xmlattributes(current_date as bar), 'cont', 'ent');
xmlelement
-------------------------------------
<foo bar="2007-01-26">content</foo>
不是有效 XML 名称的元素和属性名称将被转义。通过将有问题的字符替换为序列 _xHHHH_ 来转义,其中 HHHH 是字符的 Unicode 十六进制表示。例如:
SELECT xmlelement(name "foo$bar", xmlattributes('xyz' as "a&b"));
xmlelement
----------------------------------
<foo_x0024_bar a_x0026_b="xyz"/>
如果属性值是列引用,则无需指定显式属性名称,此时列名将默认用作属性名称。在其他情况下,必须为属性指定显式名称。因此,此示例是有效的:
CREATE TABLE test (a xml, b xml);
SELECT xmlelement(name test, xmlattributes(a, b)) FROM test;
但这些不是:
SELECT xmlelement(name test, xmlattributes('constant'), a, b) FROM test;
SELECT xmlelement(name test, xmlattributes(func(a, b))) FROM test;
如果指定了元素内容,则将根据其数据类型进行格式化。如果内容本身是类型 xml,则可以构建复杂的 XML 文档。例如:
SELECT xmlelement(name foo, xmlattributes('xyz' as bar),
xmlelement(name abc),
xmlcomment('test'),
xmlelement(name xyz));
xmlelement
----------------------------------------------
<foo bar="xyz"><abc/><!--test--><xyz/></foo>
其他类型的内容将被格式化为有效的 XML 字符数据。这特别意味着字符 <、> 和 & 将被转换为实体。二进制数据(数据类型 bytea)将以 base64 或十六进制编码表示,具体取决于配置参数 xmlbinary 的设置。各个数据类型的特定行为与 SQL:2006 及更高版本中指定的行为相一致,以便与 UXsinoDB 映射对齐。
16.1.4. xmlforest
xmlforest ( content [ AS name ] [, ...] ) → xml
xmlforest 表达式使用给定的名称和内容生成 XML 树(序列)。与 xmlelement 一样,每个 name 必须是简单标识符,而 content 表达式可以具有任何数据类型。
例如:
SELECT xmlforest('abc' AS foo, 123 AS bar);
xmlforest
------------------------------
<foo>abc</foo><bar>123</bar>
SELECT xmlforest(table_name, column_name)
FROM information_schema.columns
WHERE table_schema = 'ux_catalog';
xmlforest
-----------------------------------------------------------------------
<table_name>ux_authid</table_name><column_name>rolname</column_name>
<table_name>ux_authid</table_name><column_name>rolsuper</column_name>
...
如第二个示例所示,如果内容值是列引用,则可以省略元素名称,在这种情况下,默认使用列名。否则,必须指定名称。
不是有效 XML 名称的元素名称将按示例所示进行转义。对于上面的 xmlelement,同样会转义内容数据以生成有效的 XML 内容,除非它已经是 xml 类型。
请注意,如果 XMLforests 由多个元素组成,则不是有效的 XML 文档,因此将 xmlforest 表达式包装在 xmlelement 中可能很有用。
16.1.5. xmlpi
xmlpi ( NAME name [, content ] ) → xml
xmlpi 表达式创建 XML 处理指令。与 xmlelement 一样,name 必须是简单标识符,而 content 表达式可以具有任何数据类型。如果存在 content,则不能包含字符序列 ?>。
示例:
SELECT xmlpi(name php, 'echo "hello world";');
xmlpi
-----------------------------
<?php echo "hello world";?>
16.1.6. xmlroot
xmlroot ( xml, VERSION {text|NO VALUE} [, STANDALONE {YES|NO|NO VALUE} ] ) → xml
xmlroot 表达式更改 XML 值的根节点的属性。如果指定了版本,则替换根节点的版本声明中的值;如果指定了独立设置,则替换根节点的独立声明中的值。
SELECT xmlroot(xmlparse(document '<?xml version="1.1"?><content>abc</content>'),
version '1.0', standalone yes);
xmlroot
----------------------------------------
<?xml version="1.0" standalone="yes"?>
<content>abc</content>
16.1.7. xmlagg
xmlagg ( xml ) → xml
xmlagg 函数是聚合函数,它将输入值连接到聚合函数调用中,类似于 xmlconcat,但连接发生在行之间而不是在单行表达式之间。有关聚合函数的更多信息,请参见聚合函数。
示例:
CREATE TABLE test (y int, x xml);
INSERT INTO test VALUES (1, '<foo>abc</foo>');
INSERT INTO test VALUES (2, '<bar/>');
SELECT xmlagg(x) FROM test;
xmlagg
----------------------
<foo>abc</foo><bar/>
示例:
SELECT xmlagg(x ORDER BY y DESC) FROM test;
xmlagg
----------------------
<bar/><foo>abc</foo>
以下非标准方法曾经推荐在以前的版本中使用,在特定情况下仍然有用:
SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab;
xmlagg
----------------------
<bar/><foo>abc</foo>
16.2. XML 谓词
本节中描述的表达式检查 xml 值的属性。
16.2.1. IS DOCUMENT
xml IS DOCUMENT → boolean
表达式 IS DOCUMENT 如果参数 XML 值是一个合法的 XML 文档,则返回 true,如果不是(即它是一个内容片段),则返回 false,如果参数为 null,则返回 null。
16.2.2. IS NOT DOCUMENT
xml IS NOT DOCUMENT → boolean
表达式 IS NOT DOCUMENT 如果参数 XML 值是一个合法的 XML 文档,则返回 false,如果不是(即它是一个内容片段),则返回 true,如果参数为 null,则返回 null。
16.2.3. XMLEXISTS
XMLEXISTS ( text PASSING [BY {REF|VALUE}] xml [BY {REF|VALUE}] ) → boolean
函数 xmlexists 使用传递的 XML 值作为上下文项,评估 XPath 1.0 表达式(第一个参数)。如果该评估的结果产生一个空节点集,则函数返回 false,如果产生任何其他值,则返回 true。如果任何参数为 null,则函数返回 null。作为上下文项传递的非 null 值必须是 XML 文档,而不是内容片段或任何非 XML 值。
例如:
SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY VALUE '<towns><town>Toronto</town><town>Ottawa</town></towns>');
xmlexists
------------
t
(1 row)
在 UXsinoDB 中,接受 BY REF 和 BY VALUE 子句,但会被忽略。
在 SQL 标准中,xmlexists 函数在 XML 查询语言中评估表达式,但是 UXsinoDB 仅允许使用 XPath 1.0 表达式。
16.2.3. xml_is_well_formed
xml_is_well_formed ( text ) → boolean
xml_is_well_formed_document ( text ) → boolean
xml_is_well_formed_content ( text ) → boolean
这些函数检查一个 text 字符串是否表示为格式良好的 XML,并返回布尔结果。xml_is_well_formed_document 检查格式良好的文档,而 xml_is_well_formed_content 检查格式良好的内容。如果 xmloption 配置参数设置为 DOCUMENT,则 xml_is_well_formed 执行前者,如果设置为 CONTENT,则执行后者。这意味着 xml_is_well_formed 对于查看简单类型 xml 的转换是否成功很有用,而其他两个函数对于查看相应的 XMLPARSE 变体是否成功很有用。
示例:
SET xmloption TO DOCUMENT;
SELECT xml_is_well_formed('<>');
xml_is_well_formed
--------------------
f
(1 row)
SELECT xml_is_well_formed('<abc/>');
xml_is_well_formed
--------------------
t
(1 row)
SET xmloption TO CONTENT;
SELECT xml_is_well_formed('abc');
xml_is_well_formed
--------------------
t
(1 row)
SELECT xml_is_well_formed_document('<ux:foo xmlns:ux="http://uxsinodb.org/stuff">bar</ux:foo>');
xml_is_well_formed_document
-----------------------------
t
(1 row)
SELECT xml_is_well_formed_document('<ux:foo xmlns:ux="http://uxsinodb.org/stuff">bar</my:foo>');
xml_is_well_formed_document
-----------------------------
f
(1 row)
最后一个示例显示检查包括名称空间是否正确匹配。
16.3. 处理 XML
要处理 xml 数据类型的值,UXsinoDB 提供了 xpath 和 xpath_exists 函数,这些函数评估 XPath 1.0 表达式,以及 XMLTABLE 表函数。
16.3.1. xpath
xpath ( xpath text, xml xml [, nsarray text[] ] ) → xml[]
函数 xpath 评估 XPath 1.0 表达式 xpath(以文本形式给出)对 XML 值 xml 进行计算。它返回一个 XML 值数组。对应于 XPath 表达式生成的节点集。如果 XPath 表达式返回标量值而不是节点集,则返回单元素数组。
第二个参数必须是格式良好的 XML 文档。特别地,它必须有一个单一的根节点元素。
函数的可选第三个参数是一个命名空间映射数组。这个数组应该是一个二维的文本数组,第二个轴的长度应该等于 2(即,它应该是一个数组的数组,每个数组都恰好由 2 个元素组成)。每个数组条目的第一个元素是命名空间名称(别名),第二个元素是命名空间 URI。不要求在这个数组中提供的别名与 XML 文档本身中使用的别名相同(换句话说,在 XML 文档和 xpath 函数上下文中,别名是本地的)。
例如:
SELECT xpath('/my:a/text()', '<my:a xmlns:my="http://example.com">test</my:a>',
ARRAY[ARRAY['my', 'http://example.com']]);
xpath
--------
{test}
(1 row)
要处理默认(匿名)命名空间,可以这样做:
SELECT xpath('//mydefns:b/text()', '<a xmlns="http://example.com"><b>test</b></a>',
ARRAY[ARRAY['mydefns', 'http://example.com']]);
xpath
--------
{test}
(1 row)
16.3.2. xpath_exists
xpath_exists ( xpath text, xml xml [, nsarray text[] ] ) → boolean
xpath_exists 是 xpath 函数的一种特殊形式。它不返回满足 XPath 1.0 表达式的单个 XML 值,而是返回一个布尔值,指示查询是否满足或不满足(具体而言,它是否产生了除空节点集之外的任何值)。此函数等效于 XMLEXISTS 谓词,但它还提供了对命名空间映射参数的支持。
例如:
SELECT xpath_exists('/my:a/text()', '<my:a xmlns:my="http://example.com">test</my:a>',
ARRAY[ARRAY['my', 'http://example.com']]);
xpath_exists
--------------
t
(1 row)
16.3.3. xmltable
XMLTABLE (
[ XMLNAMESPACES ( namespace_uri AS namespace_name [, ...] ), ]
row_expression PASSING [BY {REF|VALUE}] document_expression [BY {REF|VALUE}]
COLUMNS name { type [PATH column_expression] [DEFAULT default_expression] [NOT NULL | NULL]
| FOR ORDINALITY }
[, ...]
) → setof record
xmltable 表达式基于 XML 值、XPath 过滤器提取行和一组列定义生成表格。虽然它在语法上类似于函数,但它只能出现在查询的 FROM 子句中作为表格。
可选的 XMLNAMESPACES 子句给出了一个逗号分隔的命名空间定义列表,其中每个 namespace_uri 是一个 text 表达式,每个 namespace_name 是一个简单的标识符。它指定了文档中使用的 XML 命名空间及其别名。当前不支持默认命名空间规范。
必需的 row_expression 参数是一个 XPath 1.0 表达式(以 text 形式给出),它在将 XML 值 document_expression 作为上下文项进行评估时,获取一组 XML 节点。这些节点是 xmltable 转换为输出行的内容。如果 document_expression 为空或 row_expression 产生空节点集或任何值而不是节点集,则不会产生行。
document_expression 为 row_expression 提供上下文项。它必须是一个格式良好的 XML 文档;不接受片段/森林。BY REF 和 BY VALUE 子句被接受但被忽略。
在 SQL 标准中,xmltable 函数在 XML 查询语言中评估表达式,但 UXsinoDB 仅允许 XPath 1.0 表达式。
必需的 COLUMNS 子句指定将在输出表中生成的列。有关格式,请参见上面的语法摘要。每个列都需要一个名称,以及一个数据类型(除非指定了 FOR ORDINALITY,在这种情况下,类型 integer 是隐含的)。路径、默认值和可空性子句是可选的。
标记为 FOR ORDINALITY 的列将以从 row_expression 的结果节点集检索的节点的顺序填充行号,从 1 开始。最多只能标记一个列为 FOR ORDINALITY。
注意
XPath 1.0 不为节点集中的节点指定顺序,因此依赖特定结果顺序的代码将依赖于实现。
列的 column_expression 是一个 XPath 1.0 表达式,对于每一行进行评估,将 row_expression 结果的当前节点作为上下文项,以找到列的值。如果没有给出 column_expression,则列名将用作隐式路径。
如果列的 XPath 表达式返回非 XML 值(在 XPath 1.0 中仅限于字符串、布尔或双精度),并且列具有除 xml 之外的 UXsinoDB 类型,则该列将被设置为将该值的字符串表示分配给 UXsinoDB 类型。(如果该值是布尔值,则其字符串表示被视为 1 或 0,如果输出列的类型类别是数值,则为 true 或 false。)
如果列的 XPath 表达式返回非空的 XML 节点集,并且列的 UXsinoDB 类型为 xml,则如果表达式结果为文档或内容形式,则将分配该列的表达式结果。
将非 XML 结果分配给 xml 输出列会产生内容,即具有结果字符串值的单个文本节点。分配给其他任何类型列的 XML 结果可能不超过一个节点,否则将引发错误。如果恰好有一个节点,则将该列设置为将节点的字符串值(如 XPath 1.0 string 函数定义的)分配给 UXsinoDB 类型。
XML 元素的字符串值是按文档顺序连接该元素及其后代中包含的所有文本节点。没有后代文本节点的元素的字符串值为空字符串(而不是 NULL)。任何 xsi:nil 属性都将被忽略。请注意,两个非文本元素之间的仅空格 text() 节点将被保留,并且 text() 节点上的前导空格不会被压平。XPath 1.0 string 函数可以用于查询定义其他 XML 节点类型和非 XML 值的字符串值的规则。
这里介绍的转换规则与 SQL 标准不完全相同。
如果路径表达式对于给定行返回空节点集(通常是因为它不匹配),则该列将设置为 NULL,除非指定了 default_expression;然后使用从评估该表达式得出的值。
default_expression 不是在调用 xmltable 时立即评估,而是每次需要列的默认值时评估。如果表达式符合稳定或不可变条件,则可以跳过重复评估。这意味着您可以有用地使用像 nextval 这样的易失性函数在 default_expression 中。
列可以标记为 NOT NULL。如果 NOT NULL 列的 column_expression 没有匹配任何内容,并且没有 DEFAULT 或 default_expression 的评估结果也为空,则报告错误。
例如:
CREATE TABLE xmldata AS SELECT
xml $$
<ROWS>
<ROW id="1">
<COUNTRY_ID>AU</COUNTRY_ID>
<COUNTRY_NAME>Australia</COUNTRY_NAME>
</ROW>
<ROW id="5">
<COUNTRY_ID>JP</COUNTRY_ID>
<COUNTRY_NAME>Japan</COUNTRY_NAME>
<PREMIER_NAME>Shinzo Abe</PREMIER_NAME>
<SIZE unit="sq_mi">145935</SIZE>
</ROW>
<ROW id="6">
<COUNTRY_ID>SG</COUNTRY_ID>
<COUNTRY_NAME>Singapore</COUNTRY_NAME>
<SIZE unit="sq_km">697</SIZE>
</ROW>
</ROWS>
$$ AS data;
SELECT xmltable.*
FROM xmldata,
XMLTABLE('//ROWS/ROW'
PASSING data
COLUMNS id int PATH '@id',
ordinality FOR ORDINALITY,
"COUNTRY_NAME" text,
country_id text PATH 'COUNTRY_ID',
size_sq_km float PATH 'SIZE[@unit = "sq_km"]',
size_other text PATH
'concat(SIZE[@unit!="sq_km"], " ", SIZE[@unit!="sq_km"]/@unit)',
premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified');
id | ordinality | COUNTRY_NAME | country_id | size_sq_km | size_other | premier_name
----+------------+--------------+------------+------------+--------------+---------------
1 | 1 | Australia | AU | | | not specified
5 | 2 | Japan | JP | | 145935 sq_mi | Shinzo Abe
6 | 3 | Singapore | SG | 697 | | not specified
以下示例显示了多个 text() 节点的连接,使用列名作为 XPath 过滤器以及处理空格,XML 注释和处理指令:
CREATE TABLE xmlelements AS SELECT
xml $$
<root>
<element> Hello<!-- xyxxz -->2a2<?aaaaa?> <!--x--> bbb<x>xxx</x>CC </element>
</root>
$$ AS data;
SELECT xmltable.*
FROM xmlelements, XMLTABLE('/root' PASSING data COLUMNS element text);
element
-------------------------
Hello2a2 bbbxxxCC
以下示例说明了如何使用 XMLNAMESPACES 子句指定 XML 文档中使用的命名空间列表以及 XPath 表达式中使用的命名空间:
WITH xmldata(data) AS (VALUES ('
<example xmlns="http://example.com/myns" xmlns:B="http://example.com/b">
<item foo="1" B:bar="2"/>
<item foo="3" B:bar="4"/>
<item foo="4" B:bar="5"/>
</example>'::xml)
)
SELECT xmltable.*
FROM XMLTABLE(XMLNAMESPACES('http://example.com/myns' AS x,
'http://example.com/b' AS "B"),
'/x:example/x:item'
PASSING (SELECT data FROM xmldata)
COLUMNS foo int PATH '@foo',
bar int PATH '@B:bar');
foo | bar
-----+-----
1 | 2
3 | 4
4 | 5
(3 rows)
16.4. 将表映射到 XML
以下函数将关系表的内容映射到 XML 值。它们可以被视为 XML 导出功能:
table_to_xml ( table regclass, nulls boolean,
tableforest boolean, targetns text ) → xml
query_to_xml ( query text, nulls boolean,
tableforest boolean, targetns text ) → xml
cursor_to_xml ( cursor refcursor, count integer, nulls boolean,
tableforest boolean, targetns text ) → xml
table_to_xml 将作为参数 table 传递的命名表的内容映射。regclass 类型接受使用通常的表示法标识表的字符串,包括可选的模式限定和双引号。query_to_xml 执行作为参数 query 传递的文本的查询并映射结果集。cursor_to_xml 从由参数 cursor 指定的游标中获取指定数量的行。如果需要映射大型表,则建议使用此变体,因为每个函数都在内存中构建结果值。
如果 tableforest 为 false,则生成的 XML 文档如下所示:
<tablename>
<row>
<columnname1>data</columnname1>
<columnname2>data</columnname2>
</row>
<row>
...
</row>
...
</tablename>
如果 tableforest 为 true,则结果是一个 XML 内容片段,如下所示:
<tablename>
<columnname1>data</columnname1>
<columnname2>data</columnname2>
</tablename>
<tablename>
...
</tablename>
...
如果没有表名可用,即在映射查询或游标时,则在第一种格式中使用字符串 table,在第二种格式中使用字符串 row。
这些格式之间的选择取决于用户。第一种格式是一个正确的 XML 文档,在许多应用程序中将非常重要。第二种格式在 cursor_to_xml 函数中更有用,如果结果值稍后需要重新组合为一个文档。上面讨论的用于生成 XML 内容的函数,特别是 xmlelement,可以用于根据需要修改结果。
数据值的映射方式与上面描述的函数 xmlelement 相同。
参数 nulls 确定是否应在输出中包括空值。如果为 true,则列中的空值表示为:
<columnname xsi:nil="true"/>
其中 xsi 是 XML Schema Instance 的 XML 命名空间前缀。适当的命名空间声明将添加到结果值中。如果为 false,则包含空值的列将从输出中简单地省略。
参数 targetns 指定结果的所需 XML 命名空间。如果不需要特定的命名空间,则应传递一个空字符串。
下面的函数返回 XML Schema 文档,描述由上面的相应函数执行的映射:
table_to_xmlschema ( table regclass, nulls boolean,
tableforest boolean, targetns text ) → xml
query_to_xmlschema ( query text, nulls boolean,
tableforest boolean, targetns text ) → xml
cursor_to_xmlschema ( cursor refcursor, nulls boolean,
tableforest boolean, targetns text ) → xml
为了获得匹配的 XML 数据映射和 XML Schema 文档,必须传递相同的参数。
以下函数在一个文档(或森林)中生成 XML 数据映射和相应的 XML Schema,并将它们链接在一起。它们可以在需要自包含和自描述结果时很有用:
table_to_xml_and_xmlschema ( table regclass, nulls boolean,
tableforest boolean, targetns text ) → xml
query_to_xml_and_xmlschema ( query text, nulls boolean,
tableforest boolean, targetns text ) → xml
此外,还提供以下函数来生成整个模式或整个当前数据库的类似映射:
schema_to_xml ( schema name, nulls boolean,
tableforest boolean, targetns text ) → xml
schema_to_xmlschema ( schema name, nulls boolean,
tableforest boolean, targetns text ) → xml
schema_to_xml_and_xmlschema ( schema name, nulls boolean,
tableforest boolean, targetns text ) → xml
database_to_xml ( nulls boolean,
tableforest boolean, targetns text ) → xml
database_to_xmlschema ( nulls boolean,
tableforest boolean, targetns text ) → xml
database_to_xml_and_xmlschema ( nulls boolean,
tableforest boolean, targetns text ) → xml
这些函数会忽略当前用户无法读取的表。数据库范围的函数还会忽略当前用户没有 USAGE(查找)权限的模式。
请注意,这些函数可能会产生大量数据,需要在内存中构建。当请求大型模式或数据库的内容映射时,可能值得考虑单独映射表,甚至通过游标进行映射。
模式内容映射的结果如下所示:
<schemaname>
table1-mapping
table2-mapping
...
</schemaname>
其中表映射的格式取决于上面解释的 tableforest 参数。
数据库内容映射的结果如下所示:
<dbname>
<schema1name>
...
</schema1name>
<schema2name>
...
</schema2name>
...
</dbname>
其中模式映射如上所述。
使用这些函数生成的输出的示例,在示例 将 SQL/XML 输出转换为 md 的 XSLT 样式表中展示了一个 XSLT 样式表,将 table_to_xml_and_xmlschema 的输出转换为包含表数据表格呈现的 md 文档。以类似的方式,这些函数的结果可以转换为其他基于 XML 的格式。
示例 将 SQL/XML 输出转换为 md 的 XSLT 样式表
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.w3.org/1999/xhtml"
>
<xsl:output method="xml"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
doctype-public="-//W3C/DTD XHTML 1.0 Strict//EN"
indent="yes"/>
<xsl:template match="/*">
<xsl:variable name="schema" select="//xsd:schema"/>
<xsl:variable name="tabletypename"
select="$schema/xsd:element[@name=name(current())]/@type"/>
<xsl:variable name="rowtypename"
select="$schema/xsd:complexType[@name=$tabletypename]/xsd:sequence/xsd:element[@name='row']/@type"/>
<html>
<head>
<title><xsl:value-of select="name(current())"/></title>
</head>
<body>
<table>
<tr>
<xsl:for-each select="$schema/xsd:complexType[@name=$rowtypename]/xsd:sequence/xsd:element/@name">
<th><xsl:value-of select="."/></th>
</xsl:for-each>
</tr>
<xsl:for-each select="row">
<tr>
<xsl:for-each select="*">
<td><xsl:value-of select="."/></td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
顶层包含多个元素节点或元素外的非空白文本的结果是内容形式的一个示例。XPath 结果既不能是这种形式,例如如果它返回从包含它的元素中选择的属性节点。这样的结果将被放入内容形式,其中每个不允许的节点都将被其字符串值所替换,如 XPath 1.0 的 string 函数所定义。
17. JSON 函数和操作符
本节介绍:
- 处理和创建 JSON 数据的函数和操作符
- SQL/JSON 路径语言
17.1. 处理和创建 JSON 数据
表 json 和 jsonb 操作符显示可用于 JSON 数据类型的操作符。此外,通常在表 比较操作符中显示的比较操作符可用于 jsonb,但不适用于 json。比较操作符遵循 B 树操作的排序规则。聚合函数 json_agg,它将记录值作为 JSON 聚合,聚合函数 json_object_agg,它将值对聚合成 JSON 对象,以及它们的 jsonb 等效项,jsonb_agg 和 jsonb_object_agg。
| 操作符 | 描述 | 示例 |
|---|---|---|
json -> integer → jsonjsonb -> integer → jsonb | 提取 JSON 数组的第 n 个元素(数组元素从零开始索引,但负整数从末尾开始计数)。 | '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json -> 2 → {"c":"baz"}'[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json -> -3 → {"a":"foo"} |
json -> text → jsonjsonb -> text → jsonb | 提取具有给定键的 JSON 对象字段。 | '{"a": {"b":"foo"}}'::json -> 'a' → {"b":"foo"} |
json ->> integer → textjsonb ->> integer → text | 提取 JSON 数组的第 n 个元素,作为 text。 | '[1,2,3]'::json ->> 2 → 3 |
json ->> text → textjsonb ->> text → text | 提取具有给定键的 JSON 对象字段,作为 text。 | '{"a":1,"b":2}'::json ->> 'b' → 2 |
json #> text[] → jsonjsonb #> text[] → jsonb | 提取指定路径处的 JSON 子对象,其中路径元素可以是字段键或数组索引。 | '{"a": {"b": ["foo","bar"]}}'::json #> '{a,b,1}' → "bar" |
json #>> text[] → textjsonb #>> text[] → text | 提取指定路径下的 JSON 子对象作为 text。 | '{"a": {"b": ["foo","bar"]}}'::json #>> '{a,b,1}' → bar |
注意
字段/元素/路径提取操作符返回 NULL,而不是失败,如果 JSON 输入没有正确的结构来匹配请求;例如,如果不存在这样的键或数组元素。
还有一些仅适用于 jsonb 的操作符,如表 附加的 jsonb 操作符所示。
表 附加的 jsonb 操作符
| 操作符 | 描述 | 示例 |
|---|---|---|
jsonb @> jsonb → boolean | 第一个 JSON 值是否包含第二个 JSON 值? | '{"a":1, "b":2}'::jsonb @> '{"b":2}'::jsonb → t |
jsonb <@ jsonb → boolean | 第一个 JSON 值是否包含在第二个 JSON 值中? | '{"b":2}'::jsonb <@ '{"a":1, "b":2}'::jsonb → t |
jsonb ? text → boolean | 文本字符串是否作为顶级键或数组元素存在于 JSON 值中? | '{"a":1, "b":2}'::jsonb ? 'b' → t'["a", "b", "c"]'::jsonb ? 'b' → t |
jsonb ?| text[] → boolean | 文本数组中的任何字符串是否作为顶级键或数组元素存在? | '{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'd'] → t |
jsonb ?& text[] → boolean | 文本数组中的所有字符串是否作为顶级键或数组元素存在? | '["a", "b", "c"]'::jsonb ?& array['a', 'b'] → t |
jsonb || jsonb → jsonb | 连接两个 jsonb 值。连接两个数组生成包含所有元素的数组。每个输入的元素。连接两个对象会生成一个包含它们键的并集的对象,当有重复键时,取第二个对象的值。所有其他情况都通过将非数组输入转换为单元素数组,然后像处理两个数组一样继续处理。不递归操作:仅合并顶层数组或对象结构。 | '["a", "b"]'::jsonb || '["a", "d"]'::jsonb → ["a", "b", "a", "d"]'{"a": "b"}'::jsonb || '{"c": "d"}'::jsonb → {"a": "b", "c": "d"}'[1, 2]'::jsonb || '3'::jsonb → [1, 2, 3]'{"a": "b"}'::jsonb || '42'::jsonb → [{"a": "b"}, 42]要将数组附加到另一个数组作为单个条目,请将其包装在另一层数组中,例如: '[1, 2]'::jsonb || jsonb_build_array('[3, 4]'::jsonb) → [1, 2, [3, 4]] |
jsonb - text → jsonb | 从 JSON 对象中删除键(及其值),或从 JSON 数组中删除匹配的字符串值。 | '{"a": "b", "c": "d"}'::jsonb - 'a' → {"c": "d"}'["a", "b", "c", "b"]'::jsonb - 'b' → ["a", "c"] |
jsonb - text[] → jsonb | 从左操作数中删除所有匹配的键或数组元素。 | '{"a": "b", "c": "d"}'::jsonb - '{a,c}'::text[] → {} |
jsonb - integer → jsonb | 删除具有指定索引的数组元素(负整数从末尾计数)。如果 JSON 值不是数组,则抛出错误。 | '["a", "b"]'::jsonb - 1 → ["a"] |
jsonb #- text[] → jsonb | 删除指定路径处的字段或数组元素,其中路径元素可以是字段键或数组索引。 | '["a", {"b":1}]'::jsonb #- '{1,b}' → ["a", {}] |
jsonb @? jsonpath → boolean | JSON 路径是否为指定的 JSON 值返回任何项? | '{"a":[1,2,3,4,5]}'::jsonb @? '$.a[*] ? (@ > 2)' → t |
jsonb @@ jsonpath → boolean | 返回指定 JSON 值的 JSON 路径谓词检查的结果。仅考虑结果的第一项。如果结果不是布尔值,则返回 NULL。 | '{"a":[1,2,3,4,5]}'::jsonb @@ '$.a[*] > 2' → t |
注意
@?和@@是jsonpath操作符,可以抑制以下错误:缺少对象字段或数组元素、意外的 JSON 项类型、日期时间和数字错误。下面描述的与jsonpath相关的函数也可以被告知抑制这些类型的错误。当搜索具有不同结构的 JSON 文档集合时,这种行为可能是有帮助的。
表 JSON 创建函数显示了可用于构建 json 和 jsonb 值的函数。
| 函数 | 描述 | 示例 |
|---|---|---|
to_json ( anyelement ) → jsonto_jsonb ( anyelement ) → jsonb | 将任何 SQL 值转换为 json 或 jsonb。数组和复合类型递归地转换为数组和对象(多维数组在 JSON 中成为数组的数组)。否则,如果从 SQL 数据类型到 json 的转换,则使用转换函数执行转换;否则,将生成标量 JSON 值。对于除数字、布尔值或空值之外的任何标量,将使用文本表示形式,并进行必要的转义,以使其成为有效的 JSON 字符串值。 | to_json('Fred said "Hi."'::text) → "Fred said \"Hi.\""to_jsonb(row(42, 'Fred said "Hi."'::text)) → {"f1": 42, "f2": "Fred said \"Hi.\""} |
array_to_json ( anyarray [ , boolean ] ) → json | 将 SQL 数组转换为 JSON 数组。行为与 to_json 相同,只是如果可选布尔参数为 true,则在顶级数组元素之间添加换行符。 | array_to_json('{{1,5},{99,100}}'::int[]) → [[1,5],[99,100]] |
row_to_json ( record [ , boolean ] ) → json | 将 SQL 复合值转换为 JSON 对象。行为与 to_json 相同,只是如果可选布尔参数为 true,则在顶级元素之间添加换行符。 | row_to_json(row(1,'foo')) → {"f1":1,"f2":"foo"} |
json_build_array ( VARIADIC "any" ) → jsonjsonb_build_array ( VARIADIC "any" ) → jsonb | 从可变参数列表中构建可能具有异构类型的 JSON 数组。每个参数都会按照 to_json 或 to_jsonb 进行转换。 | json_build_array(1, 2, 'foo', 4, 5) → [1, 2, "foo", 4, 5] |
json_build_object ( VARIADIC "any" ) → jsonjsonb_build_object ( VARIADIC "any" ) → jsonb | 从可变参数列表中构建 JSON 对象。按照惯例,参数列表由交替的键和值组成。键参数被强制转换为文本;值参数按照 to_json 或 to_jsonb 进行转换。 | json_build_object('foo', 1, 2, row(3,'bar')) → {"foo" : 1, "2" : {"f1":3,"f2":"bar"}} |
json_object ( text[] ) → jsonjsonb_object ( text[] ) → jsonb | 从文本数组中构建 JSON 对象。该数组必须具有恰好一个维度,其成员数为偶数,这些成员被视为交替的键/值对;或者具有两个维度,每个内部数组恰好有两个元素,这些元素被视为键/值对。所有值都被转换为 JSON 字符串。 | json_object('{a, 1, b, "def", c, 3.5}') → {"a" : "1", "b" : "def", "c" : "3.5"}json_object('{{a, 1}, {b, "def"}, {c, 3.5}}') → {"a" : "1", "b" : "def", "c" : "3.5"} |
json_object ( keys text[], values text[] ) → jsonjsonb_object ( keys text[], values text[] ) → jsonb | 这种形式的 json_object 从单独的文本数组中逐对地获取键和值。否则,它与单参数形式相同。 | json_object('{a,b}', '{1,2}') → {"a": "1", "b": "2"} |
[a] 例如,hstore 扩展有一个从
hstore到json的转换,因此通过 JSON 创建函数转换的hstore值将被表示为 JSON 对象,而不是原始字符串值。
表 JSON 处理函数显示了可用于处理 json 和 jsonb 值的函数。
| 函数 | 描述 | 示例 |
|---|---|---|
json_array_elements ( json ) → setof jsonjsonb_array_elements ( jsonb ) → setof jsonb | 将顶层 JSON 数组扩展为一组 JSON 值。 | select * from json_array_elements('[1,true, [2,false]]') → value-----------1true[2,false] |
json_array_elements_text ( json ) → setof textjsonb_array_elements_text ( jsonb ) → setof text | 将顶层 JSON 数组扩展为一组 text 值。 | select * from json_array_elements_text('["foo", "bar"]') → value-----------foobar |
json_array_length ( json ) → integerjsonb_array_length ( jsonb ) → integer | 返回顶层 JSON 数组中的元素数量。 | json_array_length('[1,2,3,{"f1":1,"f2":[5,6]},4]') → 5jsonb_array_length('[]') → 0 |
json_each ( json ) → setof record ( key text, value json )jsonb_each ( jsonb ) → setof record ( key text, value jsonb ) | 将顶层 JSON 对象扩展为键/值对集合。 | select * from json_each('{"a":"foo", "b":"bar"}') → key | value-----+-------a | "foo"b | "bar" |
json_each_text ( json ) → setof record ( key text, value text )jsonb_each_text ( jsonb ) → setof record ( key text, value text ) | 将顶层 JSON 对象扩展为键/值对集合。返回的 value 将是 text 类型。 | select * from json_each_text('{"a":"foo", "b":"bar"}') → key | value-----+-------a | foob | bar |
json_extract_path ( from_json json, VARIADIC path_elems text[] ) → jsonjsonb_extract_path ( from_json jsonb, VARIADIC path_elems text[] ) → jsonb | 提取指定路径下的 JSON 子对象。(这在功能上等同于 #> 操作符,但将路径写成可变参数列表在某些情况下更方便。) | json_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}', 'f4', 'f6') → "foo" |
json_extract_path_text ( from_json json, VARIADIC path_elems text[] ) → textjsonb_extract_path_text ( from_json jsonb, VARIADIC path_elems text[] ) → text | 将指定路径下的 JSON 子对象提取为 text。(这在功能上等同于 #>> 操作符。) | json_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}', 'f4', 'f6') → foo |
json_object_keys ( json ) → setof textjsonb_object_keys ( jsonb ) → setof text | 返回顶层 JSON 对象的键集合。 | select * from json_object_keys('{"f1":"abc","f2":{"f3":"a", "f4":"b"}}') → json_object_keys------------------f1f2 |
json_populate_record ( base anyelement, from_json json ) → anyelementjsonb_populate_record ( base anyelement, from_json jsonb ) → anyelement | 将顶层 JSON 对象扩展为具有 base 参数的复合类型的行。扫描 JSON 对象以查找与输出行类型的列名匹配的字段,并将它们的值插入到输出的列中。(不对应任何输出列名的字段进行处理。)在典型用法中,base 的值只是 NULL,这意味着任何不匹配任何对象字段的输出列将填充为 null。但是,如果 base 不是 NULL,则将使用其包含的值来填充不匹配的列。 | create type subrowtype as (d int, e text); create type myrowtype as (a int, b text[], c subrowtype);select * from json_populate_record(null::myrowtype, '{"a": 1, "b": ["2", "a b"], "c": {"d": 4, "e": "a b c"}, "x": "foo"}') → a | b | c---+-----------+-------------1 | {2,"a b"} | (4,"a b c") |
json_populate_recordset ( base anyelement, from_json json ) → setof anyelementjsonb_populate_recordset ( base anyelement, from_json jsonb ) → setof anyelement | 将顶层的 JSON 对象数组扩展为具有 base 参数的复合类型的行集。JSON 数组的每个元素都按照上面描述的 json[b]_populate_record 的方式进行处理。 | create type twoints as (a int, b int);select * from json_populate_recordset(null::twoints, '[{"a":1,"b":2}, {"a":3,"b":4}]') → a | b---+---1 | 23 | 4 |
json_to_record ( json ) → recordjsonb_to_record ( json ) → record | 将顶层的 JSON 对象扩展为具有 AS 子句定义的复合类型的行。(与返回 record 的所有函数一样,调用查询必须明确使用 AS 子句定义记录的结构。)输出记录从 JSON 对象的字段中填充,方式与上面描述的 json[b]_populate_record 相同。由于没有输入记录值,因此未匹配的列始终填充为 null。 | create type myrowtype as (a int, b text);select * from json_to_record('{"a":1,"b":[1,2,3],"c":[1,2,3],"e":"bar","r": {"a": 123, "b": "a b c"}}') as x(a int, b text, c int[], d text, r myrowtype) → a | b | c | d | r---+---------+---------+---+---------------1 | [1,2,3] | {1,2,3} | | (123,"a b c") |
json_to_recordset ( json ) → setof recordjsonb_to_recordset ( json ) → setof record | 将顶层的 JSON 对象数组扩展为具有记录类型的行集。由 AS 子句定义的复合类型。(与返回 record 的所有函数一样,调用查询必须使用 AS 子句显式定义记录的结构。)JSON 数组的每个元素都会按上述描述进行处理,以进行 json[b]_populate_record。 | select * from json_to_recordset('[{"a":1,"b":"foo"}, {"a":"2","c":"bar"}]') as x(a int, b text) → a | b---+-----1 | foo2 | |
jsonb_set ( target jsonb, path text[], new_value jsonb [, create_if_missing boolean ] ) → jsonb | 返回 target,其中由 path 指定的项被替换为 new_value,如果 create_if_missing 为 true(默认值),则添加 new_value,并且由 path 指定的项不存在。路径中的所有较早步骤必须存在,否则将返回未更改的 target。与路径导向操作符一样,出现在 path 中的负整数从 JSON 数组的末尾开始计数。如果最后一个路径步骤是超出范围的数组索引,并且 create_if_missing 为 true,则如果索引为负,则在数组开头添加新值,如果为正,则在数组末尾添加新值。 | jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0,f1}', '[2,3,4]', false) → [{"f1": [2, 3, 4], "f2": null}, 2, null, 3]jsonb_set('[{"f1":1,"f2":null},2]', '{0,f3}', '[2,3,4]') → [{"f1": 1, "f2": null, "f3": [2, 3, 4]}, 2] |
jsonb_set_lax ( target jsonb, path text[], new_value jsonb [, create_if_missing boolean [, null_value_treatment text ] ] ) → jsonb | 如果 new_value 不是 NULL,则与 jsonb_set 完全相同。否则,根据 null_value_treatment 的值进行操作,该值必须是 'raise_exception'、'use_json_null'、'delete_key' 或 'return_target' 之一。默认值为 'use_json_null'。 | jsonb_set_lax('[{"f1":1,"f2":null},2,null,3]', '{0,f1}', null) → [{"f1": null, "f2": null}, 2, null, 3]jsonb_set_lax('[{"f1":99,"f2":null},2]', '{0,f3}', null, true, 'return_target') → [{"f1": 99, "f2": null}, 2] |
jsonb_insert ( target jsonb, path text[], new_value jsonb [, insert_after boolean ] ) → jsonb | 返回插入了 new_value 的 target。如果 path 指定的项是数组元素,则如果 insert_after 为 false(默认值),则在该项之前插入 new_value,否则在该项之后插入 new_value。如果 path 指定的项是对象字段,则仅在对象不包含该键时插入 new_value。路径中的所有较早步骤必须存在,否则将返回 target。与路径导向操作符一样,出现在 path 中的负整数从 JSON 数组的末尾开始计数。如果最后一个路径步骤是超出范围的数组索引,则如果索引为负,则在数组开头添加新值,如果为正,则在数组末尾添加新值。 | jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"') → {"a": [0, "new_value", 1, 2]}jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"', true) → {"a": [0, 1, "new_value", 2]} |
json_strip_nulls ( json ) → jsonjsonb_strip_nulls ( jsonb ) → jsonb | 递归删除给定 JSON 值中所有具有 null 值的对象字段。不会更改不是对象字段的 null 值。 | json_strip_nulls('[{"f1":1, "f2":null}, 2, null, 3]') → [{"f1":1},2,null,3] |
jsonb_path_exists ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ] ] ) → boolean | 检查指定的 JSON 值是否返回任何项。如果指定了 vars 参数,则它必须是 JSON 对象,其字段提供要替换为 jsonpath 表达式中的命名值。如果指定了 silent 参数并且为 true,则函数会抑制相同的错误。与 @? 和 @@ 操作符一样。 | jsonb_path_exists('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}') → t |
jsonb_path_match ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ] ] ) → boolean | 返回指定 JSON 值的 JSON 路径谓词检查结果。仅考虑结果的第一个项。如果结果不是布尔值,则返回 NULL。可选的 vars 和 silent 参数与 jsonb_path_exists 的作用相同。 | jsonb_path_match('{"a":[1,2,3,4,5]}', 'exists($.a[*] ? (@ >= $min && @ <= $max))', '{"min":2, "max":4}') → t |
jsonb_path_query ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ] ] ) → setof jsonb | 返回指定 JSON 值的 JSON 路径返回的所有 JSON 项。可选的 vars 和 silent 参数与 jsonb_path_exists 的作用相同。 | select * from jsonb_path_query('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}') → jsonb_path_query------------------234 |
jsonb_path_query_array ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ] ] ) → jsonb | 返回指定 JSON 值的 JSON 路径返回的所有 JSON 项,作为 JSON 数组。可选的 vars 和 silent 参数与 jsonb_path_exists 的作用相同。 | jsonb_path_query_array('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}') → [2, 3, 4] |
jsonb_path_query_first ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ] ] ) → jsonb | 返回指定 JSON 值的 JSON 路径返回的第一个 JSON 项。如果没有结果,则返回 NULL。可选的 vars 和 silent 参数与 jsonb_path_exists 相同。 | jsonb_path_query_first('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}') → 2 |
jsonb_path_exists_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ] ] ) → booleanjsonb_path_match_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ] ] ) → booleanjsonb_path_query_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ] ] ) → setof jsonbjsonb_path_query_array_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ] ] ) → jsonbjsonb_path_query_first_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ] ] ) → jsonb | 这些函数的作用与上述函数相同,只是增加了时区支持。_tz 后缀,这些函数支持需要时区感知转换的日期/时间值的比较。下面的示例需要将仅日期值 2015-08-02 解释为带有时区的时间戳,因此结果取决于当前的 TimeZone 设置。由于这种依赖关系,这些函数被标记为稳定的,这意味着这些函数不能用于索引。它们的对应函数是不可变的,因此可以用于索引;但是如果要求进行此类比较,它们将抛出错误。 | jsonb_path_exists_tz('["2015-08-01 12:00:00-05"]', '$[*] ? (@.datetime() < "2015-08-02".datetime())') → t |
jsonb_pretty ( jsonb ) → text | 将给定的 JSON 值转换为漂亮的、缩进的文本。 | jsonb_pretty('[{"f1":1,"f2":null}, 2]') → [{"f1": 1,"f2": null},2] |
json_typeof ( json ) → textjsonb_typeof ( jsonb ) → text | 返回顶层 JSON 值的类型作为文本字符串。可能的类型有 object、array、string、number、boolean 和 null。(不应将 null 结果与 SQL NULL 混淆;请参见示例。) | json_typeof('-123.4') → numberjson_typeof('null'::json) → nulljson_typeof(NULL::json) IS NULL → t |
17.2. SQL/JSON 路径语言
SQL/JSON 路径表达式指定要从 JSON 数据中检索的项,类似于用于 SQL 访问 XML 的 XPath 表达式。在 UXsinoDB 中,路径表达式作为 jsonpath 数据类型实现。
JSON 查询函数和操作符将提供的路径表达式传递给路径引擎进行评估。如果表达式与查询的 JSON 数据匹配,则返回相应的 JSON 项或一组项。路径表达式以 SQL/JSON 路径语言编写,并且可以包括算术表达式和函数。
路径表达式由 jsonpath 数据类型允许的一系列元素组成。路径表达式通常从左到右进行评估,但是您可以使用括号更改操作顺序。如果评估成功,则会生成一系列 JSON 项,并将评估结果返回到完成指定计算的 JSON 查询函数。
要引用正在查询的 JSON 值(上下文项),请在路径表达式中使用 $ 变量。它后面可以跟随一个或多个访问器操作符,这些操作符在 JSON 结构级别上逐级下降,以检索上下文项的子项。后面的每个操作符处理前一个计算步骤的结果。
例如,假设您有一些来自 GPS 跟踪器的 JSON 数据,希望对其进行解析,例如:
{
"track": {
"segments": [
{
"location": [ 47.763, 13.4034 ],
"start time": "2018-10-14 10:05:14",
"HR": 73
},
{
"location": [ 47.706, 13.2635 ],
"start time": "2018-10-14 10:39:21",
"HR": 135
}
]
}
}
要检索可用的轨迹段,需要使用 .key 访问器操作符来遍历周围 JSON 对象:
$.track.segments
要检索数组的内容,通常使用 [*] 操作符。例如,以下路径将返回所有可用轨迹段的位置坐标:
$.track.segments[*].location
要仅返回第一个段的坐标,可以在 [] 访问器操作符中指定相应的下标。请记住,JSON 数组索引是从 0 开始的:
$.track.segments[0].location
每个路径评估步骤的结果可以由SQL/JSON 路径操作符和方法中列出的一个或多个 jsonpath 操作符和方法进行处理。每个方法名前必须加上一个点。例如,您可以获取数组的大小:
$.track.segments.size()
在路径定义中,还可以使用一个或多个过滤器表达式,它们的工作方式类似于 SQL 中的 WHERE 子句。过滤器表达式以问号开头,并在括号中提供条件:
? (condition)
过滤器表达式必须紧接着它们应用的路径评估步骤写入。该步骤的结果被过滤,仅包括满足提供的条件的项。SQL/JSON 定义了三值逻辑,因此条件可以是 true、false 或 unknown。unknown 值扮演与 SQL NULL 相同的角色,并且可以使用 is unknown 谓词进行测试。进一步的路径评估步骤仅使用过滤器表达式返回 true 的项。
可以在表 jsonpath 过滤表达式元素中列出的函数和操作符中使用过滤器表达式。在过滤器表达式中,@ 变量表示正在过滤的值(即前面路径步骤的一个结果)。您可以在 @ 后面编写访问器操作符以检索组件项。
例如,假设您想要检索所有心率值大于 130 的值。您可以使用以下表达式实现:
$.track.segments[*].HR ? (@ > 130)
要获取具有这些值的片段的开始时间,您必须在返回开始时间之前过滤掉不相关的片段,因此将过滤器表达式应用于前一步骤,并且在条件中使用的路径不同:
$.track.segments[*] ? (@.HR > 130)."start time"
如果需要,可以按顺序使用多个过滤器表达式。例如,以下表达式选择包含相关坐标和高心率值的所有段的开始时间:
$.track.segments[*] ? (@.location[1] < 13.4) ? (@.HR > 130)."start time"
还允许在不同嵌套级别使用过滤器表达式。以下示例首先通过位置过滤所有段,然后返回这些段的高心率值(如果可用):
$.track.segments[*] ? (@.location[1] < 13.4).HR ? (@ > 130)
您还可以在彼此内嵌的过滤器表达式中嵌套:
$.track ? (exists(@.segments[*] ? (@.HR > 130))).segments.size()
如果包含任何具有高心率值的段,则此表达式返回轨迹的大小,否则返回空序列。
UXsinoDB 的 SQL/JSON 路径语言实现与 SQL/JSON 标准有以下偏差:
-
路径表达式可以是布尔谓词,尽管 SQL/JSON 标准仅允许在过滤器中使用谓词。这对于实现
@@操作符是必要的。例如,以下jsonpath表达式在 UXsinoDB 中是有效的:$.track.segments[*].HR < 70 -
在
like_regex过滤器中使用的正则表达式模式的解释存在细微差异。
17.2.1. 严格模式和宽松模式
查询 JSON 数据时,路径表达式可能与实际的 JSON 数据结构不匹配。尝试访问对象的不存在成员或数组的元素会导致结构错误。SQL/JSON 路径表达式有两种处理结构错误的模式:
-
宽松模式(默认)- 路径引擎隐式地将查询的数据适应于指定的路径。任何剩余的结构错误都会被抑制并转换为空的 SQL/JSON 序列。
-
严格模式 - 如果发生结构错误,则会引发错误。
宽松模式有助于匹配 JSON 文档结构和路径表达式,如果 JSON 数据不符合预期的模式,则可以使用宽松模式。如果操作数不符合特定操作的要求,则可以自动将其包装 SQL/JSON 数组或通过将其元素转换为 SQL/JSON 序列来取消包装。此外,比较操作符在宽松模式下自动取消包装其操作数,因此您可以直接比较 SQL/JSON 数组。大小为 1 的数组被视为等于其唯一元素。仅当以下情况时不执行自动取消包装:
-
路径表达式包含
type()或size()方法分别返回数组的类型和元素数量。 -
查询的 JSON 数据包含嵌套数组。在这种情况下,只有最外层的数组被展开,而所有内部数组保持不变。因此,隐式展开只能在每个路径评估步骤中向下展开一级。
例如,在查询上面列出的 GPS 数据时,您可以在使用松散模式时抽象出它存储了一组段的事实:
lax $.track.segments.location
在严格模式下,指定的路径必须完全匹配查询的 JSON 文档的结构才能返回 SQL/JSON 项,因此使用此路径表达式将导致错误。要获得与松散模式相同的结果,您必须显式展开 segments 数组:
strict $.track.segments[*].location
当使用松散模式时,.** 访问器可能会导致令人惊讶的结果。例如,以下查询会将每个 HR 值选择两次:
lax $.**.HR
这是因为 .** 访问器选择了 segments 数组及其每个元素,而 .HR 访问器在使用松散模式时会自动展开数组。为避免出现令人惊讶的结果,我们建议仅在严格模式下使用 .** 访问器。以下查询仅选择每个 HR 值一次:
strict $.**.HR
17.2.2. SQL/JSON 路径操作符和方法
表 jsonpath 操作符和方法显示了在 jsonpath 中可用的操作符和方法。请注意,虽然一元操作符和方法可以应用于先前路径步骤产生的多个值,但二元操作符(加法等)只能应用于单个值。
| 操作符/方法 | 描述 | 示例 |
|---|---|---|
number + number → number | 加法 | jsonb_path_query('[2]', '$[0] + 3') → 5 |
+ number → number | 一元加号(无操作);与加法不同,它可以迭代多个值 | jsonb_path_query_array('{"x": [2,3,4]}', '+ $.x') → [2, 3, 4] |
number - number → number | 减法 | jsonb_path_query('[2]', '7 - $[0]') → 5 |
- number → number | 取反;与减法不同,它可以迭代多个值 | jsonb_path_query_array('{"x": [2,3,4]}', '- $.x') → [-2, -3, -4] |
number * number → number | 乘法 | jsonb_path_query('[4]', '2 * $[0]') → 8 |
number / number → number | 除法 | jsonb_path_query('[8.5]', '$[0] / 2') → 4.2500000000000000 |
number % number → number | 模数(余数) | jsonb_path_query('[32]', '$[0] % 10') → 2 |
value . type() → string | JSON 项的类型(参见 json_typeof) | jsonb_path_query_array('[1, "2", {}]', '$[*].type()') → ["number", "string", "object"] |
value . size() → number | JSON 项的大小(数组元素数量,如果不是数组则为 1) | jsonb_path_query('{"m": [11, 15]}', '$.m.size()') → 2 |
value . double() → number | 从 JSON 数字或字符串转换的近似浮点数 | jsonb_path_query('{"len": "1.9"}', '$.len.double() * 2') → 3.8 |
number . ceiling() → number | 最接近给定数字且大于或等于它的整数 | jsonb_path_query('{"h": 1.3}', '$.h.ceiling()') → 2 |
number . floor() → number | 最接近给定数字且小于或等于它的整数 | jsonb_path_query('{"h": 1.7}', '$.h.floor()') → 1 |
number . abs() → number | 给定数字的绝对值 | jsonb_path_query('{"z": -0.3}', '$.z.abs()') → 0.3 |
string . datetime() → datetime_type | 从字符串转换为日期/时间值 | jsonb_path_query('["2015-8-1", "2015-08-12"]', '$[*] ? (@.datetime() < "2015-08-2".datetime())') → "2015-8-1" |
string . datetime(template) → datetime_type | 使用指定的 to_timestamp 模板从字符串转换为日期/时间值 | jsonb_path_query_array('["12:30", "18:40"]', '$[*].datetime("HH24:MI")') → ["12:30:00", "18:40:00"] |
object . keyvalue() → array | 将对象的键值对表示为包含三个字段的对象数组:"key"、"value" 和 "id";"id" 是键值对所属对象的唯一标识符 | jsonb_path_query_array('{"x": "20", "y": 32}', '$.keyvalue()') → [{"id": 0, "key": "x", "value": "20"}, {"id": 0, "key": "y", "value": 32}] |
注释
datetime()和datetime(template)方法的结果类型可以是date、timetz、time、timestamptz或timestamp。这两种方法动态确定其结果类型。
datetime()方法依次尝试将其输入字符串与 ISO 格式匹配,以获取date、timetz、time、timestamptz和timestamp的相应数据类型。它在第一个匹配格式时停止并发出相应的数据类型。
datetime(template)方法根据提供的模板字符串中使用的字段确定结果类型。
datetime()和datetime(template)方法使用与 SQL 函数to_timestamp相同的解析规则,但有三个例外。首先,这些方法不允许不匹配的模板模式。其次,模板字符串中只允许以下分隔符:减号、句点、斜杠(斜杠)、逗号、撇号、分号、冒号和空格。第三,模板字符串中的分隔符必须与输入字符串完全匹配。如果需要比较不同的日期/时间类型,则会应用隐式转换。可以将
date值转换为timestamp或timestamptz,将timestamp转换为timestamptz,将time转换为timetz。但是,除第一个转换外,所有这些转换都取决于当前的TimeZone设置,因此只能在有时区意识的jsonpath函数中执行。
表 jsonpath 过滤表达式元素显示了可用的过滤表达式元素。
| 谓词/值 | 描述 | 示例 |
|---|---|---|
value == value → boolean | 相等比较(这个和其他比较操作符适用于所有 JSON 标量值) | jsonb_path_query_array('[1, "a", 1, 3]', '$[*] ? (@ == 1)') → [1, 1]jsonb_path_query_array('[1, "a", 1, 3]', '$[*] ? (@ == "a")') → ["a"] |
value != value → booleanvalue <> value → boolean | 非等比较 | jsonb_path_query_array('[1, 2, 1, 3]', '$[*] ? (@ != 1)') → [2, 3]jsonb_path_query_array('["a", "b", "c"]', '$[*] ? (@ <> "b")') → ["a", "c"] |
value < value → boolean | 小于比较 | jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ < 2)') → [1] |
value <= value → boolean | 小于或等于比较 | jsonb_path_query_array('["a", "b", "c"]', '$[*] ? (@ <= "b")') → ["a", "b"] |
value > value → boolean | 大于比较 | jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ > 2)') → [3] |
value >= value → boolean | 大于等于比较 | jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ >= 2)') → [2, 3] |
true → boolean | JSON 常量 true | jsonb_path_query('[{"name": "John", "parent": false}, {"name": "Chris", "parent": true}]', '$[*] ? (@.parent == true)') → {"name": "Chris", "parent": true} |
false → boolean | JSON 常量 false | jsonb_path_query('[{"name": "John", "parent": false}, {"name": "Chris", "parent": true}]', '$[*] ? (@.parent == false)') → {"name": "John", "parent": false} |
null → value | JSON 常量 null(注意,与 SQL 不同,与 null 的比较正常工作) | jsonb_path_query('[{"name": "Mary", "job": null}, {"name": "Michael", "job": "driver"}]', '$[*] ? (@.job == null) .name') → "Mary" |
boolean && boolean → boolean | 布尔 AND | jsonb_path_query('[1, 3, 7]', '$[*] ? (@ > 1 && @ < 5)') → 3 |
boolean || boolean → boolean | 布尔 OR | jsonb_path_query('[1, 3, 7]', '$[*] ? (@ < 1 || @ > 5)') → 7 |
! boolean → boolean | 布尔 NOT | jsonb_path_query('[1, 3, 7]', '$[*] ? (!(@ < 5))') → 7 |
boolean is unknown → boolean | 测试布尔条件是否为 unknown。 | jsonb_path_query('[-1, 2, 7, "foo"]', '$[*] ? ((@ > 0) is unknown)') → "foo" |
string like_regex string [ flag string ] → boolean | 测试第一个操作数是否与第二个操作数给出的正则表达式匹配,可以选择使用标志字符串描述的修改。 | jsonb_path_query_array('["abc", "abd", "aBdC", "abdacb", "babc"]', '$[*] ? (@ like_regex "^ab.*c")') → ["abc", "abdacb"]jsonb_path_query_array('["abc", "abd", "aBdC", "abdacb", "babc"]', '$[*] ? (@ like_regex "^ab.*c" flag "i")') → ["abc", "aBdC", "abdacb"] |
string starts with string → boolean | 测试第二个操作数是否为第一个操作数的初始子字符串。 | jsonb_path_query('["John Smith", "Mary Stone", "Bob Johnson"]', '$[*] ? (@ starts with "John")') → "John Smith" |
exists ( path_expression ) → boolean | 测试路径表达式是否至少匹配一个 SQL/JSON 项。返回未知的路径表达式是否会导致错误;第二个示例使用该表达式在严格模式下避免无此键错误。 | jsonb_path_query('{"x": [1, 2], "y": [2, 4]}', 'strict $.* ? (exists (@ ? (@[*] > 2)))') → [2, 4]jsonb_path_query_array('{"value": 41}', 'strict $ ? (exists (@.name)) .name') → [] |
17.2.3. SQL/JSON 正则表达式
SQL/JSON 路径表达式允许使用 like_regex 过滤器将文本与正则表达式匹配。例如,以下 SQL/JSON 路径查询将不区分大小写地匹配以英语元音字母开头的数组中的所有字符串:
$[*] ? (@ like_regex "^[aeiou]" flag "i")
可选的 flag 字符串可以包含一个或多个字符 i 表示不区分大小写匹配,m 表示允许 ^ 和 $ 在换行符处匹配,s 表示允许 . 匹配换行符,q 表示引用整个模式(将行为简化为简单的子字符串匹配)。
SQL/JSON 标准从 LIKE_REGEX 操作符中借用了其正则表达式的定义,而 LIKE_REGEX 操作符又使用了 XQuery 标准。UXsinoDB 目前不支持 LIKE_REGEX 操作符。因此,like_regex 过滤器使用在 POSIX 正则表达式中描述的 POSIX 正则表达式引擎实现。这导致与标准 SQL/JSON 行为的各种轻微差异,这些差异在与 XQuery 的区别 (LIKE_REGEX)中进行了分类。然而,请注意,那里描述的标志字母不兼容性不适用于 SQL/JSON,因为它将 XQuery 标志字母转换为与 POSIX 引擎所期望的匹配。
请记住,like_regex 的模式参数是一个 JSON 路径字符串文字。这意味着特别要注意的是,您想在正则表达式中使用的任何反斜杠都必须加倍。例如,要匹配仅包含数字的根文档的字符串值:
$.* ? (@ like_regex "^\\d+$")
18. 序列操作函数
本节介绍用于操作序列对象(也称为序列生成器或序列)的函数。序列对象是使用 CREATE SEQUENCE 创建的特殊单行表。序列对象通常用于为表的行生成唯一标识符。在表 序列函数中列出的序列函数提供了从序列对象获取连续序列值的简单、多用户安全的方法。
| 函数 | 描述 |
|---|---|
nextval ( regclass ) → bigint | 将序列对象推进到其下一个值并返回该值。这是原子性的:即使多个会话同时执行 nextval,每个会话也会安全地接收到一个不同的序列值。如果使用默认参数创建序列对象,则连续的 nextval 调用将从 1 开始返回连续的值。可以通过在 CREATE SEQUENCE 命令中使用适当的参数来获得其他行为。此函数需要序列的 USAGE 或 UPDATE 权限。 |
setval ( regclass, bigint [ , boolean ] ) → bigint | 设置序列对象的当前值,可选地设置其 is_called 标志。两个参数的形式将序列的 last_value 字段设置为指定的值,并将其 is_called 字段设置为 true,表示下一个 nextval 将在返回值之前推进序列。由 currval 报告的值也设置为指定的值。在三个参数的形式中,is_called 可以设置为 true 或 false。true 具有与两个参数形式相同的效果。如果设置为 false,则下一个 nextval 将返回完全指定的值,并且序列推进将从以下 nextval 开始。此外,在这种情况下,由 currval 报告的值不会更改。例如,SELECT setval('myseq', 42); 下一个 nextval 将返回 43SELECT setval('myseq', 42, true); 与上面相同SELECT setval('myseq', 42, false); 下一个 nextval 将返回 42setval 返回的结果只是其第二个参数的值。此函数需要对序列具有 UPDATE 权限。 |
currval ( regclass ) → bigint | 返回当前会话中此序列最近由 nextval 获取的值。(如果在此会话中从未为此序列调用过 nextval,则报告错误。)因为这返回一个会话本地值,所以它无论其他会话是否执行了 nextval,都会给出可预测的答案。此函数需要对序列具有 USAGE 或 SELECT 权限。 |
lastval () → bigint | 返回当前会话中最近由 nextval 返回的值。此函数与 currval 相同,只是它不需要将序列名称作为参数,而是引用当前会话中最近应用 nextval 的任何序列。如果在当前会话中尚未调用 nextval,则调用 lastval 是错误的。此函数需要对最近使用的序列具有 USAGE 或 SELECT 权限。 |
注意
为避免阻塞从同一序列获取数字的并发事务,如果调用事务后续中止,则不会重新使用由nextval获取的值。这意味着事务中止或数据库崩溃可能导致分配值序列中的间隙。即使没有并发事务,这也可能发生。事务中止也会影响序列。例如,带有 ON CONFLICT 子句的 INSERT 语句将计算要插入的元组,包括执行任何必需的 nextval 调用,然后才检测是否存在冲突,如果存在冲突,则遵循 ON CONFLICT 规则。因此,UXsinoDB 序列对象不能用于获取“无间隙”的序列。
同样,由 setval 进行的序列状态更改对其他事务立即可见,并且如果调用事务回滚,则不会撤消这些更改。
如果在提交包含 nextval 或 setval 调用的事务之前,数据库集群崩溃,则序列状态更改可能尚未传递到持久存储,因此不确定在群集重新启动后序列是否具有其原始状态或更新状态。对于数据库内部使用序列值,这是无害的,因为未提交事务的其他影响也不可见。但是,如果您希望将序列值用于持久的数据库外部目的,请确保在这样做之前已提交 nextval 调用。
由序列函数操作的序列由 regclass 参数指定,该参数只是序列在 ux_class 系统目录中的 OID。但是,您不必手动查找 OID,因为 regclass 数据类型的输入转换器将为您完成此工作。
19. 条件表达式
本节介绍了在 UXsinoDB 中可用的符合 SQL 标准的条件表达式。
提示
如果您的需求超出了这些条件表达式的能力范围,您可能需要考虑使用更具表现力的编程语言编写服务器端函数。
注意
虽然COALESCE、GREATEST和LEAST在语法上类似于函数,但它们不是普通的函数,因此不能与显式的VARIADIC数组参数一起使用。
19.1. CASE
SQL CASE 表达式是一种通用的条件表达式,类似于其他编程语言中的 if/else 语句:
CASE WHEN condition THEN result
[WHEN ...]
[ELSE result]
END
CASE [col_name]
WHEN [value] THEN result...
[ ELSE result ]
END
CASE 子句可以在任何表达式有效的地方使用。每个 condition 都是返回 boolean 结果的表达式。如果条件的结果为真,则返回对应的 result。如果没有条件为真,则返回可选的 ELSE 子句中的 result。如果没有 ELSE 子句,则返回 NULL。
一个例子:
SELECT * FROM test;
a
---
1
2
3
SELECT a,
CASE WHEN a=1 THEN 'one'
WHEN a=2 THEN 'two'
ELSE 'other'
END
FROM test;
a | case
---+-------
1 | one
2 | two
3 | other
所有 result 表达式的数据类型必须可转换为单个输出类型。
有一种 CASE 表达式的“简单”形式,是上述一般形式的变体:
CASE expression
WHEN value THEN result
[WHEN ...]
[ELSE result]
END
首先计算第一个 expression,然后将其与 WHEN 子句中的每个 value 表达式进行比较,直到找到一个等于它的表达式。如果没有找到匹配项,则返回 ELSE 子句的 result(或 null 值)。这类似于 C 中的 switch 语句。
可以使用简单的 CASE 语法编写上面的示例:
SELECT a,
CASE a WHEN 1 THEN 'one'
WHEN 2 THEN 'two'
ELSE 'other'
END
FROM test;
a | case
---+-------
1 | one
2 | two
3 | other
CASE 表达式不评估不需要确定结果的任何子表达式。例如,这是避免除以零失败的可能方法:
SELECT ... WHERE CASE WHEN x <> 0 THEN y/x > 1.5 ELSE false END;
注意
有各种情况下,表达式的子表达式在不同的时间评估,因此原则“CASE仅评估必要的子表达式”并不是绝对的。例如,常量1/0子表达式通常会导致在计划时间发生除以零的失败,即使它在永远不会进入的CASE分支中。
19.2. COALESCE
COALESCE(value [, ...])
COALESCE 函数返回其参数中第一个非空值。仅当所有参数都为空时才返回空值。例如,在检索数据以显示时,通常用它来替换空值为默认值,例如:
SELECT COALESCE(description, short_description, '(none)') ...
如果 description 不为空,则返回它,否则返回 short_description,如果它不为空,则返回 (none)。
参数必须都可以转换为公共数据类型,这将是结果的类型。
与 CASE 表达式一样,COALESCE 仅评估需要确定结果的参数;也就是说,在第一个非空参数右侧的参数不会被评估。这个 SQL 标准函数提供了类似于其他一些数据库系统中使用的 NVL 和 IFNULL 的功能。
19.3. NULLIF
NULLIF(value1, value2)
NULLIF 函数如果 value1 等于 value2,则返回空值;否则返回 value1。
这个函数常用于避免特定值的计算,例如避免除以 0 错误。expr1 与 expr2 支持类型包括:char/varchar/text/smallint/int/bigint/decimal/double/float/boolean/date/time/time with time zone/timestamp/timestamp with time zone。
NULLIF 函数逻辑上和以下的 CASE 表达式的功能相同,如下所示。
CASE WHEN expr1=expr2 THEN NULL ELSE expr1 END
这可以用于执行上面给出的 COALESCE 的反向操作:
SELECT NULLIF(value, '(none)') ...
在这个例子中,如果 value 是 (none),则返回空值,否则返回 value 的值。
两个参数必须是可比较的类型。具体来说,它们将被精确比较,就好像你写了 value1 = value2 一样,因此必须有一个合适的 = 操作符可用。
结果与第一个参数具有相同的类型,但有一个微妙之处。实际返回的是隐含的 = 操作符的第一个参数,有时它将被提升以匹配第二个参数的类型。例如,NULLIF(1, 2.2) 产生 numeric,因为没有 integer = numeric 操作符,只有 numeric = numeric。
19.4. GREATEST 和 LEAST
GREATEST(value [, ...])
LEAST(value [, ...])
GREATEST 和 LEAST 函数从任意数量的表达式列表中选择最大或最小值。这些表达式必须都可以转换为公共数据类型,这将是结果的类型。列表中的 NULL 值将被忽略。仅当所有表达式都求值为 NULL 时,结果才为 NULL。
请注意,GREATEST 和 LEAST 不在 SQL 标准中,但它们是常见的扩展。一些其他数据库使它们返回 NULL,如果任何参数为 NULL,而不仅仅是当所有参数都为 NULL 时。
19.5. decode
-
功能
将输入的数值与函数中的参数列表相比较,根据输入值返回一个对应值。第一个参数为目标值或运算表达式,后续参数都是成对出现,成对参数的第一个作为判断条件,如果判断条件符合,则输出第二个参数,若参数列表末尾参数非成对出现,则为 default 结果,如果不存在与目标值一致的 search,则输出 default。default 值也可以省略,此时如果不存在与目标值一致的 search 则输出 NULL。
-
函数
select decode(expr, search1, result1, search2, result2, …, [default]); -
参数
表 decode 参数说明
参数 说明 expr 目标值或运算表达式,用于与参数列表中的 search 比较。 search1 … searchn 判断条件,与 expr 比较。 result1 … resultn 所要输出的结果,根据对应的 search 是否与 expr 匹配。 default 默认输出结果,若列表中没有与 expr 相匹配的 search,则输出 default,可省略,省略时输出 null。 -
返回值
返回值类型由 result 类型确定,各 result 类型不一致且无法转换时会报错。
-
示例
正常传入多个参数。
select decode (3, 1, 'one', 2, 'two', 3, 'three'); decode -------- three (1 row)没有与 expr 相匹配且携带 default。
select decode (4, 1, 'one', 2, 'two', 3, 'three', 'default'); decode --------- default (1 row)没有与 expr 相匹配未携带 default。
select decode (4, 1, 'one', 2, 'two', 3, 'three'); decode -------- (1 row)传入 2 个参数,数据转码功能。
select decode ('MTIzAAE=', 'base64'); decode -------------- \x3132330001 (1 row) -
注意事项
decode可接收的参数个数可变,且参数数据类型不确定,若传入各result参数数据类型的基类型相同,则内部可直接转换,最终输出对应数据类型,但存在传入参数的类型基类型也不一致的场景,需开启语法开关:set mysql_grammar to on,另外,若expr与search中数字与字符类型混合出现,为保证可正常比较,需创建隐式转换插件。
19.6. if
-
函数
IF(condition, value_if_true, value_if_false) -
参数
表 if 参数说明
参数 描述 condition 必需,要测试的值。 value_if_true 必需,condition 为 TRUE 时返回的值。 value_if_false 必需,condition 为 FALSE 时返回的值。 -
注意
第一个参数时间为 bool 类型,若无法转换为 bool 类型,则报错。
参数为查询 sql 语句时,需保证返回为单行单列,否则会报错。
-
示例
参数 1 为 true,如下所示。
select if(1, 2, 3); if ---- 2 (1 row)参数 1 为 false,如下所示。
select if(0, 2, 3); if ---- 3 (1 row)参数 1 为 null,如下所示。
select if(null, 2, 3); if ---- 3 (1 row)
19.7. IFNULL
-
函数
IFNULL(expr1, expr2)如果
expr1的值为 null,则返回expr2的值,如果expr1的值不为 null,则返回expr1的值。如果expr1和expr2数据类型相同,则返回expr1的类型;如果参数为字符类型,通常返回varchar类型;如果参数是不为varchar2的字符类型,通常返回varchar类型;如果参数是blob、clob、varchar2以外类型,一般返回text类型;expr1和expr2是时间类型、数值类型等不相同类型的,返回varchar类型(blob、clob、varchar2除外)。 -
注意
入参类型不支持
raw、binary、varbinary、longvarbinary、bit、varbit类型。 -
示例
-
ifnull(int,int)uxdb=# create table t as select ifnull(1::int,2::int); \d t; SELECT 1 Table "public.t" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- ifnull | integer | | | -
ifnull(int,date)uxdb=# create table t as select ifnull(1::int,2::date); \d t; SELECT 1 Table "public.t" Column | Type | Collation | Nullable | Default --------+-------------------+-----------+----------+--------- ifnull | character varying | | | -
ifnull(null,null::type)uxdb=# create table t as select ifnull(null,null::numeric); \d t; SELECT 1 Table "public.t" Column | Type | Collation | Nullable | Default --------+---------+-----------+----------+--------- ifnull | numeric | | | -
ifnull(unknown,null::type)uxdb=# create table t as select ifnull('',null::numeric); \d t; SELECT 1 Table "public.t" Column | Type | Collation | Nullable | Default --------+-------------------+-----------+----------+--------- ifnull | character varying | | | uxdb=# create table t as select ifnull('abc',null::numeric); \d t; SELECT 1 Table "public.t" Column | Type | Collation | Nullable | Default --------+-------------------+-----------+----------+--------- ifnull | character varying | | | -
ifnull(varbinary,numeric)uxdb=# create table t as select ifnull(1::varbinary,2::numeric); \d t; ERROR: varbinary and numeric cannot be used for conversion by ifnull LINE 1: create table t as select ifnull(1::varbinary,2::numeric); ^ Did not find any relation named "t". -
ifnull(blob,numeric)uxdb=# create table t as select ifnull(''::blob,2::numeric); \d t; SELECT 1 Table "public.t" Column | Type | Collation | Nullable | Default --------+------+-----------+----------+--------- ifnull | text | | | -
ifnull(null::type,null::type)uxdb=# create table t as select ifnull(null::varchar,2::numeric); \d t; SELECT 1 Table "public.t" Column | Type | Collation | Nullable | Default --------+-------------------+-----------+----------+--------- ifnull | character varying | | | -
ifnull(json,bytea)uxdb=# CREATE TABLE uxdb_mysql_function_ifnull_3703_tb01 ( type1 JSON,type2 bytea); CREATE TABLE uxdb=# INSERT INTO uxdb_mysql_function_ifnull_3703_tb01 VALUES (JSON '{"k1": "value", "k2": 10}' ,bytea '1' ); INSERT 0 1 uxdb=# INSERT INTO uxdb_mysql_function_ifnull_3703_tb01 DEFAULT VALUES; INSERT 0 1 uxdb=# SELECT IFNULL(type1,type2) FROM uxdb_mysql_function_ifnull_3703_tb01 order by 1; ERROR: ifnull could not convert type bytea to json LINE 1: SELECT IFNULL(type1,type2) FROM uxdb_mysql_function_ifnull_3... -
ifnull(json,inet)uxdb=# CREATE TABLE uxdb_mysql_function_ifnull_3703_tb01 ( type1 JSON,type2 inet); CREATE TABLE uxdb=# INSERT INTO uxdb_mysql_function_ifnull_3703_tb01 VALUES (JSON '{"k1": "value", "k2": 10}' ,inet '::10.2.3.4' ); INSERT 0 1 uxdb=# SELECT IFNULL(type1,type2) FROM uxdb_mysql_function_ifnull_3703_tb01 order by 1; ERROR: json and inet cannot be used for conversion by ifnull LINE 1: SELECT IFNULL(type1,type2) FROM uxdb_mysql_function_ifnull_3...
-
20. 数组函数和操作符
表 数组操作符显示了数组类型可用的专用操作符。除此之外,表 比较操作符中显示的通常比较操作符也可用于数组。比较操作符逐个元素地比较数组内容,使用元素数据类型的默认 B 树比较函数,并基于第一个不同点进行排序。在多维数组中,元素按行优先顺序访问(最后一个下标变化最快)。如果两个数组的内容相等但维数不同,则维数信息中的第一个差异决定排序顺序。
| 操作符 | 描述 | 示例 |
|---|---|---|
anyarray @> anyarray → boolean | 第一个数组是否包含第二个数组,即第二个数组中的每个元素是否等于第一个数组中的某个元素?(重复项不会被特殊处理,因此 ARRAY[1] 和 ARRAY[1,1] 都被认为包含另一个。) | ARRAY[1,4,3] @> ARRAY[3,1,3] → t |
anyarray <@ anyarray → boolean | 第一个数组是否被第二个数组包含? | ARRAY[2,2,7] <@ ARRAY[1,7,4,2,6] → t |
anyarray && anyarray → boolean | 这两个数组是否有重叠,即是否有任何共同元素? | ARRAY[1,4,3] && ARRAY[2,1] → t |
anycompatiblearray || anycompatiblearray → anycompatiblearray | 连接两个数组。连接空或空数组不会产生任何操作;否则,这两个数组必须具有相同数量的维度(如第一个示例所示),或者维度数量相差一(如第二个示例所示)。如果这两个数组的元素类型不相同,则它们将被强制转换为一个公共类型。 | ARRAY[1,2,3] || ARRAY[4,5,6,7] → {1,2,3,4,5,6,7}ARRAY[1,2,3] || ARRAY[[4,5,6],[7,8,9.9]] → {{1,2,3},{4,5,6},{7,8,9.9}} |
anycompatible || anycompatiblearray → anycompatiblearray | 将一个元素连接到一个数组的前面(该数组必须为空或一维)。 | 3 || ARRAY[4,5,6] → {3,4,5,6} |
anycompatiblearray || anycompatible → anycompatiblearray | 将一个元素连接到一个数组的末尾(该数组必须为空或一维)。 | ARRAY[4,5,6] || 7 → {4,5,6,7} |
表 数组函数显示了可用于数组类型的函数。
| 函数 | 描述 | 示例 |
|---|---|---|
array_append ( anycompatiblearray, anycompatible ) → anycompatiblearray | 将一个元素附加到数组的末尾(与 anycompatiblearray || anycompatible 操作符相同)。 | array_append(ARRAY[1,2], 3) → {1,2,3} |
array_cat ( anycompatiblearray, anycompatiblearray ) → anycompatiblearray | 连接两个数组(与 anycompatiblearray || anycompatiblearray 操作符相同)。 | array_cat(ARRAY[1,2,3], ARRAY[4,5]) → {1,2,3,4,5} |
array_dims ( anyarray ) → text | 返回数组维度的文本表示。 | array_dims(ARRAY[[1,2,3], [4,5,6]]) → [1:2][1:3] |
array_fill ( anyelement, integer[] [ , integer[] ] ) → anyarray | 返回一个由给定值的副本填充的数组,其维度由第二个参数指定的长度确定。可选的第三个参数为每个维度提供下限值(默认为所有 1)。 | array_fill(11, ARRAY[2,3]) → {{11,11,11},{11,11,11}}array_fill(7, ARRAY[3], ARRAY[2]) → [2:4]={7,7,7} |
array_length ( anyarray, integer ) → integer | 返回请求的数组维度的长度。(对于空或缺失的数组维度,产生 NULL 而不是 0。) | array_length(array[1,2,3], 1) → 3array_length(array[]::int[], 1) → NULLarray_length(array['text'], 2) → NULL |
array_lower ( anyarray, integer ) → integer | 返回请求的数组维度的下限。 | array_lower('[0:2]={1,2,3}'::integer[], 1) → 0 |
array_ndims ( anyarray ) → integer | 返回数组的维数。 | array_ndims(ARRAY[[1,2,3], [4,5,6]]) → 2 |
array_position ( anycompatiblearray, anycompatible [ , integer ] ) → integer | 返回数组中第二个参数的第一次出现的下标,如果不存在,则返回 NULL。如果给出第三个参数,则从该下标开始搜索。数组必须是一维的。比较使用 IS NOT DISTINCT FROM 语义,因此可以搜索 NULL。 | array_position(ARRAY['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'], 'mon') → 2 |
array_positions ( anycompatiblearray, anycompatible ) → integer[] | 返回第一个参数中所有出现第二个参数的下标数组。数组必须是一维的。比较使用 IS NOT DISTINCT FROM 语义,因此可以搜索 NULL。仅当数组为 NULL 时,才返回 NULL;如果在数组中未找到该值,则返回空数组。 | array_positions(ARRAY['A','A','B','A'], 'A') → {1,2,4} |
array_prepend ( anycompatible, anycompatiblearray ) → anycompatiblearray | 在数组开头添加一个元素(与 anycompatible || anycompatiblearray 操作符相同)。 | array_prepend(1, ARRAY[2,3]) → {1,2,3} |
array_remove ( anycompatiblearray, anycompatible ) → anycompatiblearray | 从数组中删除所有等于给定值的元素。数组必须是一维的。比较使用 IS NOT DISTINCT FROM 语义,因此可以删除 NULL。 | array_remove(ARRAY[1,2,3,2], 2) → {1,3} |
array_replace ( anycompatiblearray, anycompatible, anycompatible ) → anycompatiblearray | 将等于第二个参数的每个数组元素替换为第三个参数。 | array_replace(ARRAY[1,2,5,4], 5, 3) → {1,2,3,4} |
array_to_string ( array anyarray, delimiter text [ , null_string text ] ) → text | 将每个数组元素转换为其文本表示形式,并将它们用 delimiter 字符串分隔连接起来。如果给定 null_string 且不为 NULL,则 NULL 数组条目将由该字符串表示;否则,它们将被省略。 | array_to_string(ARRAY[1, 2, 3, NULL, 5], ',', '*') → 1,2,3,*,5 |
array_upper ( anyarray, integer ) → integer | 返回所请求的数组维度的上限。 | array_upper(ARRAY[1,8,3,7], 1) → 4 |
cardinality ( anyarray ) → integer | 返回数组中的元素总数,如果数组为空,则返回 0。 | cardinality(ARRAY[[1,2],[3,4]]) → 4 |
trim_array ( array anyarray, n integer ) → anyarray | 通过删除最后的 n 个元素来修剪数组。如果数组是多维的,则仅修剪第一维。 | trim_array(ARRAY[1,2,3,4,5,6], 2) → {1,2,3,4} |
unnest ( anyarray ) → setof anyelement | 将数组扩展为一组行。按存储顺序读取数组的元素。 | unnest(ARRAY[1,2]) → 12unnest(ARRAY[['foo','bar'],['baz','quux']]) → foobarbazquux |
unnest ( anyarray, anyarray [ , ... ] ) → setof anyelement, anyelement [, ... ] | 将多个数组(可能具有不同的数据类型)扩展为一组行。如果数组的长度不相同,则较短的数组将用 NULL 填充。此形式仅允许在查询的 FROM 子句中使用。 | select * from unnest(ARRAY[1,2], ARRAY['foo','bar','baz']) as x(a,b) → a | b---+-----1 | foo2 | bar| baz |
有关与数组一起使用的聚合函数 array_agg,请参见聚合函数。
21. 范围/多范围函数和操作符
表 范围操作符显示了范围类型可用的专用操作符。表 多范围操作符显示了多范围类型可用的专用操作符。除此之外,表 比较操作符中显示的通常比较操作符也适用于范围和多范围类型。比较操作符首先按范围下限排序,只有在下限相等时才比较上限。多范围操作符比较每个范围,直到有一个不相等。这通常不会产生有用的整体排序,但提供这些操作符是为了允许在范围上构建唯一索引。
| 操作符 | 描述 | 示例 |
|---|---|---|
anyrange @> anyrange → boolean | 第一个范围是否包含第二个范围? | int4range(2,4) @> int4range(2,3) → t |
anyrange @> anyelement → boolean | 范围是否包含元素? | '[2011-01-01,2011-03-01)'::tsrange @> '2011-01-10'::timestamp → t |
anyrange <@ anyrange → boolean | 第一个范围是否被第二个范围包含? | int4range(2,4) <@ int4range(1,7) → t |
anyelement <@ anyrange → boolean | 元素是否包含在范围内? | 42 <@ int4range(1,7) → f |
anyrange && anyrange → boolean | 范围是否重叠,即是否有任何共同元素? | int8range(3,7) && int8range(4,12) → t |
anyrange << anyrange → boolean | 第一个范围是否严格在第二个范围左侧? | int8range(1,10) << int8range(100,110) → t |
anyrange >> anyrange → boolean | 第一个范围是否严格在第二个范围右侧? | int8range(50,60) >> int8range(20,30) → t |
anyrange &< anyrange → boolean | 第一个范围是否不向右延伸到第二个范围? | int8range(1,20) &< int8range(18,20) → t |
anyrange &> anyrange → boolean | 第一个范围是否不向左延伸到第二个范围? | int8range(7,20) &> int8range(5,10) → t |
anyrange -|- anyrange → boolean | 范围是否相邻? | numrange(1.1,2.2) -|- numrange(2.2,3.3) → t |
anyrange + anyrange → anyrange | 计算范围的并集。范围必须重叠或相邻,以便并集是单个范围(但请参见 range_merge())。 | numrange(5,15) + numrange(10,20) → [5,20) |
anyrange * anyrange → anyrange | 计算范围的交集。 | int8range(5,15) * int8range(10,20) → [10,15) |
anyrange - anyrange → anyrange | 计算范围的差异。第二个范围不能包含在第一个范围中,以至于差异不是单个范围。 | int8range(5,15) - int8range(10,20) → [5,10) |
| 操作符 | 描述 | 示例 |
|---|---|---|
anymultirange @> anymultirange → boolean | 第一个多范围是否包含第二个? | '{[2,4)}'::int4multirange @> '{[2,3)}'::int4multirange → t |
anymultirange @> anyrange → boolean | 多范围是否包含范围? | '{[2,4)}'::int4multirange @> int4range(2,3) → t |
anymultirange @> anyelement → boolean | 多范围是否包含元素? | '{[2011-01-01,2011-03-01)}'::tsmultirange @> '2011-01-10'::timestamp → t |
anyrange @> anymultirange → boolean | 范围是否包含多范围? | '[2,4)'::int4range @> '{[2,3)}'::int4multirange → t |
anymultirange <@ anymultirange → boolean | 第一个多范围是否被第二个包含? | '{[2,4)}'::int4multirange <@ '{[1,7)}'::int4multirange → t |
anymultirange <@ anyrange → boolean | 多范围是否被范围包含? | '{[2,4)}'::int4multirange <@ int4range(1,7) → t |
anyrange <@ anymultirange → boolean | 范围是否被多范围包含? | int4range(2,4) <@ '{[1,7)}'::int4multirange → t |
anyelement <@ anymultirange → boolean | 元素是否被多范围包含? | 4 <@ '{[1,7)}'::int4multirange → t |
anymultirange && anymultirange → boolean | 这些多范围是否重叠,即是否有任何共同元素? | '{[3,7)}'::int8multirange && '{[4,12)}'::int8multirange → t |
anymultirange && anyrange → boolean | 这个多范围是否与范围重叠? | '{[3,7)}'::int8multirange && int8range(4,12) → t |
anyrange && anymultirange → boolean | 这个范围是否与多范围重叠? | int8range(3,7) && '{[4,12)}'::int8multirange → t |
anymultirange << anymultirange → boolean | 第一个多范围是否严格在第二个多范围左侧? | '{[1,10)}'::int8multirange << '{[100,110)}'::int8multirange → t |
anymultirange << anyrange → boolean | 这个多范围是否严格在范围左侧? | '{[1,10)}'::int8multirange << int8range(100,110) → t |
anyrange << anymultirange → boolean | 这个范围是否严格在多范围左侧? | int8range(1,10) << '{[100,110)}'::int8multirange → t |
anymultirange >> anymultirange → boolean | 第一个多范围是否严格在第二个多范围右侧? | '{[50,60)}'::int8multirange >> '{[20,30)}'::int8multirange → t |
anymultirange >> anyrange → boolean | 这个多范围是否严格在范围右侧? | '{[50,60)}'::int8multirange >> int8range(20,30) → t |
anyrange >> anymultirange → boolean | 这个范围是否严格在多范围右侧? | int8range(50,60) >> '{[20,30)}'::int8multirange → t |
anymultirange &< anymultirange → boolean | 第一个多范围是否不延伸到第二个的右侧? | '{[1,20)}'::int8multirange &< '{[18,20)}'::int8multirange → t |
anymultirange &< anyrange → boolean | 多范围是否不延伸到范围的右侧? | '{[1,20)}'::int8multirange &< int8range(18,20) → t |
anyrange &< anymultirange → boolean | 范围是否不延伸到多范围的右侧? | int8range(1,20) &< '{[18,20)}'::int8multirange → t |
anymultirange &> anymultirange → boolean | 第一个多范围是否不延伸到第二个的左侧? | '{[7,20)}'::int8multirange &> '{[5,10)}'::int8multirange → t |
anymultirange &> anyrange → boolean | 多范围是否不延伸到范围的左侧? | '{[7,20)}'::int8multirange &> int8range(5,10) → t |
anyrange &> anymultirange → boolean | 范围是否不延伸到多范围的左侧? | int8range(7,20) &> '{[5,10)}'::int8multirange → t |
anymultirange -|- anymultirange → boolean | 多范围是否相邻? | '{[1.1,2.2)}'::nummultirange -|- '{[2.2,3.3)}'::nummultirange → t |
anymultirange -|- anyrange → boolean | 多范围是否与范围相邻? | '{[1.1,2.2)}'::nummultirange -|- numrange(2.2,3.3) → t |
anyrange -|- anymultirange → boolean | 范围是否与多范围相邻? | numrange(1.1,2.2) -|- '{[2.2,3.3)}'::nummultirange → t |
anymultirange + anymultirange → anymultirange | 计算多范围的并集。多范围不需要重叠或相邻。 | '{[5,10)}'::nummultirange + '{[15,20)}'::nummultirange → {[5,10), [15,20)} |
anymultirange * anymultirange → anymultirange | 计算多范围的交集。 | '{[5,15)}'::int8multirange * '{[10,20)}'::int8multirange → {[10,15)} |
anymultirange - anymultirange → anymultirange | 计算多范围的差异。 | '{[5,20)}'::int8multirange - '{[10,15)}'::int8multirange → {[5,10), [15,20)} |
当涉及空范围或多范围时,左侧/右侧/相邻操作符始终返回 false;也就是说,空范围不被认为是在任何其他范围之前或之后。
在其他地方,空范围和多范围被视为加法恒等式:与空值联合的任何内容都是它本身。减去空值的任何内容都是它本身。空的多范围具有与空范围完全相同的点。每个范围都包含空范围。每个多范围都包含任意数量的空范围。
如果结果范围需要包含两个不相交的子范围,则范围联合和差异操作符将失败,因为这样的范围无法表示。有单独的联合和差异操作符,它们采用多范围参数并返回多范围,即使它们的参数是不相交的,它们也不会失败。因此,如果您需要联合或差异操作可能不相交的范围,则可以通过首先将范围转换为多范围来避免错误。
表 范围函数显示可用于范围类型的函数。 表 多范围函数显示可用于多范围类型的函数。
| 函数 | 描述 | 示例 |
|---|---|---|
lower ( anyrange ) → anyelement | 提取范围的下限(如果范围为空或下限为无穷大,则为 NULL)。 | lower(numrange(1.1,2.2)) → 1.1 |
upper ( anyrange ) → anyelement | 提取范围的上限(如果范围为空或上限为无穷大,则为 NULL)。 | upper(numrange(1.1,2.2)) → 2.2 |
isempty ( anyrange ) → boolean | 范围是否为空? | isempty(numrange(1.1,2.2)) → f |
lower_inc ( anyrange ) → boolean | 范围的下限是否包含在内? | lower_inc(numrange(1.1,2.2)) → t |
upper_inc ( anyrange ) → boolean | 范围的上限是否包含在内? | upper_inc(numrange(1.1,2.2)) → f |
lower_inf ( anyrange ) → boolean | 范围的下限是否为无限? | lower_inf('(,)'::daterange) → t |
upper_inf ( anyrange ) → boolean | 范围的上限是否为无限? | upper_inf('(,)'::daterange) → t |
range_merge ( anyrange, anyrange ) → anyrange | 计算包含给定范围的最小范围。 | range_merge('[1,2)'::int4range, '[3,4)'::int4range) → [1,4) |
| 函数 | 描述 | 示例 |
|---|---|---|
lower ( anymultirange ) → anyelement | 提取多范围的下限(如果多范围为空或下限为无限,则为 NULL)。 | lower('{[1.1,2.2)}'::nummultirange) → 1.1 |
upper ( anymultirange ) → anyelement | 提取多范围的上限(如果多范围为空或上限为无限,则为 NULL)。 | upper('{[1.1,2.2)}'::nummultirange) → 2.2 |
isempty ( anymultirange ) → boolean | 多范围是否为空? | isempty('{[1.1,2.2)}'::nummultirange) → f |
lower_inc ( anymultirange ) → boolean | 多范围的下限是否包含在内? | lower_inc('{[1.1,2.2)}'::nummultirange) → t |
upper_inc ( anymultirange ) → boolean | 多范围的上限是否包含在内? | upper_inc('{[1.1,2.2)}'::nummultirange) → f |
lower_inf ( anymultirange ) → boolean | 多范围的下限是否为无限? | lower_inf('{(,)}'::datemultirange) → t |
upper_inf ( anymultirange ) → boolean | 多范围的上限是否为无限? | upper_inf('{(,)}'::datemultirange) → t |
range_merge ( anymultirange ) → anyrange | 计算包含整个多范围的最小范围。 | range_merge('{[1,2), [3,4)}'::int4multirange) → [1,4) |
multirange ( anyrange ) → anymultirange | 返回仅包含给定范围的多范围。 | multirange('[1,2)'::int4range) → {[1,2)} |
unnest ( anymultirange ) → setof anyrange | 将多范围展开为一组范围。范围按存储顺序(升序)读取。 | unnest('{[1,2), [3,4)}'::int4multirange) → [1,2)[3,4) |
lower_inc、upper_inc、lower_inf 和 upper_inf 函数对于空范围或多范围都返回 false。
22. 聚合函数
聚合函数 从一组输入值中计算出单个结果。内置的通用聚合函数列在表 通用聚合函数中,而统计聚合函数则在表 统计聚合函数中。内置的组内有序集聚合函数列在表 有序集合聚合函数中,而内置的组内假设集函数则在表 虚拟集合聚合函数中。与聚合函数密切相关的分组操作列在表 分组操作中。
支持部分模式的聚合函数有资格参与各种优化,例如并行聚合。
| 函数 | 描述 | 部分模式 |
|---|---|---|
array_agg ( anynonarray ) → anyarray | 将所有输入值(包括 null)收集到一个数组中。 | 否 |
array_agg ( anyarray ) → anyarray | 将所有输入数组连接成一个更高维度的数组。(输入必须具有相同的维度,且不能为空或 null。) | 否 |
avg ( smallint ) → numericavg ( integer ) → numericavg ( bigint ) → numericavg ( numeric ) → numericavg ( real ) → double precisionavg ( double precision ) → double precisionavg ( interval ) → interval | 计算所有非 null 输入值的平均值(算术平均值)。 | 是 |
bit_and ( smallint ) → smallintbit_and ( integer ) → integerbit_and ( bigint ) → bigintbit_and ( bit ) → bit | 计算所有非 null 输入值的按位与。 | 是 |
bit_or ( smallint ) → smallintbit_or ( integer ) → integerbit_or ( bigint ) → bigintbit_or ( bit ) → bit | 计算所有非 null 输入值的按位或。 | 是 |
bit_xor ( smallint ) → smallintbit_xor ( integer ) → integerbit_xor ( bigint ) → bigintbit_xor ( bit ) → bit | 计算所有非 null 输入值的按位异或。可以用作无序值集的校验和。 | 是 |
bool_and ( boolean ) → boolean | 如果所有非空输入值都为 true,则返回 true,否则返回 false。 | 是 |
bool_or ( boolean ) → boolean | 如果任何非空输入值为 true,则返回 true,否则返回 false。 | 是 |
count ( * ) → bigint | 计算输入行数。 | 是 |
count ( "any" ) → bigint | 计算输入行数,其中输入值不为 null。 | 是 |
every ( boolean ) → boolean | 这是 SQL 标准等效于 bool_and。 | 是 |
json_agg ( anyelement ) → jsonjsonb_agg ( anyelement ) → jsonb | 将所有输入值(包括 null)收集到 JSON 数组中。值将根据 to_json 或 to_jsonb 转换为 JSON。 | 否 |
json_object_agg ( key "any", value "any" ) → jsonjsonb_object_agg ( key "any", value "any" ) → jsonb | 将所有键/值对收集到 JSON 对象中。键参数强制转换为文本;值参数将根据 to_json 或 to_jsonb 转换。值可以为 null,但键不行。 | 否 |
max ( see text ) → same as input type | 计算非 null 输入值的最大值。适用于任何数字,字符串,日期/时间或枚举类型,以及 inet、interval、money、oid、ux_lsn、tid、xid8,以及这些类型的数组。 | 是 |
min ( see text ) → same as input type | 计算非空输入值的最小值。适用于任何数字、字符串、日期/时间或枚举类型,以及 inet、interval、money、oid、ux_lsn、tid、xid8 和任何这些类型的数组。 | 是 |
range_agg ( value anyrange ) → anymultirangerange_agg ( value anymultirange ) → anymultirange | 计算非空输入值的并集。 | 否 |
range_intersect_agg ( value anyrange ) → anyrangerange_intersect_agg ( value anymultirange ) → anymultirange | 计算非空输入值的交集。 | 否 |
string_agg ( value text, delimiter text ) → textstring_agg ( value bytea, delimiter bytea ) → bytea | 将非空输入值连接成字符串。第一个值之后的每个值都在其前面加上相应的 delimiter(如果它不为空)。 | 否 |
sum ( smallint ) → bigintsum ( integer ) → bigintsum ( bigint ) → numericsum ( numeric ) → numericsum ( real ) → realsum ( double precision ) → double precisionsum ( interval ) → intervalsum ( money ) → money | 计算非空输入值的总和。 | 是 |
xmlagg ( xml ) → xml | 连接非空的 XML 输入值。 | 否 |
需要注意的是,除了 count 之外,这些函数在未选择任何行时返回 null 值。特别地,没有行的 sum 返回 null,而不是像人们可能期望的那样返回零,而 array_agg 在没有输入行时返回 null 而不是空数组。当需要时,coalesce 函数可用于将零或空数组替换为 null。
聚合函数 array_agg、json_agg、jsonb_agg、json_object_agg、jsonb_object_agg、string_agg 和 xmlagg,以及类似的用户定义的聚合函数,根据输入值的顺序产生有意义的不同结果值。默认情况下,这种排序是未指定的,但可以通过在聚合调用中编写 ORDER BY 子句来控制。或者,通常可以通过从排序的子查询中提供输入值来解决。例如:
SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab;
请注意,如果外部查询级别包含其他处理(例如联接),则此方法可能会失败,因为这可能会导致在计算聚合之前重新排序子查询的输出。
注意
布尔聚合函数bool_and和bool_or对应于标准 SQL 聚合函数every和any或some。UXsinoDB 支持every,但不支持any或some,因为标准语法中存在一个歧义:SELECT b1 = ANY((SELECT b2 FROM t2 ...)) FROM t1 ...;在这里,
ANY可以被认为是引入子查询,也可以被认为是聚合函数,如果子查询返回一个布尔值的行。因此,不能将标准名称赋予这些聚合函数。
习惯于使用其他 SQL 数据库管理系统的用户可能会对将 count 聚合应用于整个表时的性能感到失望。像这样的查询:
SELECT count(*) FROM sometable;
将需要与表的大小成比例的工作量:UXsinoDB 需要扫描整个表或包括表中所有行的索引的全部内容。
表 统计聚合函数显示了通常用于统计分析的聚合函数。(这些仅分开显示,以避免杂乱无章地列出更常用的聚合函数。)作为统计分析的一部分,还提供了一些专用的聚合函数,如聚合函数所述。可接受 numeric_type 的函数适用于所有类型 smallint、integer、bigint、numeric、real 和 double precision。当描述中提到 N 时,它表示所有输入表达式都非空的输入行数。在所有情况下,如果计算无意义,例如当 N 为零时,将返回 null。
| 函数 | 描述 | 部分模式 |
|---|---|---|
corr ( Y double precision, X double precision ) → double precision | 计算相关系数。 | 是 |
covar_pop ( Y double precision, X double precision ) → double precision | 计算总体协方差。 | 是 |
covar_samp ( Y double precision, X double precision ) → double precision | 计算样本协方差。 | 是 |
regr_avgx ( Y double precision, X double precision ) → double precision | 计算自变量的平均值,sum(X)/N。 | 是 |
regr_avgy ( Y double precision, X double precision ) → double precision | 计算因变量的平均值,sum(Y)/N。 | 是 |
regr_count ( Y double precision, X double precision ) → bigint | 计算两个输入都非空的行数。 | 是 |
regr_intercept ( Y double precision, X double precision ) → double precision | 计算由(X,Y)对确定的最小二乘拟合线性方程的 y 截距。 | 是 |
regr_r2 ( Y double precision, X double precision ) → double precision | 计算相关系数的平方。 | 是 |
regr_slope ( Y double precision, X double precision ) → double precision | 计算由(X,Y)对确定的最小二乘拟合线性方程的斜率。 | 是 |
regr_sxx ( Y double precision, X double precision ) → double precision | 计算独立变量的“平方和”,sum(X^2) - sum(X)^2/N。 | 是 |
regr_sxy ( Y double precision, X double precision ) → double precision | 计算独立变量和相关变量的“乘积和”,sum(X*Y) - sum(X) * sum(Y)/N。 | 是 |
regr_syy ( Y double precision, X double precision ) → double precision | 计算因变量的“平方和”,公式为 sum(Y^2) - sum(Y)^2/N。 | 是 |
stddev ( numeric_type ) → double precision for floating-point, else numeric | stddev 是历史别名,现在使用 stddev_samp。 | 是 |
stddev_pop ( numeric_type ) → double precision for floating-point, else numeric | 计算输入值的总体标准差。 | 是 |
stddev_samp ( numeric_type ) → double precision for floating-point, else numeric | 计算输入值的样本标准差。 | 是 |
variance ( numeric_type ) → double precision for floating-point, else numeric | variance 是历史别名,现在使用 var_samp。 | 是 |
var_pop ( numeric_type ) → double precision for floating-point, else numeric | 计算输入值的总体方差(总体标准差的平方)。 | 是 |
var_samp ( numeric_type ) → double precision for floating-point, else numeric | 计算输入值的样本方差(样本标准差的平方)。 | 是 |
表 有序集合聚合函数显示了一些有序集合聚合函数。使用有序集合聚合语法的聚合函数。
这些函数有时被称为逆分布函数。它们的聚合输入由 ORDER BY 引入,它们还可以接受一个直接参数,该参数不是聚合的,但仅计算一次。所有这些函数都忽略其聚合输入中的空值。对于那些带有 fraction 参数的函数,分数值必须在 0 和 1 之间;如果不是,则会抛出错误。然而,空的 fraction 值只会产生一个空结果。
| 函数 | 描述 | 部分模式 |
|---|---|---|
LISTAGG (expr[,delimiter]) WITHIN GROUP (ORDER BY expr[,expr......]) → text | 可以根据排序参数(ORDER BY 后面的列)对表中数据进行排序,然后根据聚集参数对查询列进行聚合,若存在分隔符,则会对需要聚集的列用分隔符进行分隔。 | 是 |
mode () WITHIN GROUP ( ORDER BY anyelement ) → anyelement | 计算聚合参数的众数,即最频繁出现的值(如果有多个同样频繁的值,则任意选择第一个)。聚合参数必须是可排序类型。 | 否 |
percentile_cont ( fraction double precision ) WITHIN GROUP ( ORDER BY double precision ) → double precisionpercentile_cont ( fraction double precision ) WITHIN GROUP ( ORDER BY interval ) → interval | 计算连续百分位数,即在聚合参数值的有序集合中对应于指定 fraction 的值。如果需要,这将在相邻的输入项之间进行插值。 | 否 |
percentile_cont ( fractions double precision[] ) WITHIN GROUP ( ORDER BY double precision ) → double precision[]percentile_cont ( fractions double precision[] ) WITHIN GROUP ( ORDER BY interval ) → interval[] | 计算多个连续百分位数。结果是与 fractions 参数具有相同维度的数组,其中每个非空元素都被替换为对应于该百分位数的(可能插值的)值。 | 否 |
percentile_disc ( fraction double precision ) WITHIN GROUP ( ORDER BY anyelement ) → anyelement | 计算离散百分位数,即有序聚合参数值集合中第一个位置等于或超过指定 fraction 的值。聚合参数必须是可排序类型。 | 否 |
percentile_disc ( fractions double precision[] ) WITHIN GROUP ( ORDER BY anyelement ) → anyarray | 计算多个离散百分位数。结果是与 fractions 参数具有相同维度的数组,每个非空元素都被对应于该百分位数的输入值替换。聚合参数必须是可排序类型。 | 否 |
表 虚拟集合聚合函数中列出的每个“虚拟集合”聚合函数都与同名的窗口函数相关联,这些函数在窗口函数中定义。在每种情况下,聚合的结果是与关联的窗口函数为 sorted_args 表示的排序行组添加了一个虚拟行后返回的值。对于这些函数,args 中给出的直接参数列表必须与 sorted_args 中给出的聚合参数的数量和类型相匹配。与大多数内置聚合函数不同,这些聚合函数不是严格的,即它们不会删除包含空值的输入行。空值按 ORDER BY 子句中指定的规则排序。
| 函数 | 描述 | 部分模式 |
|---|---|---|
rank ( args ) WITHIN GROUP ( ORDER BY sorted_args ) → bigint | 计算虚拟行的排名,带有间隙;即其对等组中第一行的行号。 | 否 |
dense_rank ( args ) WITHIN GROUP ( ORDER BY sorted_args ) → bigint | 计算假设行的排名,没有间隔;这个函数有效地计算对等组。 | 否 |
percent_rank ( args ) WITHIN GROUP ( ORDER BY sorted_args ) → double precision | 计算假设行的相对排名,即 (rank - 1) / (总行数 - 1)。因此,该值的范围从 0 到 1(包括 0 和 1)。 | 否 |
cume_dist ( args ) WITHIN GROUP ( ORDER BY sorted_args ) → double precision | 计算累积分布,即(假设行之前或对等行的数量)/(总行数)。因此,该值的范围从 1/N 到 1。 | 否 |
| 函数 | 描述 |
|---|---|
GROUPING ( group_by_expression(s) ) → integer | 返回一个位掩码,指示哪些 GROUP BY 表达式不包含在当前分组集中。位分配与最右边的参数对应,对应最低有效位;如果相应的表达式包含在生成当前结果行的分组集的分组条件中,则每个位为 0,否则为 1。 |
GROUPING_ID ( expr [, expr ]..... ) → numeric | 将超聚合行与常规分组行区分开来。 |
GROUP BY 扩展,例如 ROLLUP 和 CUBE 生成超聚合行,其中所有值的集合由 null 表示。GROUPING_ID 函数,可以将表示超聚合行中所有值的集合的空值与常规行中的空值区分开来。
注意
GROUPING_ID函数有如下使用限制。
- 必须带有 group by 子句。
- 不能用作 where 条件。
- 可以使用 having 子句筛选。
create table liml_test(
id numeric(6),
no int,
first_name VARCHAR(20),
last_name VARCHAR(30),
email VARCHAR(30)
);
insert into liml_test values(1,1,'james','lebron','13478653gd@a63.com');
insert into liml_test values(2,2,'pual','cris','13378653gd@a63.com');
select id, no, grouping_id(id,no) from liml_test group by cube(id,no);
id | no | grouping_id
----+----+-------------
| | 3
2 | 2 | 0
1 | 1 | 0
1 | | 1
2 | | 1
| 2 | 2
| 1 | 2
(7 rows)
表 分组操作中显示的分组操作与分组集结合使用,以区分结果行。GROUPING 函数的参数实际上不会被评估,但它们必须与关联查询级别的 GROUP BY 子句中给定的表达式完全匹配。例如:
=> SELECT * FROM items_sold;
make | model | sales
-------+-------+-------
Foo | GT | 10
Foo | Tour | 20
Bar | City | 15
Bar | Sport | 5
(4 行记录)
=> SELECT make, model, GROUPING(make,model), sum(sales) FROM items_sold GROUP BY ROLLUP(make,model);
make | model | grouping | sum
-------+-------+----------+-----
Foo | GT | 0 | 10
Foo | Tour | 0 | 20
Bar | City | 0 | 15
Bar | Sport | 0 | 5
Foo | | 1 | 30
Bar | | 1 | 20
| | 3 | 50
(7 行记录)
在这里,前四行中的 grouping 值 0 显示它们已经按照 make 和 model 正常分组,而最后三行则是按照 make 或 model 进行分组的结果。值 1 表示在倒数第二行中未按 model 进行分组,值 3 表示在最后一行中未按 make 或 model 进行分组(因此是所有输入行的聚合)。
22.1. LISTAGG
-
功能
LISTAGG列转行的有序聚集函数。可以根据排序参数(ORDER BY后面的列)对表中数据进行排序,然后根据聚集参数对查询列进行聚合,若存在分隔符,则会对需要聚集的列用分隔符进行分隔。 -
函数
LISTAGG( expr [,delimiter]) WITHIN GROUP (ORDER BY expr[,expr......]) [over(partition by expr )] -
参数
表 LISTAGG 参数说明
参数 说明 expr 一个表中已经存在的列名。 delimiter 一个任意的分隔符。 -
示例
将表中的数据按照 first_name 分组排序后进行聚合。
select listagg(first_name,',') within group (order by first_name) from liml_test group by first_name; -
注意
listagg函数用作分析函数时,不能带within group (order by ...)子句。
22.2. aggregate_name KEEP
-
功能
keep子句用于辅助聚集函数取分组排序后的聚集结果,也可以与聚集函数及over窗口函数组合使用,取分区后分组排序的聚集结果。 -
函数
aggregate_name KEEP ( DENSE_RANK FIRST | LAST ORDER BY expr [ DESC | ASC ] [ NULLS { FIRST | LAST } ] [, expr [ DESC | ASC ] [ NULLS { FIRST | LAST } ]]...) [ OVER ( [query_partition_clause] ) ] -
参数
表 aggregate_name KEEP 参数说明
参数 说明 aggregate_name 所有聚集函数(包括自定义的)。 KEEP 分析函数,取同一个分组下以某个字段排序后,对执行字段取最小或最大的那个值。 DENSE_RANK FIRST LAST ORDER BY 指定排序顺序的列或表达式。 NULLS FIRST LAST OVER 开窗函数(或窗口函数),指定聚合函数的工作窗口,即聚合函数作用域。 query_partition_clause 分析函数,以某一个或多个字段为条件进行分组,一般是被 over 指定使用,相比较于 group by,它能够保留全部数据。 -
示例
将 keep_test 表中的数据按照普通聚集的方式获取结果集,如下所示。
select min(sal) keep(dense_rank first order by dept_id) from keep_test;将 keep_test 表中的数据按照窗口聚集的方式获取结果集,如下所示。
select min(sal) keep(dense_rank first order by a_id) over(partition by dept_id) from keep_test; -
注意
- 聚集函数 + keep 子句组合查询时,只能查询聚集结果信息。
- 聚集函数 + keep 子句 + over 窗口函数组合查询时,over 中不能使用 order by 做排序。
- keep 子句不可以与非聚集函数组合使用。
23. 窗口函数
窗口函数提供了在与当前查询行相关的行集合上执行计算的能力。
内置的窗口函数列在表 通用窗口函数中。请注意,这些函数必须使用窗口函数语法调用,即需要一个 OVER 子句。
除了这些函数之外,任何内置或用户定义的普通聚合函数(即不是有序集或假设集聚合)都可以用作窗口函数;有关内置聚合函数的列表,请参见聚合函数。只有在调用后跟随一个 OVER 子句时,聚合函数才充当窗口函数;否则,它们充当普通聚合函数,并为整个集合返回单个行。
| 函数 | 说明 |
|---|---|
row_number () → bigint | 返回其分区内当前行的编号,从 1 开始计数。 |
rank () → bigint | 返回当前行的排名,带有间隙;也就是说,它是其对等组中第一行的 row_number。 |
dense_rank () → bigint | 返回当前行的排名,没有间隔;此函数有效地计算对等组。 |
percent_rank () → double precision | 返回当前行的相对排名,即 (rank - 1) / (总分区行数 - 1)。因此,该值的范围为 0 到 1(包括 0 和 1)。 |
cume_dist () → double precision | 返回累积分布,即(当前行之前或与当前行相同的行数)/(总分区行数)。因此,该值的范围为 1/N 到 1。 |
ntile ( num_buckets integer ) → integer | 返回一个整数,范围从 1 到参数值,尽可能平均地划分分区。 |
lag ( value anycompatible [ , offset integer [ , default anycompatible ] ] ) → anycompatible | 返回在分区内当前行之前的第 offset 行处评估的 value;如果没有这样的行,则返回 default(必须与 value 兼容的类型)。offset 和 default 都是相对于当前行进行评估的。如果省略,则 offset 默认为 1,default 默认为 NULL。 |
lead ( value anycompatible [ , offset integer [ , default anycompatible ] ] ) → anycompatible | 返回在分区内当前行之后的第 offset 行处评估的 value;如果没有这样的行,则返回 default(必须与 value 兼容的类型)。offset 和 default 都是相对于当前行进行评估的。如果省略,则 offset 默认为 1,default 默认为 NULL。 |
first_value ( value anyelement ) → anyelement | 返回在窗口帧的第一行评估的 value。 |
last_value ( value anyelement ) → anyelement | 返回在窗口帧的最后一行评估的 value。 |
nth_value ( value anyelement, n integer ) → anyelement | 返回在窗口帧的第 n 行(从 1 开始计数)评估的 value;如果没有这样的行,则返回 NULL。 |
表 通用窗口函数中列出的所有函数都依赖于与相关窗口定义的 ORDER BY 子句指定的排序顺序。仅考虑 ORDER BY 列时不是唯一的行被称为对等行。四个排名函数(包括 cume_dist)被定义为对同一对等行组的所有行给出相同的答案。
请注意,first_value、last_value 和 nth_value 仅考虑窗口帧内的行,默认情况下包含从分区开始到当前行的最后一个对等行的行。这可能会给 last_value 和有时也会给 nth_value 带来无用的结果。您可以通过向 OVER 子句添加适当的帧规范(RANGE、ROWS 或 GROUPS)来重新定义帧。
当聚合函数用作窗口函数时,它会聚合当前行窗口帧内的行。使用 ORDER BY 和默认窗口帧定义的聚合会产生一种“运行总和”类型的行为,这可能是所需的,也可能不是所需的。要在整个分区上进行聚合,请省略 ORDER BY 或使用 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING。其他帧规范可用于获得其他效果。
注意
SQL 标准为 lead、lag、first_value、last_value 和 nth_value 定义了一个RESPECT NULLS或IGNORE NULLS选项。这在 UXsinoDB 中未实现:行为始终与标准的默认行为相同,即RESPECT NULLS。同样,标准的FROM FIRST或FROM LAST选项对于nth_value未实现:仅支持默认的FROM FIRST行为。(您可以通过反转ORDER BY排序来实现FROM LAST的结果。)
表 分析窗口函数
| 函数 | 参数类型 | 返回类型 | 描述 |
|---|---|---|---|
ratio_to_report (expr) over (partition_clause) | float8 | numeric | 求当前值在其组内所占的比率 |
表中 ratio_to_report 函数 over 子句中不支持指定 order by 及其他窗口子句,在 uxdb 运行模式为 oracle 时,当列插入值为空串时,函数结果为空,其他模式不支持。下面是一些例子:
-- RATIO_TO_REPORT (expr) OVER ([partition_clause])
CREATE TABLE EMPLOYEES(ID INT, NAME CHAR(10), SALARY INT, CATEGORY CHAR(1));
INSERT INTO EMPLOYEES VALUES (1, 'Khoo', 3100, 'a');
INSERT INTO EMPLOYEES VALUES (2, 'Baida', 2900, 'a');
INSERT INTO EMPLOYEES VALUES (3, 'Tobias', 2800, 'a');
INSERT INTO EMPLOYEES VALUES (4, 'Himuro', 2600, 'b');
INSERT INTO EMPLOYEES VALUES (5, 'Himuro', 2500, 'b');
INSERT INTO EMPLOYEES VALUES (6, 'Jore', 0, 'c');
INSERT INTO EMPLOYEES VALUES (7, 'Bob', null, 'd');
-- 查询每个员工工资占所有的工资比例
SELECT ID, NAME, SALARY, RATIO_TO_REPORT(SALARY) OVER () AS RR FROM EMPLOYEES;
id | name | salary | rr
----+------------+--------+----------------------------
1 | Khoo | 3100 | 0.22302158273381294964
2 | Baida | 2900 | 0.20863309352517985612
3 | Tobias | 2800 | 0.20143884892086330935
4 | Himuro | 2600 | 0.18705035971223021583
5 | Himuro | 2500 | 0.17985611510791366906
6 | Jore | 0 | 0.000000000000000000000000
7 | Bob | |
(7 rows)
-- 查询每个员工工资占所在部门的工资比例
SELECT ID, NAME, SALARY,CATEGORY, RATIO_TO_REPORT(SALARY) OVER (PARTITION BY CATEGORY) FROM EMPLOYEES;
id | name | salary | category | ratio_to_report
----+------------+--------+----------+------------------------
1 | Khoo | 3100 | a | 0.35227272727272727273
2 | Baida | 2900 | a | 0.32954545454545454545
3 | Tobias | 2800 | a | 0.31818181818181818182
4 | Himuro | 2600 | b | 0.50980392156862745098
5 | Himuro | 2500 | b | 0.49019607843137254902
6 | Jore | 0 | c |
7 | Bob | | d |
(7 rows)
-- expr 为常量
SELECT ID, NAME, SALARY,CATEGORY, RATIO_TO_REPORT(1000) OVER (PARTITION BY CATEGORY) FROM EMPLOYEES;
id | name | salary | category | ratio_to_report
----+------------+--------+----------+------------------------
1 | Khoo | 3100 | a | 0.33333333333333333333
2 | Baida | 2900 | a | 0.33333333333333333333
3 | Tobias | 2800 | a | 0.33333333333333333333
4 | Himuro | 2600 | b | 0.50000000000000000000
5 | Himuro | 2500 | b | 0.50000000000000000000
6 | Jore | 0 | c | 1.00000000000000000000
7 | Bob | | d | 1.00000000000000000000
(7 rows)
-- 入参为列表达式
SELECT ID, NAME, SALARY,CATEGORY, RATIO_TO_REPORT(SALARY+100) OVER (PARTITION BY CATEGORY) FROM EMPLOYEES;
id | name | salary | category | ratio_to_report
----+------------+--------+----------+------------------------
1 | Khoo | 3100 | a | 0.35164835164835164835
2 | Baida | 2900 | a | 0.32967032967032967033
3 | Tobias | 2800 | a | 0.31868131868131868132
4 | Himuro | 2600 | b | 0.50943396226415094340
5 | Himuro | 2500 | b | 0.49056603773584905660
6 | Jore | 0 | c | 1.00000000000000000000
7 | Bob | | d |
(7 rows)
SELECT ID, NAME, SALARY,CATEGORY, RATIO_TO_REPORT(SALARY*100) OVER (PARTITION BY CATEGORY) FROM EMPLOYEES;
id | name | salary | category | ratio_to_report
----+------------+--------+----------+------------------------
1 | Khoo | 3100 | a | 0.35227272727272727273
2 | Baida | 2900 | a | 0.32954545454545454545
3 | Tobias | 2800 | a | 0.31818181818181818182
4 | Himuro | 2600 | b | 0.50980392156862745098
5 | Himuro | 2500 | b | 0.49019607843137254902
6 | Jore | 0 | c |
7 | Bob | | d |
(7 rows)
-- 指定 ORDER BY 子句
SELECT NAME, SALARY,CATEGORY, RATIO_TO_REPORT(SALARY) OVER (PARTITION BY CATEGORY ORDER BY NAME ) AS TT FROM EMPLOYEES;
ERROR: ORDER BY not allowed here
LINE 1: ...TIO_TO_REPORT(SALARY) OVER (PARTITION BY CATEGORY ORDER BY N...
^
-- 指定 windows 子句
SELECT NAME, SALARY,CATEGORY, RATIO_TO_REPORT(SALARY) OVER (PARTITION BY CATEGORY RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS TT FROM EMPLOYEES;
ERROR: The analysis function [RATIO_TO_REPORT] does not allow window definition
SELECT NAME, SALARY,CATEGORY, RATIO_TO_REPORT(SALARY) OVER (PARTITION BY CATEGORY ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS TT FROM EMPLOYEES;
ERROR: The analysis function [RATIO_TO_REPORT] does not allow window definition
SELECT NAME, SALARY,CATEGORY, RATIO_TO_REPORT(SALARY) OVER (PARTITION BY CATEGORY ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS TT FROM EMPLOYEES;
ERROR: ORDER BY not allowed here
LINE 1: ...TIO_TO_REPORT(SALARY) OVER (PARTITION BY CATEGORY ORDER BY I...
^
DROP TABLE EMPLOYEES;
--- 空串测试
CREATE TABLE EMPLOYEES(ID INT, NAME CHAR(10), SALARY VARCHAR(5), CATEGORY CHAR(1));
INSERT INTO EMPLOYEES VALUES (1, 'Khoo', 3100, 'a');
INSERT INTO EMPLOYEES VALUES (2, 'Baida',2900, 'a');
INSERT INTO EMPLOYEES VALUES (3, 'Tobias',2800, 'a');
INSERT INTO EMPLOYEES VALUES (4, 'Himuro',2600, 'b');
INSERT INTO EMPLOYEES VALUES (5, 'Himuro',2500, 'b');
INSERT INTO EMPLOYEES VALUES (6, 'Jore', '', 'c');
-- 仅 oracle 模式下正确执行,其他模式下报错
SELECT ID, NAME, SALARY, RATIO_TO_REPORT(SALARY) OVER () AS RR FROM EMPLOYEES;
ERROR: invalid input syntax for type double precision: ""
SELECT ID, NAME, SALARY,CATEGORY, RATIO_TO_REPORT(SALARY) OVER (PARTITION BY CATEGORY) FROM EMPLOYEES;
ERROR: invalid input syntax for type double precision: ""
DROP TABLE EMPLOYEES;
-- expr 嵌套其他内置函数
CREATE TABLE T_SALARY(
F_DEPART VARCHAR2(20),
F_EMP VARCHAR2(20),
F_SALARY INTEGER
);
TRUNCATE TABLE T_SALARY;
-- 插入测试数据
INSERT INTO T_SALARY(F_DEPART, F_EMP, F_SALARY)
SELECT '信息管理部','张三',10000 FROM DUAL
UNION ALL
SELECT '信息管理部','李四',2000 FROM DUAL
UNION ALL
SELECT '人力资源部','王五',3000 FROM DUAL
UNION ALL
SELECT '人力资源部','赵六',10000 FROM DUAL;
-- 查询每个员工占所在部门的工资比例
SELECT F_DEPART,F_EMP,F_SALARY,SUM(F_SALARY) OVER(PARTITION BY F_DEPART) SUM_SALARY,
RATIO_TO_REPORT(F_SALARY) OVER(PARTITION BY F_DEPART) RATIO_SALARY
FROM T_SALARY;
f_depart | f_emp | f_salary | sum_salary | ratio_salary
------------+-------+----------+------------+------------------------
人力资源部 | 王五 | 3000 | 13000 | 0.23076923076923076923
人力资源部 | 赵六 | 10000 | 13000 | 0.76923076923076923077
信息管理部 | 张三 | 10000 | 12000 | 0.83333333333333333333
信息管理部 | 李四 | 2000 | 12000 | 0.16666666666666666667
(4 rows)
-- 递归查询员工占所在部门的百分比, 以及部门所占公司的工资比例.
SELECT F_DEPART,F_EMP,F_SALARY,G1,
SUM(F_SALARY) OVER(PARTITION BY DECODE(G1, 0, F_DEPART, NULL), G1) SUM_SALARY,
RATIO_TO_REPORT(F_SALARY) OVER(PARTITION BY DECODE(G1, 0, F_DEPART, NULL), G1) R_SALARY
FROM
( SELECT F_DEPART,F_EMP, SUM(F_SALARY) F_SALARY,
GROUPING(F_DEPART) + GROUPING(F_EMP) G1
FROM T_SALARY GROUP BY ROLLUP(F_DEPART, F_EMP)
) T;
f_depart | f_emp | f_salary | g1 | sum_salary | r_salary
------------+-------+----------+----+------------+------------------------
人力资源部 | 赵六 | 10000 | 0 | 13000 | 0.76923076923076923077
人力资源部 | 王五 | 3000 | 0 | 13000 | 0.23076923076923076923
信息管理部 | 张三 | 10000 | 0 | 12000 | 0.83333333333333333333
信息管理部 | 李四 | 2000 | 0 | 12000 | 0.16666666666666666667
信息管理部 | | 12000 | 1 | 25000 | 0.48000000000000000000
人力资源部 | | 13000 | 1 | 25000 | 0.52000000000000000000
| | 25000 | 2 | 25000 | 1.00000000000000000000
(7 rows)
--- 由于分析函数可以使用普通函数的结果作为 expr 参数
SELECT F_DEPART, F_EMP, SUM(F_SALARY) F_SALARY,
SUM(SUM(F_SALARY)) OVER (PARTITION BY DECODE(GROUPING(F_DEPART) + GROUPING(F_EMP), 0, F_DEPART, NULL),
GROUPING(F_DEPART) + GROUPING(F_EMP)) SUM_SALARY,
RATIO_TO_REPORT(SUM(F_SALARY)) OVER(PARTITION BY DECODE(GROUPING(F_DEPART) + GROUPING(F_EMP), 0, F_DEPART, NULL),
GROUPING(F_DEPART) + GROUPING(F_EMP)) R_SALARY,
GROUPING(F_DEPART) + GROUPING(F_EMP) G1
FROM T_SALARY GROUP BY ROLLUP(F_DEPART, F_EMP);
f_depart | f_emp | f_salary | sum_salary | r_salary | g1
------------+-------+----------+------------+------------------------+----
人力资源部 | 赵六 | 10000 | 13000 | 0.76923076923076923077 | 0
人力资源部 | 王五 | 3000 | 13000 | 0.23076923076923076923 | 0
信息管理部 | 张三 | 10000 | 12000 | 0.83333333333333333333 | 0
信息管理部 | 李四 | 2000 | 12000 | 0.16666666666666666667 | 0
信息管理部 | | 12000 | 25000 | 0.48000000000000000000 | 1
人力资源部 | | 13000 | 25000 | 0.52000000000000000000 | 1
| | 25000 | 25000 | 1.00000000000000000000 | 2
(7 rows)
DROP TABLE T_SALARY;
-- #175421 & #175423
CREATE TABLE UXDBC_ORACLE_REPORT_0001_TABLE01(ID INT,NAME VARCHAR(15),GRADE VARCHAR2(10),SALARY DOUBLE);
INSERT INTO UXDBC_ORACLE_REPORT_0001_TABLE01 VALUES(1,'zhangsan','77.5',3500);
INSERT INTO UXDBC_ORACLE_REPORT_0001_TABLE01 VALUES(2,'lisi','68',3500);
INSERT INTO UXDBC_ORACLE_REPORT_0001_TABLE01 VALUES(3,'wangwu','26',2000);
INSERT INTO UXDBC_ORACLE_REPORT_0001_TABLE01 VALUES(4,'wanhan','65.3',4500);
INSERT INTO UXDBC_ORACLE_REPORT_0001_TABLE01 VALUES(5,'xiaoming','82.5',3000);
INSERT INTO UXDBC_ORACLE_REPORT_0001_TABLE01 VALUES(6,'liming','85',4500);
SELECT NAME,RATIO_TO_REPORT(ROW_NUMBER() OVER(PARTITION BY SALARY)) OVER(PARTITION BY SALARY) AS RR FROM UXDBC_ORACLE_REPORT_0001_TABLE01;
ERROR: window function calls cannot be nested
LINE 1: SELECT NAME,RATIO_TO_REPORT(ROW_NUMBER() OVER(PARTITION BY S...
^
SELECT NAME,RATIO_TO_REPORT(ROW_NUMBER() OVER(PARTITION BY SALARY)) OVER(PARTITION BY SALARY ORDER BY ID) AS RR FROM UXDBC_ORACLE_REPORT_0001_TABLE01;
ERROR: window function calls cannot be nested
LINE 1: SELECT NAME,RATIO_TO_REPORT(ROW_NUMBER() OVER(PARTITION BY S...
^
SELECT NAME,RATIO_TO_REPORT(GRADE) OVER(PARTITION BY SALARY ORDER BY ID) AS RR FROM UXDBC_ORACLE_REPORT_0001_TABLE01;
ERROR: ORDER BY not allowed here
LINE 1: ...E,RATIO_TO_REPORT(GRADE) OVER(PARTITION BY SALARY ORDER BY I...
^
SELECT NAME,RATIO_TO_REPORT(-4.94065645841246544E-324) OVER(PARTITION BY SALARY) FROM UXDBC_ORACLE_REPORT_0001_TABLE01 ORDER BY 1;
name | ratio_to_report
----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
liming | 0.50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
lisi | 0.50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
wangwu | 1.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
wanhan | 0.50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
xiaoming | 1.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
zhangsan | 0.50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
(6 rows)
DROP TABLE IF EXISTS UXDBC_ORACLE_REPORT_0001_TABLE01 CASCADE;
24. 子查询表达式
本节介绍了在 UXsinoDB 中可用的符合 SQL 标准的子查询表达式。本节中记录的所有表达式形式都返回布尔(真/假)结果。
24.1. EXISTS
EXISTS (subquery)
EXISTS 的参数是任意的 SELECT 语句或子查询。子查询将被评估以确定它是否返回任何行。如果它返回至少一行,则 EXISTS 的结果是“true”;如果子查询没有返回行,则 EXISTS 的结果是“false”。
子查询可以引用周围查询的变量,在子查询的任何一次评估期间将作为常量。
子查询通常只会执行到确定是否返回至少一行,而不是完全执行。编写具有副作用(例如调用序列函数)的子查询是不明智的,因为副作用的发生可能是不可预测的。由于结果仅取决于是否返回任何行,而不是这些行的内容,因此子查询的输出列表通常不重要。一个常见的编码约定是以 EXISTS(SELECT 1 WHERE ...) 的形式编写所有 EXISTS 测试。然而,有一些例外,比如使用 INTERSECT 的子查询。这个简单的例子类似于在 col2 上的内连接,但对于每个 tab1 行,它最多产生一行输出,即使有多个匹配的 tab2 行:
SELECT col1
FROM tab1
WHERE EXISTS (SELECT 1 FROM tab2 WHERE col2 = tab1.col2);
24.2. IN
expression IN (subquery)
右侧是一个带括号的子查询,它必须返回恰好一列。左侧表达式被评估并与子查询结果的每一行进行比较。如果找到任何相等的子查询行,则 IN 的结果为“true”。如果没有找到相等的行(包括子查询不返回任何行的情况),则结果为“false”。
请注意,如果左侧表达式产生 null,或者如果没有相等的右侧值并且至少有一个右侧行产生 null,则 IN 构造的结果将为 null,而不是 false。这符合 SQL 对 null 值的布尔组合的正常规则。
与 EXISTS 一样,假设子查询将被完全评估是不明智的。
row_constructor IN (subquery)
这种形式的 IN 的左侧是一个行构造函数。右侧是一个带括号的子查询,它必须返回与左侧行中的表达式数量完全相同的列。左侧表达式按行进行评估并与子查询结果的每一行进行比较。如果找到任何相等的子查询行,则 IN 的结果为“true”。如果没有找到相等的行(包括子查询不返回任何行的情况),则结果为“false”。
通常,行中的 null 值按 SQL 布尔表达式的正常规则进行组合。如果两行的所有对应成员都是非 null 且相等,则认为这两行相等;如果任何对应成员是非 null 且不相等,则这两行不相等;否则该行比较的结果为未知(null)。如果所有每行结果都是不相等或 null,并且至少有一个 null,则 IN 的结果为 null。
24.3. NOT IN
expression NOT IN (subquery)
右侧是一个带括号的子查询,它必须返回与左侧表达式相同的列。如果找到任何不相等的子查询行,则 NOT IN 的结果为“true”。如果没有找到不相等的行(包括子查询不返回任何行的情况),则结果为“false”。子查询必须返回恰好一列。左侧表达式将被评估并与子查询结果的每一行进行比较。如果只找到不相等的子查询行(包括子查询返回零行的情况),则 NOT IN 的结果为“true”。如果找到任何相等的行,则结果为“false”。
请注意,如果左侧表达式产生 null,或者如果没有相等的右侧值并且至少有一个右侧行产生 null,则 NOT IN 构造的结果将为 null,而不是 true。这符合 SQL 对 null 值的布尔组合的正常规则。
与 EXISTS 一样,假设子查询将被完全评估是不明智的。
这种形式的 NOT IN 的左侧是一个行构造。右侧是一个带括号的子查询,它必须返回与左侧行中的表达式数量完全相同的列数。左侧表达式将按行进行评估并与子查询结果的每一行进行比较。如果只找到不相等的子查询行(包括子查询返回零行的情况),则 NOT IN 的结果为“true”。如果找到任何相等的行,则结果为“false”。
通常,行中的 null 值按 SQL 布尔表达式的正常规则组合。如果所有的每行结果都是不相等或 null,且至少有一个 null,则 NOT IN 的结果为 null。
24.4. ANY/SOME
expression operator ANY (subquery)
expression operator SOME (subquery)
右侧是一个带括号的子查询,它必须返回恰好一列。左侧表达式将被评估并使用给定的操作符与子查询结果的每一行进行比较,该操作符必须产生布尔结果。如果获得任何 true 结果,则 ANY 的结果为“true”。如果找不到 true 结果(包括子查询返回零行的情况),则结果为“false”。
SOME 是 ANY 的同义词。IN 等同于 = ANY。
请注意,如果没有成功,并且至少有一个右侧行产生操作符结果的 null,则 ANY 构造的结果将为 null,而不是 false。这符合 SQL 对 null 值的布尔组合的正常规则。
与 EXISTS 一样,假设子查询将被完全评估是不明智的。
row_constructor operator ANY (subquery)
row_constructor operator SOME (subquery)
这种形式的 ANY 的左侧是一个行构造器。右侧是一个带括号的子查询,它必须返回与左侧行中的表达式数量完全相同的列数。左侧表达式按行与子查询结果的每一行进行评估和比较,使用给定的 operator。如果比较对于任何子查询行返回 true,则 ANY 的结果为“true”。如果比较对于每个子查询行都返回 false(包括子查询不返回任何行的情况),则结果为“false”。如果没有与子查询行的比较返回 true,并且至少有一个比较返回 NULL,则结果为 NULL。
有关行构造器比较的含义的详细信息,请参见行构造函数比较。
expression operator ANY (expression1, expression2...)
expression operator SOME (expression1, expression2...)
左边表达式被计算并且使用给出的操作符并与右边的每个表达式进行比较,如果获得任何真值结果,那么 ANY 的结果就是“真”,如果没有找到真值结果,那么结果是“假”。
SOME 是 ANY 的同义词。
24.5. ALL
expression operator ALL (subquery)
右侧是一个带括号的子查询,它必须返回恰好一列。左侧表达式按行与子查询结果的每一行进行评估和比较,使用给定的 operator,该操作符必须产生布尔结果。如果所有行都返回 true(包括子查询不返回任何行的情况),则 ALL 的结果为“true”。如果找到任何 false 结果,则结果为“false”。如果没有与子查询行的比较返回 false,并且至少有一个比较返回 NULL,则结果为 NULL。
NOT IN 等同于 <> ALL。
与 EXISTS 一样,假设子查询将被完全评估是不明智的。
row_constructor operator ALL (subquery)
这种形式的 ALL 的左侧是一个行构造器。右侧是一个带括号的子查询,它必须返回与左侧行中的表达式数量完全相同的列数。左侧表达式按行与子查询结果的每一行进行评估和比较,使用给定的 operator。如果比较对于所有子查询行都返回 true(包括子查询不返回任何行的情况),则 ALL 的结果为“true”。如果比较对于任何子查询行返回 false,则结果为“false”。如果没有与子查询行的比较返回 false,并且至少有一个比较返回 NULL,则结果为 NULL。
有关行构造比较的详细信息,请参见行构造函数比较。
expression operator ALL (expression1, expression2...)
左边表达式被计算并且使用给出的操作符并与右边的每个表达式进行比较,这个操作符必须得到布尔结果。只有所有的表达式比较结果为真,则返回“真”,否则返回为“假”。
24.6. 单行比较
row_constructor operator ( subquery )
左侧是行构造,右侧是带括号的子查询,必须返回与左侧行中的表达式数量完全相同的列。此外,子查询不能返回多行。(如果返回零行,则结果视为 null。)左侧被逐行评估并与单个子查询结果行进行比较。
有关行构造比较的详细信息,请参见行构造函数比较。
25. 行和数组比较
本节介绍了几种用于对值组进行多重比较的专用结构。这些形式在语法上与前一节的子查询形式相关,但不涉及子查询。涉及数组子表达式的形式是 UXsinoDB 扩展;其余的是 SQL 兼容的。本节文档中记录的所有表达式形式都返回布尔(真/假)结果。
25.1. IN
expression IN (value [, ...])
右侧是一个括号括起来的标量表达式列表。如果左侧表达式的值等于列表中的任何一个值,则结果为“true”,否则为“false”。如果列表为空,则结果为“false”。
expression = value1
OR
expression = value2
OR
...
注意,如果左侧表达式生成 null,或者如果没有相等的右侧值,并且至少有一个右侧表达式生成 null,则 IN 结构的结果将为 null,而不是 false。这符合 SQL 对空值的布尔组合的一般规则。
25.2. NOT IN
expression NOT IN (value [, ...])
右侧是一个括号括起来的标量表达式列表。如果左侧表达式的结果与所有右侧表达式都不相等,则结果为 true。这是一个简写符号表示:
expression <> value1
AND
expression <> value2
AND
...
请注意,如果左侧表达式产生 null,或者如果没有相等的右侧值且至少有一个右侧表达式产生 null,则 NOT IN 构造的结果将是 null,而不是 true,这可能会让初学者感到困惑。这符合 SQL 对 null 值的布尔组合的正常规则。
提示
在所有情况下,x NOT IN y等价于NOT (x IN y)。然而,当使用NOT IN时,null 值更容易使初学者犯错。如果可能的话,最好以肯定的方式表达您的条件。
25.3. ANY/SOME (array)
expression operator ANY (array expression)
expression operator SOME (array expression)
右侧是一个括号括起来的表达式,必须产生一个数组值。左侧表达式将被评估,并使用给定的 operator 与数组的每个元素进行比较,该操作符必须产生一个布尔结果。如果获得任何 true 结果,则 ANY 的结果为 true。如果找不到 true 结果(包括数组没有元素的情况),则结果为 false。
如果数组表达式产生 null 数组,则 ANY 的结果将为 null。如果左侧表达式产生 null,则 ANY 的结果通常为 null(尽管非严格比较操作符可能会产生不同的结果)。此外,如果右侧数组包含任何 null 元素且未获得 true 比较结果,则 ANY 的结果将为 null,而不是 false(假设使用严格比较操作符)。这符合 SQL 对 null 值的布尔组合的正常规则。
SOME 是 ANY 的同义词。
25.4. ALL(数组)
expression operator ALL (array expression)
右侧是一个括号内的表达式,必须产生一个数组值。左侧表达式被评估并使用给定的 operator 与数组的每个元素进行比较,该操作符必须产生一个布尔值结果。如果所有比较都为真(包括数组没有元素的情况),则 ALL 的结果为“true”。如果发现任何假结果,则结果为“false”。
如果数组表达式产生空数组,则 ALL 的结果将为 null。如果左侧表达式产生 null,则 ALL 的结果通常为 null(尽管非严格比较操作符可能产生不同的结果)。此外,如果右侧数组包含任何 null 元素并且没有获得 false 比较结果,则 ALL 的结果将为 null,而不是 true(再次假设严格的比较操作符)。这符合 SQL 对 null 值的布尔组合的正常规则。
25.5. 行构造函数比较
row_constructor operator row_constructor
每个侧面都是行构造函数。两个行值必须具有相同数量的字段。每个侧面都被评估并且它们按行进行比较。当 operator 为 =、<>、<、<=、> 或 >= 时,允许行构造函数比较。每个行元素必须是具有默认 B-tree 操作符类的类型,否则尝试的比较可能会生成错误。
注意
如果使用早期列解决比较,则可能不会发生与元素数量或类型相关的错误。
= 和 <> 情况与其他情况略有不同。如果所有对应成员都是非 null 且相等,则认为两个行相等;如果任何对应成员都是非 null 且不相等,则行不相等;否则行比较的结果未知(null)。
对于 <、<=、> 和 >= 情况,行元素从左到右进行比较,一旦找到不相等或 null 对的元素即停止。如果这对元素中的任何一个是 null,则行比较的结果未知(null);否则,比较这对元素确定结果。例如,ROW(1,2,NULL) < ROW(1,3,0) 产生 true,而不是 null,因为第三对元素不被考虑。
注意
在 UXsinoDB 之前版本,<、<=、>和>=的情况没有按照 SQL 规范处理。例如,像ROW(a,b) < ROW(c,d)这样的比较被实现为a < c AND b < d,而正确的行为应该等价于a < c OR (a = c AND b < d)。
row_constructor IS DISTINCT FROM row_constructor
这个结构类似于 <> 行比较,但它不会对空输入产生空值。相反,任何空值都被视为与任何非空值不相等(不同),任何两个空值都被视为相等(不同)。因此,结果将是真或假,永远不会是空值。
row_constructor IS NOT DISTINCT FROM row_constructor
这个结构类似于 = 行比较,但它不会对空输入产生空值。相反,任何空值都被视为与任何非空值不相等(不同),任何两个空值都被视为相等(不同)。因此,结果将始终为真或假,永远不会是空值。
25.6. 复合类型比较
record operator record
SQL 规范要求行比较在结果依赖于比较两个空值或一个空值和一个非空值时返回 NULL。当比较两个行构造函数的结果(如行构造函数比较)或将行构造函数与子查询的输出进行比较(如子查询表达式)时,UXsinoDB 才会这样做。在其他上下文中,当比较两个复合类型值时,两个空字段值被视为相等,而空值被视为大于非空值。这是为了具有一致的复合类型排序和索引行为而必需的。
每个侧面都被评估,然后它们被逐行比较。当 operator 是 =、<>、<、<=、> 或 >=,或者具有类似于这些的语义时,允许复合类型比较。(具体来说,如果操作符是 B-tree 操作符类的成员,或者是 B-tree 操作符类的 = 成员的否定,则操作符可以是行比较操作符。)上述操作符的默认行为与行构造函数的 IS [ NOT ] DISTINCT FROM 相同(请参见行构造函数比较)。
为了支持包括没有默认 B-tree 操作符类的元素的行匹配,为复合类型比较定义了以下操作符:*=、*<>、*<、*<=、*> 和 *>=。这些操作符比较两行的内部二进制表示。两行可能具有不同的二进制表示,即使它们在逻辑上相等。尽管使用等号操作符比较两行是正确的,但在这些比较操作符下的行的排序是确定性的,但不具有其他有意义的含义。这些操作符在材料化视图中被内部使用,可能对其他专业用途(例如复制和 B-Tree 去重)有用。它们不打算用于编写查询,尽管可能有一些特殊情况。
26. 集合返回函数
本节介绍可能返回多行的函数。这个类别中最常用的函数是系列生成函数,详见表 系列生成函数和表 下标生成函数。其他更专业的集合返回函数在本手册的其他地方描述。
| 函数 | 描述 |
|---|---|
generate_series ( start integer, stop integer [ , step integer ] ) → setof integergenerate_series ( start bigint, stop bigint [ , step bigint ] ) → setof bigintgenerate_series ( start numeric, stop numeric [ , step numeric ] ) → setof numeric | 生成从 start 到 stop 的一系列值,步长为 step。默认步长为 1。 |
generate_series ( start timestamp, stop timestamp, step interval ) → setof timestampgenerate_series ( start timestamp with time zone, stop timestamp with time zone, step interval ) → setof timestamp with time zone | 生成从 start 到 stop 的一系列值,步长为 step。 |
当 step 为正数时,如果 start 大于 stop,则返回零行。相反,当 step 为负数时,如果 start 小于 stop,则返回零行。如果任何输入为 NULL,也会返回零行。step 为零是错误的。以下是一些示例:
SELECT * FROM generate_series(2,4);
generate_series
-----------------
2
3
4
(3 rows)
SELECT * FROM generate_series(5,1,-2);
generate_series
-----------------
5
3
1
(3 rows)
SELECT * FROM generate_series(4,3);
generate_series
-----------------
(0 rows)
SELECT generate_series(1.1, 4, 1.3);
generate_series
-----------------
1.1
2.4
3.7
(3 rows)
-- this example relies on the date-plus-integer operator:
SELECT current_date + s.a AS dates FROM generate_series(0,14,7) AS s(a);
dates
------------
2004-02-05
2004-02-12
2004-02-19
(3 rows)
SELECT * FROM generate_series('2008-03-01 00:00'::timestamp,
'2008-03-04 12:00', '10 hours');
generate_series
---------------------
2008-03-01 00:00:00
2008-03-01 10:00:00
2008-03-01 20:00:00
2008-03-02 06:00:00
2008-03-02 16:00:00
2008-03-03 02:00:00
2008-03-03 12:00:00
2008-03-03 22:00:00
2008-03-04 08:00:00
(9 rows)
| 函数 | 描述 |
|---|---|
generate_subscripts ( array anyarray, dim integer ) → setof integer | 生成给定数组第 dim 维度的有效下标组成的一系列值。 |
generate_subscripts ( array anyarray, dim integer, reverse boolean ) → setof integer | 生成由给定数组的第 dim 维的有效下标组成的系列。当 reverse 为真时,以相反的顺序返回系列。 |
generate_subscripts 是一个方便的函数,用于生成给定数组的指定维度的有效下标集合。对于没有请求的维度的数组或任何输入为 NULL 的数组,将返回零行。以下是一些示例:
-- 基本用法:
SELECT generate_subscripts('{NULL,1,NULL,2}'::int[], 1) AS s;
s
---
1
2
3
4
(4 rows)
-- 显示数组、下标和下标值需要使用子查询:
SELECT * FROM arrays;
a
--------------------
{-1,-2}
{100,200,300}
(2 rows)
SELECT a AS array, s AS subscript, a[s] AS value
FROM (SELECT generate_subscripts(a, 1) AS s, a FROM arrays) foo;
array | subscript | value
---------------+-----------+-------
{-1,-2} | 1 | -1
{-1,-2} | 2 | -2
{100,200,300} | 1 | 100
{100,200,300} | 2 | 200
{100,200,300} | 3 | 300
(5 rows)
-- 展开一个二维数组:
CREATE OR REPLACE FUNCTION unnest2(anyarray)
RETURNS SETOF anyelement AS $$
select $1[i][j]
from generate_subscripts($1,1) g1(i),
generate_subscripts($1,2) g2(j);
$$ LANGUAGE sql IMMUTABLE;
CREATE FUNCTION
SELECT * FROM unnest2(ARRAY[[1,2],[3,4]]);
unnest2
---------
1
2
3
4
(4 rows)
当 FROM 子句中的函数后缀为 WITH ORDINALITY 时,将在函数的输出列后附加一个 bigint 列,该列从 1 开始,每行递增 1。这在返回集的函数(如 unnest())的情况下最为有用。
-- 带序号的返回集函数:
SELECT * FROM ux_ls_dir('.') WITH ORDINALITY AS t(ls,n);
ls | n
-----------------+----
ux_serial | 1
ux_twophase | 2
uxmaster.opts | 3
ux_notify | 4
uxsinodb.conf | 5
ux_tblspc | 6
logfile | 7
base | 8
uxmaster.pid | 9
ux_ident.conf | 10
global | 11
ux_xact | 12
ux_snapshots | 13
ux_multixact | 14
UX_VERSION | 15
ux_wal | 16
ux_hba.conf | 17
ux_stat_tmp | 18
ux_subtrans | 19
(19 rows)
27. 系统信息函数和操作符
表 会话信息函数显示了提取会话和系统信息的几个函数。
除了本节列出的函数外,还有一些与统计系统相关的函数也提供系统信息。
| 函数 | 描述 | 示例 |
|---|---|---|
current_catalog → namecurrent_database () → name | 返回当前数据库的名称。(在 SQL 标准中,数据库称为“目录”,因此 current_catalog 是标准的拼写方式。) | |
current_query () → text | 返回当前正在执行的查询的文本,由客户端提交(可能包含多个语句)。 | |
current_role → name | 这相当于 current_user。 | |
current_schema → namecurrent_schema () → name | 返回搜索路径中第一个模式的名称(如果搜索路径为空,则返回空值)。这是将用于创建任何未指定目标模式的表或其他命名对象的模式。 | |
current_schemas ( include_implicit boolean ) → name[] | 以它们的优先顺序返回当前有效搜索路径中所有模式的名称数组。(省略了当前 search_path 设置中不对应于现有可搜索模式的项。)如果布尔参数为 true,则包括隐式搜索的系统模式,如 ux_catalog 在结果中。 | |
current_user → name | 返回当前执行上下文的用户名。 | |
database() → varchar2 | 以一个字符串的形式返回当前数据库集簇下的默认模式名(在跨模式调用该 database() 函数时,返回结果与当前调用上下文的模式有关,而与定义例程的模式无关)。 | |
inet_client_addr () → inet | 返回当前客户端的 IP 地址,如果当前连接是通过 Unix 域套接字进行的,则返回 NULL。 | |
inet_client_port () → integer | 返回当前客户端的 IP 端口号,如果当前连接是通过 Unix 域套接字进行的,则返回 NULL。 | |
inet_server_addr () → inet | 返回服务器接受当前连接的 IP 地址,如果当前连接是通过 Unix 域套接字进行的,则返回 NULL。 | |
inet_server_port () → integer | 返回服务器接受当前连接的 IP 端口号,如果当前连接是通过 Unix 域套接字进行的,则返回 NULL。 | |
sys_context('context','parameter'[, length]) → text | 用于获取环境上下文信息或判断当前会话角色。 | |
ux_backend_pid () → integer | 返回附加到当前会话的服务器进程的进程 ID。 | |
ux_blocking_pids ( integer ) → integer[] | 返回阻止具有指定进程 ID 的服务器进程的会话的进程 ID 数组。获取锁,如果没有这样的服务器进程或者它没有被阻塞,则返回一个空数组。如果一个服务器进程持有一个与被阻塞进程的锁请求冲突的锁(硬阻塞),或者正在等待一个与被阻塞进程的锁请求冲突的锁,并且在等待队列中排在它前面(软阻塞),那么它就会阻塞另一个服务器进程。在使用并行查询时,结果总是列出客户端可见的进程 ID(即 ux_backend_pid 的结果),即使实际的锁是由子工作进程持有或等待的。因此,结果中可能会有重复的 PID。还要注意,当准备事务持有冲突锁时,它将由零进程 ID 表示。频繁调用此函数可能会对数据库性能产生一些影响,因为它需要短时间内独占锁管理器的共享状态。 | |
ux_conf_load_time () → timestamp with time zone | 返回服务器配置文件最后加载的时间。如果当前会话在此时仍然活动,则这将是会话本身重新读取配置文件的时间(因此在不同的会话中读取会有所不同)。否则,它是 uxmaster 进程重新读取配置文件的时间。 | |
ux_current_logfile ( [ text ] ) → text | 返回日志收集器当前使用的日志文件的路径名。路径包括 log_directory 目录和单个日志文件名。如果日志收集器已禁用,则结果为 NULL。当存在多个日志文件,每个文件都有不同的格式时,没有参数的 ux_current_logfile 返回有序列表中找到的第一个格式的文件的路径:stderr、csvlog、jsonlog。如果没有任何日志文件具有这些格式,则返回 NULL。要请求有关特定日志文件格式的信息,请将 csvlog、jsonlog 或 stderr 作为可选参数的值。如果所请求的日志格式未在 log_destination 中配置,则结果为 NULL。结果反映了 current_logfiles 文件的内容。 | |
ux_my_temp_schema () → oid | 返回当前会话的临时模式的 OID,如果没有临时表,则返回零。 | |
ux_is_other_temp_schema ( oid ) → boolean | 如果给定的 OID 是另一个会话的临时模式的 OID,则返回 true。(例如,这可以用于从目录显示中排除其他会话的临时表。) | |
ux_jit_available () → boolean | 如果 JIT 编译器扩展可用并且 jit 配置参数设置为 on,则返回 true。 | |
ux_listening_channels () → setof text | 返回当前会话正在侦听的异步通知通道的名称集合。 | |
ux_notification_queue_usage () → double precision | 返回异步通知队列当前占用的最大大小的分数(0-1),等待处理的通知。 | |
ux_uxmaster_start_time () → timestamp with time zone | 返回服务器启动时的时间。 | |
ux_safe_snapshot_blocking_pids ( integer ) → integer[] | 返回阻止具有指定进程 ID 的服务器进程获取安全快照的会话的进程 ID 数组,如果没有这样的服务器进程或它未被阻止,则返回空数组。运行 SERIALIZABLE 事务的会话会阻止 SERIALIZABLE READ ONLY DEFERRABLE 事务获取快照,直到后者确定可以避免获取任何谓词锁为止。频繁调用此函数可能会对数据库性能产生一些影响,因为它需要短时间访问谓词锁管理器的共享状态。 | |
ux_trigger_depth () → integer | 返回 UXsinoDB 触发器的当前嵌套级别(如果未直接或间接从触发器内部调用,则为 0)。 | |
session_user → name | 返回会话用户的名称。 | |
user → name | 这相当于 current_user。 | |
uid → oid | 返回会话用户的唯一标识符(oid)。 | |
version () → text | 返回描述 UXsinoDB 服务器版本的字符串。您也可以从 server_version 获取此信息,或者使用 server_version_num 获取机器可读版本。软件开发人员应使用 server_version_num(自 8.2 起可用)或 UXSQLServerVersion 而不是解析文本版本。 |
注意
current_catalog、current_role、current_schema、current_user、session_user、user和uid在 SQL 中具有特殊的语法状态:它们必须在没有尾括号的情况下调用。在 UXsinoDB 中,可以选择使用括号与current_schema一起使用,但不能与其他函数一起使用。
session_user 通常是启动当前数据库连接的用户;但是超级用户可以使用 SET SESSION AUTHORIZATION 更改此设置。current_user 是适用于权限检查的用户标识符。通常它等于会话用户,但可以使用 SET ROLE 进行更改。在具有属性 SECURITY DEFINER 的函数执行期间,它也会更改。在 Unix 术语中,会话用户是“真实用户”,当前用户是“有效用户”。current_role 和 user 是 current_user 的同义词。(SQL 标准在 current_role 和 current_user 之间划分了区别,但 UXsinoDB 没有,因为它将用户和角色统一为一种实体。)
表 访问特权查询函数列出了允许以编程方式查询对象访问权限的函数。在这些函数中,可以通过名称或 OID(ux_authid.oid)指定正在查询其权限的用户,或者如果将名称指定为 public,则检查 PUBLIC 伪角色的权限。此外,可以完全省略正在查询的 user 参数,在这种情况下,假定为 current_user。正在查询的对象也可以通过名称或 OID 指定。在指定名称时,可以包括相关的模式名称。感兴趣的访问权限由文本字符串指定,该字符串必须计算为对象类型的适当权限关键字之一(例如,SELECT)。可以选择将 WITH GRANT OPTION 添加到权限类型中,以测试是否可以授予该权限。特权带有授予选项。此外,多个特权类型可以用逗号分隔列出,此时如果持有列出的任何特权,则结果为真。(特权字符串的大小写不重要,在特权名称之间允许但不允许在特权名称内部有额外的空格。)
一些例子:
SELECT has_table_privilege('myschema.mytable', 'select');
SELECT has_table_privilege('joe', 'mytable', 'INSERT, SELECT WITH GRANT OPTION');
| 函数 | 描述 |
|---|---|
has_any_column_privilege ( [ user name or oid, ] table text or oid, privilege text ) → boolean | 用户是否具有表中任何列的特权? 如果特权适用于整个表,或者至少有一个列级别的特权授予至少一个列,则成功。允许的特权类型为 SELECT、INSERT、UPDATE 和 REFERENCES。 |
has_column_privilege ( [ user name or oid, ] table text or oid, column text or smallint, privilege text ) → boolean | 用户是否具有指定表列的特权? 如果特权适用于整个表,或者至少有一个列级别的特权授予该列,则成功。列可以通过名称或属性编号(ux_attribute.attnum)指定。允许的特权类型为 SELECT、INSERT、UPDATE 和 REFERENCES。 |
has_database_privilege ( [ user name or oid, ] database text or oid, privilege text ) → boolean | 用户是否具有数据库的特权? 允许的特权类型为 CREATE、 CONNECT、 TEMPORARY 和 TEMP(等同于 TEMPORARY)。 |
has_foreign_data_wrapper_privilege ( [ user name or oid, ] fdw text or oid, privilege text ) → boolean | 用户是否对外部数据包装器具有特权? 唯一允许的特权类型是 USAGE。 |
has_function_privilege ( [ user name or oid, ] function text or oid, privilege text ) → boolean | 用户是否对函数具有特权? 唯一允许的特权类型是 EXECUTE。当通过名称而不是 OID 指定函数时,允许的输入与 regprocedure 数据类型相同。例如:SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute'); |
has_language_privilege ( [ user name or oid, ] language text or oid, privilege text ) → boolean | 用户是否对语言具有特权? 唯一允许的特权类型是 USAGE。 |
has_parameter_privilege ( [ user name or oid, ] parameter text, privilege text ) → boolean | 用户是否对配置参数具有特权? 参数名称不区分大小写。允许的特权类型为 SET 和 ALTER SYSTEM。 |
has_schema_privilege ( [ user name or oid, ] schema text or oid, privilege text ) → boolean | 用户是否对模式具有特权? 允许的特权类型为 CREATE 和 USAGE。 |
has_sequence_privilege ( [ user name or oid, ] sequence text or oid, privilege text ) → boolean | 用户是否具有序列的权限? 允许的权限类型为 USAGE、 SELECT 和 UPDATE。 |
has_server_privilege ( [ user name or oid, ] server text or oid, privilege text ) → boolean | 用户是否具有外部服务器的权限? 唯一允许的权限类型是 USAGE。 |
has_table_privilege ( [ user name or oid, ] table text or oid, privilege text ) → boolean | 用户是否具有表的权限? 允许的权限类型为 SELECT、INSERT、 UPDATE、DELETE、 TRUNCATE、REFERENCES 和 TRIGGER。 |
has_tablespace_privilege ( [ user name or oid, ] tablespace text or oid, privilege text ) → boolean | 用户是否具有表空间的权限? 唯一允许的权限类型是 CREATE。 |
has_type_privilege ( [ user name or oid, ] type text or oid, privilege text ) → boolean | 用户是否具有数据类型的权限? 唯一允许的权限类型是 USAGE。当通过名称而不是 OID 指定类型时,允许的输入与 regtype 数据类型相同。 |
ux_has_role ( [ user name or oid, ] role text or oid, privilege text ) → boolean | 用户是否具有角色的权限?允许的权限类型为 MEMBER 和 USAGE。MEMBER 表示直接或间接成员身份(即执行 SET ROLE 的权利),而 USAGE 表示角色的权限是否立即可用,而不需要执行 SET ROLE。此函数不允许将 user 设置为 public 的特殊情况,因为 PUBLIC 伪角色永远不能成为真实角色的成员。 |
row_security_active ( table text or oid ) → boolean | 在当前用户和当前环境的上下文中,是否为指定表启用了行级安全性? |
表 aclitem 操作符显示了 aclitem 类型的可用操作符,该类型是访问权限的目录表示。
| 操作符 | 描述 | 示例 |
|---|---|---|
aclitem = aclitem → boolean | aclitem 是否相等?(请注意,类型 aclitem 缺少通常的比较操作符;它只有相等性。反过来,aclitem 数组只能比较相等性。) | 'calvin=r*w/hobbes'::aclitem = 'calvin=r*w*/hobbes'::aclitem → f |
aclitem[] @> aclitem → boolean | 数组是否包含指定的权限?(如果有与 aclitem 的受让人和授权人匹配,并且具有至少指定的权限集的数组条目,则为真。) | '{calvin=r*w/hobbes,hobbes=r*w*/uxdb}'::aclitem[] @> 'calvin=r*/hobbes'::aclitem → t |
aclitem[] ~ aclitem → boolean | 这是 @> 的弃用别名。 | '{calvin=r*w/hobbes,hobbes=r*w*/uxdb}'::aclitem[] ~ 'calvin=r*/hobbes'::aclitem → t |
表 aclitem 函数显示了一些额外的函数来管理 aclitem 类型。
| 函数 | 描述 |
|---|---|
acldefault ( type "char", ownerId oid ) → aclitem[] | 构造一个 aclitem 数组,其中包含属于 OID 为 ownerId 的角色的类型为 type 的对象的默认访问权限。这表示当对象的 ACL 条目为空时将假定的访问权限。type 参数必须是以下之一:'c' 表示 COLUMN,'r' 表示 TABLE 和类似表的对象,'s' 表示 SEQUENCE,'d' 表示 DATABASE,'f' 表示 FUNCTION 或 PROCEDURE,'l' 表示 LANGUAGE,'L' 表示 LARGE OBJECT,'n' 表示 SCHEMA,'p' 表示 PARAMETER,'t' 表示 TABLESPACE,'F' 表示 FOREIGN DATA WRAPPER,'S' 表示 FOREIGN SERVER,或 'T' 表示 TYPE 或 DOMAIN。 |
aclexplode ( aclitem[] ) → setof record ( grantor oid, grantee oid, privilege_type text, is_grantable boolean ) | 将 aclitem 数组作为一组行返回。如果受让人是伪角色 PUBLIC,则在 grantee 列中表示为零。每个授予的权限都表示为 SELECT、INSERT 等。请注意,每个权限都被拆分为单独的行,因此在 privilege_type 列中只出现一个关键字。 |
makeaclitem ( grantee oid, grantor oid, privileges text, is_grantable boolean ) → aclitem | 使用给定的属性构造一个 aclitem。 |
表 模式可见性查询函数显示了用于确定某个对象是否在当前模式搜索路径中可见的函数。例如,如果包含表的模式在搜索路径中,并且没有同名的表出现在搜索路径中,则称该表可见。这相当于可以通过名称引用表而无需显式模式限定。因此,要列出所有可见表的名称:
SELECT relname FROM ux_class WHERE ux_table_is_visible(oid);
对于函数和操作符,如果在搜索路径中没有同名的对象和参数数据类型,则该对象在搜索路径中可见。对于操作符类和族,同时考虑名称和相关的索引访问方法。
| 函数 | 描述 |
|---|---|
ux_collation_is_visible ( collation oid ) → boolean | 字符集是否在搜索路径中可见? |
ux_conversion_is_visible ( conversion oid ) → boolean | 转换是否在搜索路径中可见? |
ux_function_is_visible ( function oid ) → boolean | 函数是否在搜索路径中可见?(这也适用于存储过程和聚合函数。) |
ux_opclass_is_visible ( opclass oid ) → boolean | 操作符类是否在搜索路径中可见? |
ux_operator_is_visible ( operator oid ) → boolean | 操作符是否在搜索路径中可见? |
ux_opfamily_is_visible ( opclass oid ) → boolean | 操作符族是否在搜索路径中可见? |
ux_statistics_obj_is_visible ( stat oid ) → boolean | 统计对象在搜索路径中是否可见? |
ux_table_is_visible ( table oid ) → boolean | 表在搜索路径中是否可见?(这适用于所有类型的关系,包括视图、物化视图、索引、序列和外部表。) |
ux_ts_config_is_visible ( config oid ) → boolean | 文本搜索配置在搜索路径中是否可见? |
ux_ts_dict_is_visible ( dict oid ) → boolean | 文本搜索词典在搜索路径中是否可见? |
ux_ts_parser_is_visible ( parser oid ) → boolean | 文本搜索解析器在搜索路径中是否可见? |
ux_ts_template_is_visible ( template oid ) → boolean | 文本搜索模板在搜索路径中是否可见? |
ux_type_is_visible ( type oid ) → boolean | 类型(或域)在搜索路径中是否可见? |
所有这些函数都需要对象 OID 来标识要检查的对象。如果您想按名称测试对象,则使用 OID 别名类型(regclass、regtype、regprocedure、regoperator、regconfig 或 regdictionary),例如:
SELECT ux_type_is_visible('myschema.widget'::regtype);
请注意,以这种方式测试非模式限定的类型名称没有太多意义——如果名称可以被识别,它必须是可见的。
表 系统目录信息函数列出了从系统目录中提取信息的函数。
| 函数 | 描述 |
|---|---|
format_type ( type oid, typemod integer ) → text | 返回一个数据类型的 SQL 名称,由其类型 OID 和可能的类型修饰符标识。如果不知道特定的修饰符,请将类型修饰符传递为 NULL。 |
ux_char_to_encoding ( encoding name ) → integer | 将提供的编码名称转换为表示某些系统目录表中使用的内部标识符的整数。如果提供了未知的编码名称,则返回 -1。 |
ux_encoding_to_char ( encoding integer ) → name | 将某些系统目录表中用作编码的内部标识符转换为可读的字符串。如果提供了无效的编码编号,则返回空字符串。 |
ux_get_catalog_foreign_keys () → setof record ( fktable regclass, fkcols text[], pktable regclass, pkcols text[], is_array boolean, is_opt boolean ) | 返回一组记录,描述存在于 UXsinoDB 系统目录中的外键关系。fktable 列包含引用目录的名称,fkcols 列包含引用列的名称。类似地,pktable 列包含被引用目录的名称,pkcols 列包含被引用列的名称。如果 is_array 为 true,则最后一个引用列是一个数组,其中每个元素都应与引用目录中的某个条目匹配。如果 is_opt 为 true,则允许引用列包含零而不是有效引用。 |
ux_get_constraintdef ( constraint oid [ , pretty boolean ] ) → text | 重构约束的创建命令。(这是反编译的重构,而不是命令的原始文本。) |
ux_get_expr ( expr ux_node_tree, relation oid [ , pretty ] ) → textux_get_expr ( expr text, [ rel_oid oid, pretty_bool boolean ] ) → text | 反编译存储在系统目录中的表达式的内部形式,例如列的默认值。如果表达式可能包含 Vars,请将它们引用的关系的 OID 指定为第二个参数;如果不需要 Vars,则传递零就足够了。 |
ux_get_functiondef ( func oid ) → text | 重构函数或过程的创建命令。(这是反编译的重构,而不是命令的原始文本。)结果是完整的 CREATE OR REPLACE FUNCTION 或 CREATE OR REPLACE PROCEDURE 语句。 |
ux_get_function_arguments ( func oid ) → text | 以 CREATE FUNCTION 中需要出现的形式(包括默认值)重构函数或过程的参数列表。 |
ux_get_function_identity_arguments ( func oid ) → text | 以 ALTER FUNCTION 等命令中需要出现的形式重构函数或过程的参数列表。此形式省略了默认值。 |
ux_get_function_result ( func oid ) → text | 以 CREATE FUNCTION 中需要出现的形式重构函数的 RETURNS 子句。对于过程返回 NULL。 |
ux_get_indexdef ( index oid [ , column integer, pretty boolean ] ) → text | 重构索引的创建命令。(这是反编译的重构,而不是命令的原始文本。)如果提供了 column 并且不为零,则仅重构该列的定义。 |
ux_get_keywords () → setof record ( word text, catcode "char", barelabel boolean, catdesc text, baredesc text ) | 返回描述 SQL 关键字的记录集,这些关键字被识别并由 SQL 解析器使用。服务器。word 列包含关键字。catcode 列包含类别代码:U 表示未保留的关键字,C 表示可以是列名称的关键字,T 表示可以是类型或函数名称的关键字,或 R 表示完全保留的关键字。barelabel 列包含 true,如果关键字可以用作 SELECT 列表中的“裸”列标签,则为 false,如果只能在 AS 之后使用。catdesc 列包含描述关键字类别的可能本地化字符串。baredesc 列包含描述关键字列标签状态的可能本地化字符串。 |
ux_get_ruledef ( rule oid [ , pretty boolean ] ) → text | 重建规则的创建命令。(这是反编译的重建,而不是命令的原始文本。) |
ux_get_serial_sequence ( table text, column text ) → text | 返回与列关联的序列的名称,如果没有序列与列关联,则返回 NULL。如果列是标识列,则关联序列是为该列内部创建的序列。对于使用其中一个序列类型(serial、smallserial、bigserial)创建的列,它是为该序列列定义创建的序列。在后一种情况下,可以使用 ALTER SEQUENCE OWNED BY 修改或删除关联。(这个函数可能应该被称为 ux_get_owned_sequence;它的当前名称反映了它历史上与序列类型列一起使用的事实。)第一个参数是一个带有可选模式的表名,第二个参数是一个列名。因为第一个参数可能包含模式和表名,所以它按照通常的 SQL 规则进行解析,这意味着默认情况下将其转换为小写。第二个参数只是一个列名,因此被视为文字处理,因此其大小写得以保留。结果适合格式化以传递给序列函数。一个典型的用法是读取标识或序列列的序列的当前值,例如:SELECT currval(ux_get_serial_sequence('sometable', 'id')); |
ux_get_statisticsobjdef ( statobj oid ) → text | 重建扩展统计对象的创建命令。(这是反编译的重建,而不是命令的原始文本。) |
ux_get_triggerdef ( trigger oid [ , pretty boolean ] ) → text | 重建触发器的创建命令。(这是反编译重建,不是命令的原始文本。) |
ux_get_userbyid ( role oid ) → name | 根据其 OID 返回角色名称。 |
ux_get_viewdef ( view oid [ , pretty boolean ] ) → text | 重建视图或材料化视图的底层 SELECT 命令。(这是反编译重建,不是命令的原始文本。) |
ux_get_viewdef ( view oid, wrap_column integer ) → text | 重建视图或材料化视图的底层 SELECT 命令。(这是反编译重建,不是命令的原始文本。)在此函数形式中,总是启用漂亮打印,并且长行被包装以尝试使它们短于指定的列数。 |
ux_get_viewdef ( view text [ , pretty boolean ] ) → text | 重建视图或材料化视图的底层 SELECT 命令,从视图的文本名称而不是其 OID 工作。(已弃用;请改用 OID 变体。) |
ux_index_column_has_property ( index regclass, column integer, property text ) → boolean | 测试索引列是否具有命名属性。(请注意,扩展访问方法可以为其索引定义其他属性名称。) 如果属性名称未知或不适用于特定对象,或者 OID 或列号未标识有效对象,则返回 NULL。 |
ux_index_has_property ( index regclass, property text ) → boolean | 测试索引是否具有命名属性。(请注意,扩展访问方法可以为其索引定义其他属性名称。)如果属性名称不知道或不适用于特定对象,或者如果 OID 没有标识有效对象,则返回 NULL。 |
ux_indexam_has_property ( am oid, property text ) → boolean | 测试索引访问方法是否具有指定的属性。如果属性名称未知或不适用于特定对象,或者 OID 未标识有效对象,则返回 NULL。 |
ux_options_to_table ( options_array text[] ) → setof record ( option_name text, option_value text ) | 返回由 ux_class.reloptions 或 ux_attribute.attoptions 表示的存储选项集。 |
ux_settings_get_flags ( guc text ) → text[] | 返回与给定 GUC 相关联的标志数组,如果不存在,则返回 NULL。如果 GUC 存在但没有要显示的标志,则结果为空数组。 |
ux_tablespace_databases ( tablespace oid ) → setof oid | 返回在指定表空间中存储对象的数据库 OID 集。如果此函数返回任何行,则表空间不为空,不能删除。要识别填充表空间的特定对象,您需要连接到由 ux_tablespace_databases 标识的数据库,并查询它们的 ux_class 目录。 |
ux_tablespace_location ( tablespace oid ) → text | 返回此表空间所在的文件系统路径。 |
ux_typeof ( "any" ) → regtype | 返回传递给它的值的数据类型的 OID。这对于故障排除或动态构建 SQL 查询很有帮助。该函数声明为返回 regtype,这是一个 OID 别名类型;这意味着它与 OID 在比较目的上相同,但显示为类型名称。例如:SELECT ux_typeof(33);ux_typeof-----------integerSELECT typlen FROM ux_type WHERE oid = ux_typeof(33);typlen---------4 |
COLLATION FOR ( "any" ) → text | 返回传递给它的值的排序规则的名称。如果必要,该值将带引号并带有模式限定符。如果没有为参数表达式派生排序规则,则返回 NULL。如果参数不是可排序数据类型,则会引发错误。例如:SELECT collation for (description) FROM ux_description LIMIT 1;ux_collation_for------------------"default"SELECT collation for ('foo' COLLATE "de_DE");ux_collation_for------------------"de_DE" |
to_regclass ( text ) → regclass | 将文本关系名称转换为其 OID。通过将字符串转换为类型 regclass,可以获得类似的结果;但是,如果未找到名称,则此函数将返回 NULL 而不是引发错误。与转换不同,它不接受数字 OID 作为输入。 |
to_regcollation ( text ) → regcollation | 将文本排序规则名称转换为其 OID。通过将字符串转换为类型 regcollation,可以获得类似的结果;但是,如果未找到名称,则此函数将返回 NULL 而不是引发错误。与转换不同,它不接受数字 OID 作为输入。 |
to_regnamespace ( text ) → regnamespace | 将文本模式名称转换为其 OID。通过将字符串转换为类型 regnamespace,可以获得类似的结果;但是,如果未找到名称,则此函数将返回 NULL 而不是引发错误。与转换不同,它不接受数字 OID 作为输入。 |
to_regoper ( text ) → regoper | 将文本操作符名称转换为其 OID。通过将字符串转换为类型 regoper,可以获得类似的结果;但是,如果未找到名称或名称不明确,则此函数将返回 NULL 而不是抛出错误。此外,与转换不同,此函数不接受数字 OID 作为输入。 |
to_regoperator ( text ) → regoperator | 将文本操作符名称(带有参数类型)转换为其 OID。通过将字符串转换为类型 regoperator,可以获得与此类似的结果;但是,如果未找到名称,则此函数将返回 NULL 而不是抛出错误。此外,与转换不同,此函数不接受数字 OID 作为输入。 |
to_regproc ( text ) → regproc | 将文本函数或过程名称转换为其 OID。通过将字符串转换为类型 regproc,可以获得与此类似的结果;但是,如果未找到名称或名称不明确,则此函数将返回 NULL 而不是抛出错误。此外,与转换不同,此函数不接受数字 OID 作为输入。 |
to_regprocedure ( text ) → regprocedure | 将文本函数或过程名称(带有参数类型)转换为其 OID。通过将字符串转换为类型 regprocedure,可以获得与此类似的结果;但是,如果未找到名称,则此函数将返回 NULL 而不是抛出错误。此外,与转换不同,此函数不接受数字 OID 作为输入。 |
to_regrole ( text ) → regrole | 将文本角色名称转换为其 OID。通过将字符串转换为类型 regrole,可以获得与此类似的结果;但是,如果未找到名称,则此函数将返回 NULL 而不是抛出错误。此外,与转换不同,此函数不接受数字 OID 作为输入。 |
to_regtype ( text ) → regtype | 将文本类型名称转换为其 OID。通过将字符串转换为类型 regtype,可以获得与此类似的结果;但是,如果未找到名称,则此函数将返回 NULL 而不是抛出错误。此外,与转换不同,此函数不接受数字 OID 作为输入。 |
大多数重建(反编译)数据库对象的函数都有一个可选的 pretty 标志,如果设置为 true,则结果将被“pretty-printed”,即去除不必要的括号并添加空格以增加可读性。虽然漂亮的打印格式更易读,但默认格式更可能被未来版本的 UXsinoDB 解释相同;因此,在转储目的时避免使用漂亮的打印输出。将 pretty 参数设置为 false 将产生与省略参数相同的结果。
表 索引列属性
| 名称 | 描述 |
|---|---|
asc | 在向前扫描时列是按照升序排列吗? |
desc | 在向前扫描时列是按照降序排列吗? |
nulls_first | 在向前扫描时列排序会把空值排在前面吗? |
nulls_last | 在向前扫描时列排序会把空值排在最后吗? |
orderable | 列具有已定义的排序顺序吗? |
distance_orderable | 列能否通过一个“distance”操作符(例如 ORDER BY col <-> constant)有序地扫描? |
returnable | 列值是否可以通过一次只用索引扫描返回? |
search_array | 列是否天然支持 col = ANY(array) 搜索? |
search_nulls | 列是否支持 IS NULL 和 IS NOT NULL 搜索? |
表 索引性质
| 名称 | 描述 |
|---|---|
clusterable | 索引是否可以用于 CLUSTER 命令? |
index_scan | 索引是否支持普通扫描(非位图)? |
bitmap_scan | 索引是否支持位图扫描? |
backward_scan | 在扫描中扫描方向能否被更改(为了支持游标上无需物化的 FETCH BACKWARD)? |
表 索引访问方法性质
| 名称 | 描述 |
|---|---|
can_order | 访问方法是否支持 ASC、DESC 以及 CREATE INDEX 中的有关关键词? |
can_unique | 访问方法是否支持唯一索引? |
can_multi_col | 访问方法是否支持多列索引? |
can_exclude | 访问方法是否支持排除约束? |
can_include | 访问方法是否支持 CREATE INDEX 的 INCLUDE 子句? |
表 GUC 标志
| 标志 | 描述 |
|---|---|
EXPLAIN | 带有此标志的参数包含在 EXPLAIN (SETTINGS) 命令中。 |
NO_SHOW_ALL | 带有此标志的参数不包含在 SHOW ALL 命令中。 |
NO_RESET_ALL | 带有此标志的参数不包含在 RESET ALL 命令中。 |
NOT_IN_SAMPLE | 带有此标志的参数默认情况下不包含在 uxsinodb.conf 中。 |
RUNTIME_COMPUTED | 带有此标志的参数是运行时计算的参数。 |
表 对象信息和寻址函数列出了与数据库对象识别和寻址相关的函数。
表 对象信息和寻址函数
| 函数 | 描述 |
|---|---|
ux_describe_object ( classid oid, objid oid, objsubid integer ) → text | 返回由目录 OID、对象 OID 和子对象 ID(例如表中的列号;当引用整个对象时,子对象 ID 为零)标识的数据库对象的文本描述。此描述旨在供人阅读,并可能根据服务器配置进行翻译。这对于确定在 ux_depend 目录中引用的对象的身份非常有用。此函数对未定义的对象返回 NULL 值。 |
ux_identify_object ( classid oid, objid oid, objsubid integer ) → record ( type text, schema text, name text, identity text ) | 返回一行包含足够的信息,以唯一标识由目录 OID、对象 OID 和子对象 ID 指定的数据库对象。此信息旨在供机器阅读,永远不会被翻译。type 标识数据库对象的类型;schema 是对象所属的模式名称,或对于不属于模式的对象类型,为 NULL;name 是对象的名称,如果名称(连同模式名称,如果相关)足以唯一标识对象,则加引号,否则为 NULL;identity 是完整的对象标识,具体格式取决于对象类型,格式中的每个名称都应根据需要进行模式限定和引用。未定义的对象使用 NULL 值进行标识。 |
ux_identify_object_as_address ( classid oid, objid oid, objsubid integer ) → record ( type text, object_names text[], object_args text[] ) | 返回一行包含足够的信息,以唯一标识由目录 OID、对象 OID 和子对象 ID 指定的数据库对象。返回的信息与当前服务器无关,即它可以用于标识另一个服务器中具有相同名称的对象。type 标识数据库对象的类型;object_names 和 object_args 是文本数组,共同形成对对象的引用。这三个值可以传递给 ux_get_object_address 以获取对象的内部地址。 |
ux_get_object_address ( type text, object_names text[], object_args text[] ) → record ( classid oid, objid oid, objsubid integer ) | 返回一行包含足够的信息,以唯一标识由类型代码和对象名称和参数数组指定的数据库对象。返回的值是将用于系统目录(如 ux_depend)的值;它们可以传递给其他系统函数,如 ux_describe_object 或 ux_identify_object。classid 是包含对象的系统目录的 OID;objid 是对象本身的 OID,objsubid 是子对象 ID,如果没有则为零。此函数是反函数 ux_identify_object_as_address 的作用是识别对象的地址。未定义的对象使用 NULL 值进行标识。 |
表 注释信息函数中显示的函数提取先前使用 COMMENT 命令存储的注释。如果找不到指定参数的注释,则返回空值。
表 注释信息函数
| 函数 | 描述 |
|---|---|
col_description ( table oid, column integer ) → text | 返回表列的注释,该注释由其表的 OID 和列号指定。(对于表列,不能使用 obj_description,因为列没有自己的 OID。) |
obj_description ( object oid, catalog name ) → text | 返回由其 OID 和包含系统目录的名称指定的数据库对象的注释。例如,obj_description(123456, 'ux_class') 将检索 OID 为 123456 的表的注释。 |
obj_description ( object oid ) → text | 仅使用其 OID 指定数据库对象的注释。这是不推荐使用的,因为不能保证 OID 在不同的系统目录中是唯一的;因此,可能会返回错误的注释。 |
shobj_description ( object oid, catalog name ) → text | 返回由其 OID 和包含系统目录的名称指定的共享数据库对象的注释。这与 obj_description 相同,只是用于检索共享对象(即数据库、角色和表空间)的注释。一些系统目录对于每个集群中的所有数据库都是全局的,其中的对象的描述也存储为全局的。 |
表 事务 ID 和快照信息函数中显示的函数以可导出的形式提供服务器事务信息。这些函数的主要用途是确定两个快照之间提交的事务。
| 函数 | 描述 |
|---|---|
ux_current_xact_id () → xid8 | 返回当前事务的 ID。如果当前事务没有 ID(因为它没有执行任何数据库更新),则会分配一个新的 ID。 |
ux_current_xact_id_if_assigned () → xid8 | 返回当前事务的 ID,如果尚未分配 ID,则返回 NULL。(如果事务可能是只读的,则最好使用此变体,以避免不必要地消耗 XID。) |
ux_xact_status ( xid8 ) → text | 报告最近事务的提交状态。如果事务足够新,系统会保留该事务的提交状态,结果为 in progress、committed 或 aborted。如果事务足够旧,系统中没有对该事务的引用并且提交状态信息已被丢弃,则结果为 NULL。例如,应用程序可以使用此函数确定在应用程序和数据库服务器在提交过程中断开连接后,它们的事务是否提交或中止。请注意,准备好的事务报告为 in progress;如果需要确定事务 ID 是否属于准备好的事务,则应用程序必须检查 ux_prepared_xacts。 |
ux_current_snapshot () → ux_snapshot | 返回当前的快照,即显示哪些事务 ID 正在进行的数据结构。 |
ux_snapshot_xip ( ux_snapshot ) → setof xid8 | 返回快照中包含的正在进行的事务 ID 集合。 |
ux_snapshot_xmax ( ux_snapshot ) → xid8 | 返回快照的 xmax。 |
ux_snapshot_xmin ( ux_snapshot ) → xid8 | 返回快照的 xmin。 |
ux_visible_in_snapshot ( xid8, ux_snapshot ) → boolean | 给定的事务 ID 是否在此快照中可见(即,在快照被拍摄之前是否已经完成)?请注意,此函数对于子事务 ID 将无法给出正确的答案。 |
内部事务 ID 类型 xid 宽度为 32 位,并在每 40 亿个事务时重新开始。但是,表 事务 ID 和快照信息函数中显示的函数使用 64 位类型 xid8,在安装的生命周期内不会重新开始,并且可以通过转换为 xid 来进行转换(如果需要)。数据类型 ux_snapshot 存储有关特定时间点上事务 ID 可见性的信息。其组件在表 快照组件中描述。ux_snapshot 的文本表示形式为 xmin:xmax:xip_list。例如,10:20:10,14,15 表示 xmin=10,xmax=20,xip_list=10, 14, 15。
| 名称 | 描述 |
|---|---|
xmin | 仍处于活动状态的最低事务 ID。小于 xmin 的所有事务 ID 都已提交并可见,或已回滚并死亡。 |
xmax | 已完成的事务 ID 的下一个 ID。大于或等于 xmax 的所有事务 ID 在快照拍摄时尚未完成,因此不可见。 |
xip_list | 在快照拍摄时正在进行的事务。不在此列表中的事务 ID 是 xmin <= X < xmax 且已完成,因此根据其提交状态,它们是可见的或已死亡的。此列表不包括子事务的事务 ID。 |
在之前的 UXsinoDB 版本中没有 xid8 类型,因此提供了使用 bigint 表示 64 位 XID 的变体函数,相应地,使用不同的快照数据类型 txid_snapshot。这些旧函数在名称中带有 txid,仍然支持向后兼容性,但可能会在未来的版本中删除。请参见表 已弃用的事务 ID 和快照信息函数。
| 函数 | 描述 |
|---|---|
txid_current () → bigint | 参见 ux_current_xact_id()。 |
txid_current_if_assigned () → bigint | 参见 ux_current_xact_id_if_assigned()。 |
txid_current_snapshot () → txid_snapshot | 参见 ux_current_snapshot()。 |
txid_snapshot_xip ( txid_snapshot ) → setof bigint | 参见 ux_snapshot_xip()。 |
txid_snapshot_xmax ( txid_snapshot ) → bigint | 参见 ux_snapshot_xmax()。 |
txid_snapshot_xmin ( txid_snapshot ) → bigint | 参见 ux_snapshot_xmin()。 |
txid_visible_in_snapshot ( bigint, txid_snapshot ) → boolean | 参见 ux_visible_in_snapshot()。 |
txid_status ( bigint ) → text | 参见 ux_xact_status()。 |
track_commit_timestamp 配置选项启用后,表 已提交事务信息函数中显示的函数提供有关过去事务提交时间的信息。它们仅在启用该选项并且在启用后提交的事务中提供有用数据。
表 已提交事务信息函数
| 函数 | 描述 |
|---|---|
ux_xact_commit_timestamp ( xid ) → timestamp with time zone | 返回事务的提交时间戳。 |
ux_xact_commit_timestamp_origin ( xid ) → record ( timestamp timestamp with time zone, roident oid ) | 返回事务的提交时间戳和复制来源。 |
ux_last_committed_xact () → record ( xid xid, timestamp timestamp with time zone, roident oid ) | 返回最新提交事务的事务 ID、提交时间戳和复制来源。 |
在 initdb 初始化期间初始化的函数在表 控制数据函数中显示,例如目录版本。它们还显示关于预写式日志和检查点处理的信息。此信息是整个集群范围内的,而不是特定于任何一个数据库的。这些函数提供了与 ux_controldata 应用程序相同来源的大部分相同信息。
| 函数 | 描述 |
|---|---|
ux_control_checkpoint () → record | 返回有关当前检查点状态的信息。 |
ux_control_system () → record | 返回有关当前控制文件状态的信息。 |
ux_control_init () → record | 返回有关集群初始化状态的信息。 |
ux_control_recovery () → record | 返回有关恢复状态的信息。 |
表 ux_control_checkpoint 输出列
| 列名 | 数据类型 |
|---|---|
checkpoint_lsn | ux_lsn |
redo_lsn | ux_lsn |
redo_wal_file | text |
timeline_id | integer |
prev_timeline_id | integer |
full_page_writes | boolean |
next_xid | text |
next_oid | oid |
next_multixact_id | xid |
next_multi_offset | xid |
oldest_xid | xid |
oldest_xid_dbid | oid |
oldest_active_xid | xid |
oldest_multi_xid | xid |
oldest_multi_dbid | oid |
oldest_commit_ts_xid | xid |
newest_commit_ts_xid | xid |
checkpoint_time | timestamp with time zone |
表 ux_control_system 输出列
| 列名 | 数据类型 |
|---|---|
ux_control_version | integer |
catalog_version_no | integer |
system_identifier | bigint |
ux_control_last_modified | timestamp with time zone |
表 ux_control_init 输出列
| 列名 | 数据类型 |
|---|---|
max_data_alignment | integer |
database_block_size | integer |
blocks_per_segment | integer |
wal_block_size | integer |
bytes_per_wal_segment | integer |
max_identifier_length | integer |
max_index_columns | integer |
max_toast_chunk_size | integer |
large_object_chunk_size | integer |
float8_pass_by_value | boolean |
data_page_checksum_version | integer |
表 ux_control_recovery 输出列
| 列名 | 数据类型 |
|---|---|
min_recovery_end_lsn | ux_lsn |
min_recovery_end_timeline | integer |
backup_start_lsn | ux_lsn |
backup_end_lsn | ux_lsn |
end_of_backup_record_required | boolean |
27.1. sys_context
-
功能
sys_context函数用于获取环境上下文信息或判断当前会话角色。 -
函数
SYS_CONTEXT('context','parameter'[, length ]) -
参数
表 SYS_CONTEXT 参数说明
参数 说明 context context 名不区分大小写,最大长度 128 字节;目前支持 USERENV 和 SYS_SESSION_ROLES 两种上下文,当值为 USERENV 时,返回名为 parameter 的系统参数的值;当值为 SYS_SESSION_ROLES 时,判断 parameter 是否为在当前会话中启用的角色,是则返回 true,否则返回 false。 parameter parameter 为 context 中的属性,最大长度 64 字节。
• 当 context 为 USERENV 时,parameter 支持属性参见如下说明。
• 当 context 为 SYS_SESSION_ROLES 时,parameter 为当前会话中启用的角色名。length 返回值的最大长度,默认值为 256 字节。有效值为 1-4000,如果指定的 length 值不在有效值范围内,则忽略该值,使用默认值 256。 表 parameter 属性说明
属性 说明 CURRENT_SCHEMA 当前活动的默认模式的名称。 CURRENT_SCHEMAID 当前活动的默认模式的标识符。 CURRENT_USER 权限处于活动状态的数据库用户的名称。 CURRENT_USERID 权限处于活动状态的数据库用户的标识符。 DB_NAME 初始化参数 DB_NAME 中指定的数据库名称。 HOST 客户端连接的主机的名称,只在 guc 参数 log_hostname 开启时才能返回通过 ip 地址连接的客户端的主机名。 INSTANCE_NAME 实例的名称。 IP_ADDRESS 连接客户端的机器的 IP 地址。 ISDBA 如果用户已通过操作系统或密码文件验证为具有 DBA 特权,则返回 TRUE。 LANG 您的会话当前使用的语言的缩写。 LANGUAGE 您的会话当前使用的语言和地区,以及数据库字符集,格式如下:language_territory.characterset。 NETWORK_PROTOCOL 用于通信的网络协议。 SERVER_HOST 运行实例的机器的主机名。 SESSION_USER 会话用户的名称(登录的用户)。 SESSION_USERID 会话用户(登录的用户)的标识符。 SESSIONID 审计会话标识符,只在安全模式和兼容安全模式下有返回值。 SID 会话 ID。 -
返回值
返回值类型为
text,默认最大长度为 256 字节。 -
示例
查询当前数据库的数据库名。
SELECT sys_context('USERENV', 'DB_NAME');查询客户端连接的主机的名称并限制返回值长度为 10 字节。
SELECT sys_context('USERENV', 'HOST', 10);查询用户 uxdb 是否为在当前会话中启用的角色。
SELECT sys_context('SYS_SESSION_ROLES', 'uxdb');
27.2. sys_guid
-
功能
sys_guid函数返回一个使用系统信息生成的唯一识别码。 -
函数
SYS_GUID() -
参数
无
-
返回值
返回值类型为
VARCHAR,是一个 32 位的大写字母和数字混合的标识符。 -
说明
该函数的使用需要建立 uuid-ossp 插件,生成的标识符会含有系统时间、网络地址、机器信息的信息,如果有安全上的需求请使用 mysql_uuid 或者直接调用 uuid()。
28. 系统管理功能
本节介绍的函数用于控制和监视 UXsinoDB 安装。
28.1. 配置设置函数
表 配置设置函数显示了可用于查询和更改运行时配置参数的函数。
| 函数 | 描述 | 示例 |
|---|---|---|
current_setting ( setting_name text [, missing_ok boolean ] ) → text | 返回设置 set_name 的当前值。如果没有这样的设置,current_set 将抛出一个错误,除非提供了 miss_ok 且为 true(在这种情况下返回 NULL)。此函数对应于 SQL 命令 SHOW。 | current_setting('datestyle') → ISO, MDY |
set_config ( setting_name text, new_value text, is_local boolean ) → text | 将参数 set_name 设置为 new_value,并返回该值。如果 is_local 为 true,则新值将仅在当前事务期间应用。如果希望新值应用于当前会话的其余部分,则改为使用 false。此函数对应于 SQL 命令 SET。 | set_config('log_statement_stats', 'off', false) → off |
28.2. 服务器信号函数
表 服务器信号函数显示了可用于向服务器发送信号的函数。
| 函数 | 描述 |
|---|---|
ux_cancel_backend ( pid integer ) → boolean | 取消具有指定进程 ID 的后端进程的会话的当前查询。如果调用角色是被取消的后端所属角色的成员或调用角色具有 ux_signal_backend 的特权,则也允许这样做。然而,只有超级用户才能取消超级用户后端。 |
ux_log_backend_memory_contexts ( pid integer ) → boolean | 请求记录具有指定进程 ID 的后端的内存上下文。此函数可以将请求发送到后端和辅助进程,但不能发送到日志记录器。这些内存上下文将在 LOG 消息级别下记录。它们将根据设置的日志配置出现在服务器日志中,但无论 client_min_messages 如何,都不会发送到客户端。 |
ux_reload_conf () → boolean | 导致所有 UXsinoDB 服务器进程重新加载其配置文件。(这是通过向 uxmaster 进程发送 SIGHUP 信号来启动的,uxmaster 进程随后向其每个子进程发送 SIGHUP。)您可以使用 ux_file_settings、ux_hba_file_rules 和 ux_ident_file_mappings 视图,在重新加载之前检查配置文件是否存在可能的错误。 |
ux_rotate_logfile () → boolean | 立即向日志文件管理器发送信号,以切换到新的输出文件。这仅在内置日志收集器正在运行时才有效,否则没有日志文件管理器子进程。 |
ux_terminate_backend ( pid integer, timeout bigint DEFAULT 0 ) → boolean | 终止具有指定进程 ID 的后端进程的会话。如果调用角色是正在终止其后端的角色的成员或调用角色具有 ux_signal_backend 的特权,则也允许执行此操作,但只有超级用户才能终止超级用户后端。如果未指定或为零,则此函数返回 true,无论进程是否实际终止,仅表示信号发送成功。如果指定了 timeout(以毫秒为单位)且大于零,则函数将等待直到进程实际终止或给定的时间已过。如果进程终止,则函数返回 true。在超时时,会发出警告并返回 false。 |
ux_cancel_backend 和 ux_terminate_backend 发送信号(分别为 SIGINT 或 SIGTERM)给由进程 ID 标识的后端进程。活动后端的进程 ID 可以从 ux_stat_activity 视图的 pid 列中找到,或者通过在服务器上列出 uxdb 进程(在 Unix 上使用 ps 或在 Windows 上使用任务管理器)来找到。活动后端的角色可以从 ux_stat_activity 视图的 usename 列中找到。
ux_log_backend_memory_contexts 可用于记录后端进程的内存上下文。例如:
uxdb=# SELECT ux_log_backend_memory_contexts(ux_backend_pid());
ux_log_backend_memory_contexts
--------------------------------
t
(1 row)
将记录每个内存上下文的一条消息。例如:
LOG: logging memory contexts of PID 10377
STATEMENT: SELECT ux_log_backend_memory_contexts(ux_backend_pid());
LOG: level: 0; TopMemoryContext: 80800 total in 6 blocks; 14432 free (5 chunks); 66368 used
LOG: level: 1; uxstat TabStatusArray lookup hash table: 8192 total in 1 blocks; 1408 free (0 chunks); 6784 used
LOG: level: 1; TopTransactionContext: 8192 total in 1 blocks; 7720 free (1 chunks); 472 used
LOG: level: 1; RowDescriptionContext: 8192 total in 1 blocks; 6880 free (0 chunks); 1312 used
LOG: level: 1; MessageContext: 16384 total in 2 blocks; 5152 free (0 chunks); 11232 used
LOG: level: 1; Operator class cache: 8192 total in 1 blocks; 512 free (0 chunks); 7680 used
LOG: level: 1; smgr relation table: 16384 total in 2 blocks; 4544 free (3 chunks); 11840 used
LOG: level: 1; TransactionAbortContext: 32768 total in 1 blocks; 32504 free (0 chunks); 264 used
...
LOG: level: 1; ErrorContext: 8192 total in 1 blocks; 7928 free (3 chunks); 264 used
LOG: Grand total: 1651920 bytes in 201 blocks; 622360 free (88 chunks); 1029560 used
如果在同一父级下有超过 100 个子上下文,则将记录前 100 个子上下文以及其余上下文的摘要。请注意,频繁调用此函数可能会产生重大开销,因为它可能会生成大量日志消息。
28.3. 备份控制函数
表 备份控制函数中显示的函数有助于进行在线备份。这些函数不能在恢复期间执行(除了 ux_backup_start、ux_backup_stop 和 ux_wal_lsn_diff)。
| 函数 | 描述 | 示例 |
|---|---|---|
ux_create_restore_point ( name text ) → ux_lsn | 被用作恢复目标,并返回相应的预写日志位置。然后可以使用给定的名称与 recovery_target_name 一起指定恢复将进行到哪个点。避免创建具有相同名称的多个恢复点,因为恢复将停止在第一个名称与恢复目标匹配的恢复点处。默认情况下,此函数仅限超级用户使用,但可以授予其他用户执行该函数的权限。 | |
ux_current_wal_flush_lsn () → ux_lsn | 返回当前的预写日志刷新位置(请参见下面的注释)。 | |
ux_current_wal_insert_lsn () → ux_lsn | 返回当前的预写日志插入位置(请参见下面的注释)。 | |
ux_current_wal_lsn () → ux_lsn | 返回当前的预写日志写入位置(请参见下面的注释)。 | |
ux_backup_start ( label text [, fast boolean ] ) → ux_lsn | 准备服务器开始在线备份。唯一必需的参数是备份的任意用户定义标签。(通常这将是备份转储文件存储的名称。)如果给定了可选的第二个参数作为 true,则指定尽快执行 ux_backup_start。这将强制立即进行检查点,从而导致 I/O 操作的峰值,减慢任何同时执行的查询。默认情况下,此函数仅限超级用户使用,但可以授予其他用户执行该函数的权限。 | |
ux_backup_stop ( [wait_for_archive boolean ] ) → record ( lsn ux_lsn, labelfile text, spcmapfile text ) | 完成在线备份。备份标签文件和表空间映射文件的期望内容作为函数结果的一部分返回,并且必须写入备份区域中的文件。这些文件不能写入实时数据目录(这样做将导致 UXsinoDB 在崩溃事件中无法重新启动)。 有一个可选的类型为 boolean 的参数。如果为 false,则备份完成后该函数将立即返回,而无需等待 WAL 被归档。此行为仅对独立监视 WAL 归档的备份软件有用。否则,使备份一致所需的 WAL 可能会丢失,并使备份无用。默认情况下或当此参数为 true 时,ux_backup_stop 将在启用归档时等待 WAL 被归档。(在备用中,这将是一个异步操作。) 默认情况下,此函数仅限超级用户使用,但可以授予其他用户执行该函数的权限。这意味着只有当 archive_mode = always 时,函数才会等待。如果主服务器上的写入活动较少,则在主服务器上运行 ux_switch_wal 可能是有用的,以触发立即段切换。 当在主服务器上执行时,此函数还会在写入日志归档区域中创建备份历史文件。历史文件包括分配给 ux_backup_start 的标签、备份的起始和结束写入日志位置以及备份的起始和结束时间。在记录结束位置后,当前的写入日志插入点会自动前进到下一个写入日志文件,以便立即归档结束的写入日志文件以完成备份。 该函数的结果是一个记录。lsn 列保存备份的结束写入日志位置(可以忽略)。第二列返回备份标签文件的内容,第三列返回表空间映射文件的内容。这些必须作为备份的一部分存储,并且在恢复过程中是必需的。 默认情况下,此函数仅限超级用户使用,但可以授予其他用户 EXECUTE 权限以运行该函数。 | |
ux_switch_wal () → ux_lsn | ux_switch_wal () 强制服务器切换到新的写入日志文件,从而允许归档当前文件(假设您正在使用连续归档)。结果是刚刚完成的写入日志文件中的结束写入日志位置加 1。如果自上次写入日志切换以来没有写入日志活动,则 ux_switch_wal 不执行任何操作并返回当前正在使用的写入日志文件的起始位置。 默认情况下,此函数仅限超级用户使用,但可以授予其他用户 EXECUTE 权限以运行该函数。 | |
ux_walfile_name ( lsn ux_lsn ) → text | 将写入日志位置转换为包含该位置的 WAL 文件的名称。 | |
ux_walfile_name_offset ( lsn ux_lsn ) → record ( file_name text, file_offset integer ) | 将写入日志位置转换为 WAL 文件名和该文件中的字节偏移量。 | |
ux_wal_lsn_diff ( lsn1 ux_lsn, lsn2 ux_lsn ) → numeric | 计算两个写入日志位置之间的字节差(lsn1 - lsn2)。这可与 ux_stat_replication 显示的某些函数一起使用,以获取复制滞后时间。 |
ux_current_wal_lsn 显示与上述函数相同格式的当前写前日志写入位置。类似地,ux_current_wal_insert_lsn 显示当前写前日志插入位置,而 ux_current_wal_flush_lsn 显示当前写前日志刷新位置。插入位置是任何时刻写前日志的“逻辑”末尾,而写入位置是实际从服务器内部缓冲区写出的末尾,刷新位置是已知写入持久存储的最后位置。写入位置是可以从服务器外部检查的末尾,通常是您感兴趣的部分完成写前日志文件的归档。插入和刷新位置主要用于服务器调试目的。这些都是只读操作,不需要超级用户权限。
您可以使用 ux_walfile_name_offset 从 ux_lsn 值中提取相应的写前日志文件名和字节偏移量。例如:
uxdb=# SELECT * FROM ux_walfile_name_offset((ux_backup_stop()).lsn);
file_name | file_offset
--------------------------+-------------
00000001000000000000000D | 4039624
(1 row)
类似地,ux_walfile_name 仅提取写前日志文件名。当给定的写前日志位置恰好处于写前日志文件边界时,这两个函数都返回前一个写前日志文件的名称。这通常是管理写前日志归档行为的期望行为,因为前一个文件是当前需要归档的最后一个文件。
28.4. 恢复控制函数
表 恢复信息函数中显示的函数提供有关备用服务器当前状态的信息。这些函数可以在恢复期间和正常运行期间执行。
| 函数 | 说明 |
|---|---|
ux_is_in_recovery () → boolean | 如果恢复仍在进行中,则返回 true。 |
ux_last_wal_receive_lsn () → ux_lsn | 返回已通过流复制接收并同步到磁盘的最后一个写前日志位置。在流复制进行时,这将单调递增。如果恢复已完成,则此位置将保持静态,即在恢复期间接收并同步到磁盘的最后一个 WAL 记录的位置。如果禁用流复制,或者如果尚未启动,则该函数返回 NULL。 |
ux_last_wal_replay_lsn () → ux_lsn | 返回恢复期间重播的上一次提前写日志位置。如果经济复苏仍在进行,这个数字将单调增长。如果恢复已经完成,那么在恢复期间应用的最后一个 WAL 记录的位置将保持静态。当服务器正常启动而未恢复时,函数返回 NULL。 |
ux_last_xact_replay_timestamp () → timestamp with time zone | 返回恢复期间重播的最后一个事务的时间戳。这是在主事务上生成该事务的提交或中止 WAL 记录的时间。如果在恢复期间没有重播任何事务,该函数将返回 NULL。否则,如果复苏仍在进行之中,这个数字将单调增长。如果恢复已经完成,那么在恢复期间应用最后一个事务时,这将保持静态。当服务器正常启动而未恢复时,函数返回 NULL。 |
ux_get_wal_resource_managers () → setof record ( rm_id integer, rm_name text, rm_builtin boolean ) | 返回系统中当前加载的 WAL 资源管理器。rm_builtin 列指示它是内置资源管理器,还是由扩展加载的自定义资源管理器。 |
表 恢复控制函数所示的函数控制恢复的进度。这些函数只能在恢复期间执行。
| 函数 | 说明 |
|---|---|
ux_is_wal_replay_paused () → boolean | 如果请求恢复暂停,则返回 true。 |
ux_get_wal_replay_pause_state () → text | 返回恢复暂停状态。如果不请求暂停,则不暂停返回值;如果请求暂停但尚未暂停恢复,则不请求暂停;如果恢复实际上已暂停,则不暂停返回值。 |
ux_promote ( wait boolean DEFAULT true, wait_seconds integer DEFAULT 60 ) → boolean | 将备用服务器提升到主状态。如果 wait 设置为 true(默认值),那么函数将等待升级完成或 wait_second 已经过去,如果升级成功,则返回 true,否则返回 false。如果 wait 设置为 false,则函数在向邮政局长发送 SIGUSR1 信号以触发升级之后立即返回 true。 默认情况下,此函数仅限于超级用户,但可以授予其他用户 EXECUTE 以运行此函数。 |
ux_wal_replay_pause () → void | 请求暂停恢复。请求并不意味着恢复立即停止。如果要保证恢复实际上已暂停,需要检查 ux_get_wal_replay_pause_state() 返回的恢复暂停状态。请注意,ux_is_wal_replay_paused() 返回是否已发出请求。在恢复暂停期间,不会应用任何数据库更改。如果热备机制处于活动状态,则所有新查询将看到数据库的相同一致快照,并且在恢复恢复之前不会生成任何查询冲突。默认情况下,此函数仅限超级用户使用,但可以授予其他用户 EXECUTE 权限以运行此函数。 |
ux_wal_replay_resume () → void | 如果已暂停,则重新启动恢复。 默认情况下,此函数仅限超级用户使用,但可以授予其他用户 EXECUTE 权限以运行此函数。 |
在升级正在进行时,无法执行 ux_wal_replay_pause 和 ux_wal_replay_resume。如果在恢复暂停期间触发了升级,则暂停状态将结束并继续进行升级。
如果禁用流复制,则暂停状态可能会无限期地继续而不会出现问题。如果正在进行流复制,则将继续接收 WAL 记录,这将根据暂停的持续时间、WAL 生成速率和可用磁盘空间最终填满可用磁盘空间。
28.5. 快照同步函数
UXsinoDB 允许数据库会话同步它们的快照。快照确定正在使用快照的事务可以看到哪些数据。当两个或多个会话需要在数据库中看到相同的内容时,同步快照是必要的。如果两个会话独立启动它们的事务,那么总是有可能在两个 START TRANSACTION 命令执行之间提交某个第三个事务,以便一个会话看到该事务的影响,而另一个会话则不会看到。
为解决这个问题,UXsinoDB 允许事务导出它正在使用的快照。只要导出事务保持打开状态,其他事务就可以导入它的快照,并因此保证它们看到与第一个事务完全相同的数据库视图。但请注意,任何导入快照的事务都必须在导出事务之前开始。由这些事务所做的数据库更改对其他事务来说是不可见的,就像未提交的事务所做的更改一样。因此,事务在现有数据方面是同步的,但对它们自己所做的更改是正常的。
快照通过表 快照同步函数中所示的 ux_export_fast 函数导出,并通过 SET TRANSACTION 命令导入。
| 函数 | 描述 |
|---|---|
ux_export_snapshot () → text | 保存事务的当前快照并返回标识快照的文本字符串。此字符串必须(在数据库之外)传递给希望导入快照的客户端。快照只在导出它的事务结束之前可用于导入。 如果需要,事务可以导出多个快照。注意,这样做只在 READ COMMITTED 事务中有用,因为在 REPEATABLE READ 和更高的隔离级别中,事务在其生命周期中使用相同的快照。一旦事务导出了任何快照,就不能使用 PREPARE TRANSACTION 准备它。 |
28.6. 复制管理功能
快照是使用 ux_export_snapshot 函数导出的,该函数在表 快照同步函数中显示,并且使用 SET TRANSACTION 命令导入。许多这些函数在复制协议中都有相应的命令。复制原点的函数仅允许超级用户使用,默认情况下,但可以使用 GRANT 命令允许其他用户使用。
复制插槽的函数仅限于超级用户和具有 REPLICATION 权限的用户使用。
与复制相关的函数还包括表 备份控制函数、表 恢复控制函数和表 快照同步函数中描述的函数。
表 复制管理函数
| 函数 | 描述 |
|---|---|
ux_create_physical_replication_slot ( slot_name name [ , immediately_reserve boolean, temporary boolean ] ) → record ( slot_name name, lsn ux_lsn ) | 创建一个名为 slot_name 的新物理复制槽。可选的第二个参数,当设置为 true 时,指定此复制槽的 LSN 应立即保留;否则,LSN 将在来自流式复制客户端的第一次连接时保留。从物理槽流式更改仅适用于流式复制协议。可选的第三个参数 temporary,当设置为 true 时,指定槽不应永久存储到磁盘,并且仅供当前会话使用。任何错误都会释放临时槽。此函数对应于复制协议命令 CREATE_REPLICATION_SLOT ... PHYSICAL。 |
ux_drop_replication_slot ( slot_name name ) → void | 删除名为 slot_name 的物理或逻辑复制槽。与复制协议命令 DROP_REPLICATION_SLOT 相同。对于逻辑槽,必须在连接到创建槽的同一数据库时调用此函数。 |
ux_create_logical_replication_slot ( slot_name name, plugin name [ , temporary boolean, twophase boolean ] ) → record ( slot_name name, lsn ux_lsn ) | 使用输出插件 plugin 创建一个名为 slot_name 的新逻辑(解码)复制槽。可选的第三个参数 temporary,当设置为 true 时,指定槽不应永久存储到磁盘,并且仅供当前会话使用。任何错误都会释放临时槽。可选的第四个参数 twophase,当设置为 true 时,指定此插槽已启用准备事务的解码。调用此函数的效果与复制协议命令 CREATE_REPLICATION_SLOT ... LOGICAL 相同。 |
ux_copy_physical_replication_slot ( src_slot_name name, dst_slot_name name [ , temporary boolean ] ) → record ( slot_name name, lsn ux_lsn ) | 将现有的物理复制插槽 src_slot_name 复制到物理复制插槽 dst_slot_name。复制的物理插槽从与源插槽相同的 LSN 开始保留 WAL。temporary 是可选的。如果省略 temporary,则使用与源插槽相同的值。 |
ux_copy_logical_replication_slot ( src_slot_name name, dst_slot_name name [ , temporary boolean [ , plugin name ] ] ) → record ( slot_name name, lsn ux_lsn ) | 将现有的逻辑复制插槽 src_slot_name 复制到逻辑复制插槽 dst_slot_name,可选择更改输出插件和持久性。复制的逻辑插槽从与源逻辑插槽相同的 LSN 开始。temporary 和 plugin 都是可选的;如果省略它们,则使用源插槽的值。 |
ux_logical_slot_get_changes ( slot_name name, upto_lsn ux_lsn, upto_nchanges integer, VARIADIC options text[] ) → setof record ( lsn ux_lsn, xid xid, data text ) | 从上次消耗更改的点开始,返回插槽 slot_name 中的更改。如果 upto_lsn 和 upto_nchanges 为 NULL,则逻辑解码将继续直到 WAL 结束。如果 upto_lsn 不为 NULL,则解码仅包括在该 LSN 之前的更改。这些事务在指定的 LSN 之前提交。如果 upto_nchanges 不为 NULL,则在解码产生的行数超过指定值时,解码将停止。但是请注意,实际返回的行数可能更多,因为此限制仅在解码每个新事务提交时添加产生的行后进行检查。 |
ux_logical_slot_peek_changes ( slot_name name, upto_lsn ux_lsn, upto_nchanges integer, VARIADIC options text[] ) → setof record ( lsn ux_lsn, xid xid, data text ) | 与 ux_logical_slot_get_changes() 函数的行为相同,但是不会消耗更改;也就是说,它们将在将来的调用中再次返回。 |
ux_logical_slot_get_binary_changes ( slot_name name, upto_lsn ux_lsn, upto_nchanges integer, VARIADIC options text[] ) → setof record ( lsn ux_lsn, xid xid, data bytea ) | 与 ux_logical_slot_get_changes() 函数的行为相同,但是更改以 bytea 的形式返回。 |
ux_logical_slot_peek_binary_changes ( slot_name name, upto_lsn ux_lsn, upto_nchanges integer, VARIADIC options text[] ) → setof record ( lsn ux_lsn, xid xid, data bytea ) | 与 ux_logical_slot_peek_changes() 函数的行为相同,但是更改以 bytea 的形式返回。 |
ux_replication_slot_advance ( slot_name name, upto_lsn ux_lsn ) → record ( slot_name name, end_lsn ux_lsn ) | 推进名为 slot_name 的复制槽的当前确认位置。槽不会后退,也不会超过当前插入位置。返回槽的名称和实际推进到的位置。如果进行了任何推进,则更新槽位置信息将在下一个检查点写出。因此,在发生崩溃时,槽可能会返回到较早的位置。 |
ux_replication_origin_create ( node_name text ) → oid | 创建具有给定外部名称的复制源,并返回分配给它的内部 ID。 |
ux_replication_origin_drop ( node_name text ) → void | 删除先前创建的复制源,包括任何关联的重放进度。 |
ux_replication_origin_oid ( node_name text ) → oid | 按名称查找复制源并返回内部 ID。如果找不到这样的复制源,则返回 NULL。 |
ux_replication_origin_session_setup ( node_name text ) → void | 将当前会话标记为从给定源进行重放,以便跟踪重放进度。仅当当前未选择源时才能使用。使用 ux_replication_origin_session_reset 进行撤消。 |
ux_replication_origin_session_reset () → void | 取消 ux_replication_origin_session_setup() 的影响。 |
ux_replication_origin_session_is_setup () → boolean | 如果在当前会话中选择了复制源,则返回 true。 |
ux_replication_origin_session_progress ( flush boolean ) → ux_lsn | 返回当前会话中选择的复制源的重放位置。参数 flush 确定相应的本地事务是否已保证已刷新到磁盘。 |
ux_replication_origin_xact_setup ( origin_lsn ux_lsn, origin_timestamp timestamp with time zone ) → void | 将当前事务标记为正在重放已提交于给定 LSN 和时间戳的事务。只能在使用 ux_replication_origin_session_setup 选择了复制源时调用。 |
ux_replication_origin_xact_reset () → void | 取消 ux_replication_origin_xact_setup() 的影响。 |
ux_replication_origin_advance ( node_name text, lsn ux_lsn ) → void | 将给定节点的复制进度设置为给定位置。这主要用于设置初始位置,或在配置更改和类似情况下设置新位置。请注意,不谨慎使用此函数可能会导致数据不一致。 |
ux_replication_origin_progress ( node_name text, flush boolean ) → ux_lsn | 返回给定复制源的重放位置。参数 flush 确定相应的本地事务是否已保证已刷新到磁盘。 |
ux_logical_emit_message ( transactional boolean, prefix text, content text ) → ux_lsnux_logical_emit_message ( transactional boolean, prefix text, content bytea ) → ux_lsn | 发出逻辑解码消息。这可用于通过 WAL 向逻辑解码插件传递通用消息。参数 transactional 指定消息是否应作为当前事务的一部分,或者是否应立即写入并在逻辑解码器读取记录时解码。参数 prefix 是一个文本前缀,逻辑解码插件可以使用它轻松识别对它们有趣的消息。参数 content 是消息的内容,以文本或二进制形式给出。 |
28.7. 数据库对象管理函数
在表 数据库对象大小函数中显示的函数计算数据库对象的磁盘空间使用情况,或者辅助呈现或理解使用结果。bigint 的结果以字节为单位。如果将不表示现有对象的 OID 传递给这些函数之一,则返回 NULL。
| 函数 | 描述 |
|---|---|
ux_column_size ( "any" ) → integer | 显示用于存储任何单个数据值的字节数。如果直接应用于表列值,则反映了任何压缩。 |
ux_column_compression ( "any" ) → text | 显示用于压缩单个可变长度值的压缩算法。如果未压缩该值,则返回 NULL。 |
ux_database_size ( name ) → bigintux_database_size ( oid ) → bigint | 计算具有指定名称或 OID 的数据库使用的总磁盘空间。要使用此函数,您必须具有指定数据库的 CONNECT 权限(默认情况下授予),或者具有 ux_read_all_stats 角色的权限。 |
ux_indexes_size ( regclass ) → bigint | 计算附加到指定表的索引使用的总磁盘空间。 |
ux_relation_size ( relation regclass [ , fork text ] ) → bigint | 计算指定关系的一个“fork”使用的磁盘空间。(请注意,对于大多数目的,更方便的是使用更高级别的函数 ux_total_relation_size 或 ux_table_size,它们总结了所有分支的大小。)使用一个参数,这将返回关系的主数据分支的大小。可以提供第二个参数以指定要检查的分支:• main 返回关系的主数据分支的大小。• fsm 返回与关系相关联的自由空间映射的大小。• vm 返回与关系相关联的可见性映射的大小。• init 返回与关系相关联的初始化分支(如果有)的大小。 |
ux_size_bytes ( text ) → bigint | 将以人类可读格式(由 ux_size_pretty 返回)返回的大小转换为字节。 |
ux_size_pretty ( bigint ) → textux_size_pretty ( numeric ) → text | 将以字节为单位的大小转换为更易于人类阅读的格式,包括大小单位(适当时为字节、kB、MB、GB 或 TB)。请注意,单位是 2 的幂,而不是 10 的幂,因此 1kB 是 1024 字节,1MB 是 10242=1048576 字节,依此类推。 |
ux_table_size ( regclass ) → bigint | 计算指定表使用的磁盘空间,不包括索引(但包括其 TOAST 表(如果有)、自由空间映射和可见性映射)。 |
ux_tablespace_size ( name ) → bigintux_tablespace_size ( oid ) → bigint | 计算指定名称或 OID 的表空间中使用的总磁盘空间。要使用此函数,您必须具有指定表空间的 CREATE 特权或 ux_read_all_stats 角色的特权,除非它是当前数据库的默认表空间。 |
ux_total_relation_size ( regclass ) → bigint | 计算指定表使用的总磁盘空间,包括所有索引和 TOAST 数据。结果等同于 ux_table_size + ux_indexes_size。 |
上述操作表或索引的函数接受 regclass 参数,它只是 ux_class 系统目录中表或索引的 OID。但是,您不必手动查找 OID,因为 regclass 数据类型的输入转换器将为您完成此工作。在表 数据库对象位置函数中显示的函数有助于识别与数据库对象相关联的特定磁盘文件。
| 函数 | 描述 |
|---|---|
ux_relation_filenode ( relation regclass ) → oid | 返回当前分配给指定关系的“filenode”号码。filenode 是用于关系的文件名的基本组件。对于大多数关系,结果与 ux_class.relfilenode 相同,但对于某些系统目录,relfilenode 为零,必须使用此函数获取正确的值。如果传递了没有存储的关系(例如视图),则函数返回 NULL。 |
ux_relation_filepath ( relation regclass ) → text | 返回关系的整个文件路径名(相对于数据库群集的数据目录 UXDATA)。 |
ux_filenode_relation ( tablespace oid, filenode oid ) → regclass | 给定表空间 OID 和存储在其中的 filenode,返回关系的 OID。这基本上是 ux_relation_filepath 的反向映射。对于位于数据库默认表空间中的关系,可以将表空间指定为零。如果当前数据库中没有与给定值相关联的关系,则返回 NULL。 |
表 排序规则管理函数列出了用于管理排序规则的函数。
| 函数 | 描述 |
|---|---|
ux_collation_actual_version ( oid ) → text | 返回排序规则对象的实际版本,因为它当前安装在操作系统中。如果这与 ux_collation.collversion 中的值不同,则返回 NULL。然后,依赖于排序规则的对象可能需要重新构建。 |
ux_database_collation_actual_version ( oid ) → text | 返回数据库当前在操作系统中安装的实际排序规则版本。如果这与 ux_database 中的 datcollversion 的值不同,则依赖于排序规则的对象可能需要重新构建。 |
ux_import_system_collations ( schema regnamespace ) → integer | 基于操作系统中找到的所有区域设置,向系统目录 ux_collation 添加排序规则。这是 initdb 使用的方法。如果稍后将其他区域设置安装到操作系统中,则可以再次运行此函数以添加新区域设置的排序规则。与 ux_collation 中现有条目匹配的区域设置将被跳过。(但是,基于不再存在于操作系统中的区域设置的排序规则对象不会被此函数删除。)schema 参数通常为 ux_catalog,但这不是必需的;排序规则也可以安装到其他模式中。该函数返回它创建的新排序规则对象的数量。此函数的使用受超级用户的限制。 |
表 分区信息函数列出了提供有关分区表结构的信息的函数。
| 函数 | 描述 |
|---|---|
ux_partition_tree ( regclass ) → setof record ( relid regclass, parentrelid regclass, isleaf boolean, level integer ) | 列出给定分区表或分区索引的分区树中的表或索引,每个分区一行。提供的信息包括分区的 OID、其直接父级的 OID、一个布尔值,指示分区是否为叶子节点,以及它在层次结构中的级别。级别值为 0 表示输入表或索引,1 表示其直接子分区,2 表示它们的分区,以此类推。如果关系不存在或不是分区或分区表,则不返回任何行。 |
ux_partition_ancestors ( regclass ) → setof regclass | 列出给定分区的祖先关系,包括关系本身。如果关系不存在或不是分区或分区表,则不返回任何行。 |
ux_partition_root ( regclass ) → regclass | 返回给定关系所属的分区树的最顶层父级。如果关系不存在或不是分区或分区表,则返回 NULL。 |
例如,要检查分区表 measurement 中包含的数据的总大小,可以使用以下查询:
SELECT ux_size_pretty(sum(ux_relation_size(relid))) AS total_size
FROM ux_partition_tree('measurement');
28.8. 索引维护函数
表 索引维护函数显示了可用于索引维护任务的函数。(请注意,这些维护任务通常由自动清理自动完成;仅在特殊情况下需要使用这些函数。)这些函数不能在恢复期间执行。使用这些函数的权限仅限于超级用户和给定索引的所有者。
| 函数 | 说明 |
|---|---|
brin_summarize_new_values ( index regclass ) → integer | 扫描指定的 BRIN 索引,查找当前未由索引汇总的基表中的页面范围;对于任何这样的范围,通过扫描这些表页面创建新的汇总索引元组。返回插入到索引中的新页面范围摘要的数量。 |
brin_summarize_range ( index regclass, blockNumber bigint ) → integer | 汇总覆盖给定块的页面范围(如果尚未汇总)。这就像 brin_summarize_new_values,只是它仅处理覆盖给定表块号的页面范围。 |
brin_desummarize_range ( index regclass, blockNumber bigint ) → void | 如果存在,则删除总结给定表块覆盖的页面范围的 BRIN 索引元组。 |
gin_clean_pending_list ( index regclass ) → bigint | 通过批量将其条目移动到主 GIN 数据结构中,清理指定 GIN 索引的“挂起”列表。返回从挂起列表中删除的页面数。如果参数是使用 fastupdate 选项禁用构建的 GIN 索引,则不进行清理,结果为零,因为该索引没有挂起列表。 |
28.9. 通用文件访问函数
表 通用文件访问函数中显示的函数提供对托管服务器上的文件的本机访问。只能访问数据库群集目录和 log_directory 中的文件,除非用户是超级用户或被授予角色 ux_read_server_files。对于群集目录中的文件,请使用相对路径,对于日志文件,请使用与 log_directory 配置设置匹配的路径。
请注意,授予用户对 ux_read_file() 或相关函数的 EXECUTE 权限允许他们读取数据库服务器进程可以读取的服务器上的任何文件;这些函数绕过所有数据库内特权检查。这意味着,例如,具有此类访问权限的用户能够读取存储身份验证信息的 ux_authid 表的内容,以及读取数据库中的任何表数据。因此,应仔细考虑授予对这些函数的访问权限。
其中一些函数采用可选的 missing_ok 参数,该参数指定文件或目录不存在时的行为。如果为 true,则函数返回 NULL 或适当的空结果集。如果为 false,则会引发错误。默认值为 false。
| 函数 | 说明 | 示例 |
|---|---|---|
ux_ls_dir ( dirname text [ , missing_ok boolean, include_dot_dirs boolean ] ) → setof text | 返回指定目录中所有文件(目录和其他特殊文件)的名称目录。include_dot_dirs 参数指示是否将“.”和“..”包含在结果集中;默认情况下将它们排除在外。将它们包含在内可以在 missing_ok 为 true 时非常有用,以区分空目录和不存在的目录。默认情况下,此函数仅限超级用户使用,但可以授予其他用户 EXECUTE 以运行该函数。 | |
ux_ls_logdir () → setof record ( name text, size bigint, modification timestamp with time zone ) | 返回服务器日志目录中每个普通文件的名称,大小和最后修改时间(mtime)。排除以点开头的文件名,目录和其他特殊文件。 默认情况下,此函数仅限超级用户和具有 ux_monitor 角色特权的角色使用,但可以授予其他用户 EXECUTE 以运行该函数。 | |
ux_ls_waldir () → setof record ( name text, size bigint, modification timestamp with time zone ) | 返回服务器的预写式日志(WAL)目录中每个普通文件的名称,大小和最后修改时间(mtime)。排除以点开头的文件名,目录和其他特殊文件。 默认情况下,此函数仅限超级用户和具有 ux_monitor 角色特权的角色使用,但可以授予其他用户 EXECUTE 以运行该函数。 | |
ux_ls_logicalmapdir () → setof record ( name text, size bigint, modification timestamp with time zone ) | 返回服务器的 ux_logical/mappings 目录中每个普通文件的名称,大小和最后修改时间(mtime)。排除以点开头的文件名,目录和其他特殊文件。默认情况下,此函数仅限超级用户和 ux_monitor 角色的成员使用,但可以授予其他用户 EXECUTE 以运行该函数。 | |
ux_ls_logicalsnapdir () → setof record ( name text, size bigint, modification timestamp with time zone ) | 返回服务器的 ux_logical/snapshots 目录中每个普通文件的名称,大小和最后修改时间(mtime)。排除以点开头的文件名,目录和其他特殊文件。默认情况下,此功能仅限超级用户和 ux_monitor 角色的成员,但可以授予其他用户执行该函数的权限。 | |
ux_ls_replslotdir ( slot_name text ) → setof record ( name text, size bigint, modification timestamp with time zone ) | 返回服务器的 ux_replslot/slot_name 目录中每个普通文件的名称、大小和最后修改时间(mtime),其中 slot_name 是作为函数输入提供的复制槽的名称。排除以点开头的文件名、目录和其他特殊文件。默认情况下,此功能仅限超级用户和 ux_monitor 角色的成员,但可以授予其他用户执行该函数的权限。 | |
ux_ls_archive_statusdir () → setof record ( name text, size bigint, modification timestamp with time zone ) | 返回服务器的 WAL 归档状态目录(ux_wal/archive_status)中每个普通文件的名称、大小和最后修改时间(mtime)。排除以点开头的文件名、目录和其他特殊文件。默认情况下,此功能仅限超级用户和 ux_monitor 角色的成员,但可以授予其他用户执行该函数的权限。 | |
ux_ls_tmpdir ( [ tablespace oid ] ) → setof record ( name text, size bigint, modification timestamp with time zone ) | 返回指定 tablespace 的临时文件目录中每个普通文件的名称、大小和最后修改时间(mtime)。如果未提供 tablespace,则检查 ux_default 表空间。排除以点开头的文件名、目录和其他特殊文件。默认情况下,此功能仅限超级用户和 ux_monitor 角色的成员,但可以授予其他用户执行该函数的权限。 | |
ux_read_file ( filename text [ , offset bigint, length bigint [ , missing_ok boolean ] ] ) → text | 返回文本文件的全部或部分,从给定的字节 offset 开始,最多返回 length 字节(如果首先到达文件结尾,则返回较少)。如果 offset 为负,则相对于文件结尾。如果省略 offset 和 length,则返回整个文件。从文件中读取的字节被解释为数据库编码中的字符串;如果它们在该编码中无效,则会抛出错误。默认情况下,此函数仅限超级用户使用,但可以授予其他用户 EXECUTE 以运行该函数。 | |
ux_read_binary_file ( filename text [ , offset bigint, length bigint [ , missing_ok boolean ] ] ) → bytea | 返回文件的全部或部分。此函数与 ux_read_file 相同,只是它可以读取任意二进制数据,将结果作为 bytea 而不是 text 返回;因此,不执行编码检查。默认情况下,此函数仅限超级用户使用,但可以授予其他用户 EXECUTE 以运行该函数。 与 convert_from 函数结合使用,此函数可用于以指定的编码读取文本文件并转换为数据库的编码:SELECT convert_from(ux_read_binary_file('file_in_utf8.txt'), 'UTF8'); | |
ux_stat_file ( filename text [ , missing_ok boolean ] ) → record ( size bigint, access timestamp with time zone, modification timestamp with time zone, change timestamp with time zone, creation timestamp with time zone, isdir boolean ) | 返回包含文件大小、上次访问时间戳、上次修改时间戳、上次文件状态更改时间戳(仅适用于 Unix 平台)、文件创建时间戳(仅适用于 Windows)和指示是否为目录的标志的记录。 默认情况下,此函数仅限超级用户使用,但可以授予其他用户 EXECUTE 以运行该函数。 |
28.10. 咨询锁功能
在表 咨询锁函数中显示的函数管理咨询锁。
所有这些函数都旨在用于锁定应用程序定义的资源,这些资源可以通过单个 64 位键值或两个 32 位键值来标识(请注意,这两个键空间不重叠)。如果另一个会话已经在相同的资源标识符上持有冲突锁,则函数将等待资源变为可用,或者根据函数的适当性返回 false 结果。锁可以是共享的或排他的:共享锁不会与相同资源上的其他共享锁发生冲突,只会与排他锁发生冲突。锁可以在会话级别(因此它们保持到释放或会话结束)或事务级别(因此它们保持到当前事务结束;没有手动释放的规定)。多个会话级别的锁请求堆叠,因此如果同一资源标识符被锁定三次,则必须有三个解锁请求在会话结束之前释放资源。
| 函数 | 描述 |
|---|---|
ux_advisory_lock ( key bigint ) → voidux_advisory_lock ( key1 integer, key2 integer ) → void | 获取独占会话级别的咨询锁,必要时等待。 |
ux_advisory_lock_shared ( key bigint ) → voidux_advisory_lock_shared ( key1 integer, key2 integer ) → void | 获取共享会话级别的咨询锁,必要时等待。 |
ux_advisory_unlock ( key bigint ) → booleanux_advisory_unlock ( key1 integer, key2 integer ) → boolean | 释放先前获取的独占会话级别的咨询锁。如果成功释放锁,则返回 true。如果锁没有被持有,则返回 false,并且服务器会报告一个 SQL 警告。 |
ux_advisory_unlock_all () → void | 释放当前会话持有的所有会话级别的咨询锁。(即使客户端不正常断开连接,此函数也会在会话结束时隐式调用。) |
ux_advisory_unlock_shared ( key bigint ) → booleanux_advisory_unlock_shared ( key1 integer, key2 integer ) → boolean | 释放先前获取的共享会话级别的咨询锁。如果成功释放锁,则返回 true。如果锁没有被持有,则返回 false,并且服务器会报告一个 SQL 警告。 |
ux_advisory_xact_lock ( key bigint ) → voidux_advisory_xact_lock ( key1 integer, key2 integer ) → void | 获取一个独占的事务级别的咨询锁,必要时等待。 |
ux_advisory_xact_lock_shared ( key bigint ) → voidux_advisory_xact_lock_shared ( key1 integer, key2 integer ) → void | 获取一个共享的事务级别的咨询锁,必要时等待。 |
ux_try_advisory_lock ( key bigint ) → booleanux_try_advisory_lock ( key1 integer, key2 integer ) → boolean | 如果可用,则获取一个独占的会话级别的咨询锁。如果可以立即获取锁,则立即获取并返回 true,否则不等待并返回 false。 |
ux_try_advisory_lock_shared ( key bigint ) → booleanux_try_advisory_lock_shared ( key1 integer, key2 integer ) → boolean | 如果可用,获取共享会话级别的咨询锁。如果可以立即获取锁,则立即获取并返回 true,否则如果无法立即获取锁,则返回 false。 |
ux_try_advisory_xact_lock ( key bigint ) → booleanux_try_advisory_xact_lock ( key1 integer, key2 integer ) → boolean | 如果可用,获取排他事务级别的咨询锁。如果可以立即获取锁,则立即获取并返回 true,否则如果无法立即获取锁,则返回 false。 |
ux_try_advisory_xact_lock_shared ( key bigint ) → booleanux_try_advisory_xact_lock_shared ( key1 integer, key2 integer ) → boolean | 如果可用,获取共享事务级别的咨询锁。如果可以立即获取锁,则立即获取并返回 true,否则如果无法立即获取锁,则返回 false。 |
29. 触发器函数
虽然许多触发器的用途涉及用户编写的触发器函数,但 UXsinoDB 提供了一些内置触发器函数,可以直接在用户定义的触发器中使用。这些函数在表 内置触发器函数中进行了总结。(还存在其他内置触发器函数,用于实现外键约束和延迟索引约束。由于用户不需要直接使用它们,因此这些函数在此处未进行文档化。)
| 函数 | 描述 | 示例用法 |
|---|---|---|
suppress_redundant_updates_trigger ( ) → trigger | 抑制无效的更新操作。有关详细信息,请参见下文。 | CREATE TRIGGER ... suppress_redundant_updates_trigger() |
tsvector_update_trigger ( ) → trigger | 自动从相关的纯文本文档列更新 tsvector 列。要使用的文本搜索配置以名称形式作为触发器参数指定。 | CREATE TRIGGER ... tsvector_update_trigger(tsvcol, 'ux_catalog.swedish', title, body) |
tsvector_update_trigger_column ( ) → trigger | 自动从相关的纯文本文档列更新 tsvector 列。使用的文本搜索配置来自表中的 regconfig 列。 | CREATE TRIGGER ... tsvector_update_trigger_column(tsvcol, tsconfigcol, title, body) |
suppress_redundant_updates_trigger 函数作为行级别的 BEFORE UPDATE 触发器应用时,将阻止任何不实际更改行数据的更新。这将覆盖通常的行为,即始终执行物理行更新,而不管数据是否已更改。(这种正常行为使更新运行更快,因为不需要检查,并且在某些情况下也很有用。)
理想情况下,应避免运行实际上不更改记录中的数据的更新。冗余更新可能会耗费相当多的不必要时间,特别是如果有很多索引需要更改,并且在最终必须进行清理的死行中占用空间。但是,在客户端代码中检测这种情况并不总是容易或可能的,编写表达式来检测它们可能会出错。另一种选择是使用 suppress_redundant_updates_trigger,它将跳过不更改数据的更新。但是,您应该小心使用这个触发器。触发器需要为每个记录花费一些小但不平凡的时间,因此如果更新所影响的大多数记录实际上都会更改,则使用此触发器将使更新平均运行更慢。
可以像这样向表添加 suppress_redundant_updates_trigger 函数:
CREATE TRIGGER z_min_update
BEFORE UPDATE ON tablename
FOR EACH ROW EXECUTE FUNCTION suppress_redundant_updates_trigger();
在大多数情况下,您需要为每行最后触发此触发器,以便它不会覆盖可能希望更改行的任何其他触发器。请记住,触发器按名称顺序触发,因此您将选择一个触发器名称,该名称在表上可能具有的任何其他触发器名称之后。(因此在示例中使用了前缀“z”。)
30. 事件触发器函数
UXsinoDB 提供了这些辅助函数,用于从事件触发器中检索信息。
30.1. 捕获命令结束时的更改
ux_event_trigger_ddl_commands () → setof record
ux_event_trigger_ddl_commands 在附加到 ddl_command_end 事件触发器的函数中调用时,返回每个用户操作执行的 DDL 命令列表。如果在任何其他上下文中调用,将引发错误。
ux_event_trigger_ddl_commands 为执行的每个基本命令返回一行;一些由单个 SQL 语句组成的命令可能会返回多行。此函数返回以下列:
| 名称 | 类型 | 描述 |
|---|---|---|
classid | oid | 对象所属的目录的 OID |
objid | oid | 对象本身的 OID |
objsubid | integer | 子对象 ID(例如,列的属性编号) |
command_tag | text | 命令标签 |
object_type | text | 对象类型 |
schema_name | text | 对象所属的模式名称,如果有的话;否则为 NULL。不应用引号。 |
object_identity | text | 对象标识的文本呈现形式,带有模式限定符。如果需要,每个标识符都会加引号。 |
in_extension | boolean | 如果命令是扩展脚本的一部分,则为 True |
command | ux_ddl_command | 命令的完整表示形式,以内部格式表示。不能直接输出,但可以将其传递给其他函数以获取有关命令的不同信息。 |
30.2. 处理 DDL 命令删除的对象
ux_event_trigger_dropped_objects () → setof record
ux_event_trigger_dropped_objects 返回由其 sql_drop 事件调用的命令删除的所有对象的列表。如果在任何其他上下文中调用,将引发错误。此函数返回以下列:
| 名称 | 类型 | 描述 |
|---|---|---|
classid | oid | 对象所属的目录的 OID |
objid | oid | 对象本身的 OID |
objsubid | integer | 对象的子 ID(如列的属性号) |
original | bool | 如果这是删除中的一个根对象则为真 |
normal | bool | 指示在依赖图中有一个普通依赖关系指向该对象的标志 |
is_temporary | bool | 如果该对象是一个临时对象则为真 |
object_type | text | 对象的类型 |
schema_name | text | 对象所属模式的名称(如果存在);否则为 NULL。不应用引用。 |
object_name | text | 如果模式和名称的组合能被用于对象的一个唯一标识符,则是对象的名称;否则是 NULL。不应用引用,并且名称不是模式限定的。 |
object_identity | text | 对象身份的文本表现,模式限定的。每一个以及所有身份中出现的标识符在必要时加引号。 |
address_names | text[] | 一个数组,它可以和 object_type 及 address_args 一起通过 ux_get_object_address() 函数在一台包含有同类相同名称对象的远程服务器上重建该对象地址。 |
address_args | text[] | 上述 address_names 的补充。 |
ux_event_trigger_dropped_objects 函数可以用于下面这样的事件触发器:
CREATE FUNCTION test_event_trigger_for_drops()
RETURNS event_trigger LANGUAGE pluxsql AS $$
DECLARE
obj record;
BEGIN
FOR obj IN SELECT * FROM ux_event_trigger_dropped_objects()
LOOP
RAISE NOTICE '% dropped object: % %.% %',
tg_tag,
obj.object_type,
obj.schema_name,
obj.object_name,
obj.object_identity;
END LOOP;
END;
$$;
CREATE EVENT TRIGGER test_event_trigger_for_drops
ON sql_drop
EXECUTE FUNCTION test_event_trigger_for_drops();
30.3. 处理表重写事件
表 表重写信息函数中显示的函数提供有关刚刚调用了 table_rewrite 事件的表的信息。
表 表重写信息函数
| 名称 | 返回类型 | 描述 |
|---|---|---|
ux_event_trigger_table_rewrite_oid() | oid | 要被重写的表的 OID。 |
ux_event_trigger_table_rewrite_reason() | int | 解释重写原因的原因代码。这些代码的确切含义在单独的文档中。 |
如果在任何其他上下文中调用,将引发错误。这些函数可以在事件触发器中使用,如下所示:
CREATE FUNCTION test_event_trigger_table_rewrite_oid()
RETURNS event_trigger
LANGUAGE pluxsql AS
$$
BEGIN
RAISE NOTICE 'rewriting table % for reason %',
ux_event_trigger_table_rewrite_oid()::regclass,
ux_event_trigger_table_rewrite_reason();
END;
$$;
CREATE EVENT TRIGGER test_table_rewrite_oid
ON table_rewrite
EXECUTE FUNCTION test_event_trigger_table_rewrite_oid();
31. 统计信息函数
UXsinoDB 提供了一个函数来检查使用 CREATE STATISTICS 命令定义的复杂统计信息。
31.1. 检查 MCV 列表
ux_mcv_list_items ( ux_mcv_list ) → setof record
ux_mcv_list_items 返回一个记录集,描述存储在多列 MCV 列表中的所有项。它返回以下列:
| 名称 | 类型 | 描述 |
|---|---|---|
index | integer | 在 MCV 列表中的项的索引 |
values | text[] | 存储在 MCV 项中的值 |
nulls | boolean[] | 标识 NULL 值的标志 |
frequency | double precision | 此 MCV 项的频率 |
base_frequency | double precision | 此 MCV 项的基础频率 |
ux_mcv_list_items 函数可以像这样使用:
SELECT m.* FROM ux_statistic_ext join ux_statistic_ext_data on (oid = stxoid),
ux_mcv_list_items(stxdmcv) m WHERE stxname = 'stts';
只能从 ux_mcv_list 类型的值中获取 ux_statistic_ext_data 的 stxdmcv 列。
32. 正则表达式函数
正则表达式是一个字符序列,它是定义一个字符串集合(一个正则集合)的缩写。如果一个字符串是正则表达式描述的正则集合中的一员时,就说这个字符串匹配该正则表达式。
对正则表达式的支持可以使应用程序开发人员可以在数据库中实现复杂的模式匹配逻辑,支持的类型为 text,兼容 varchar、char、int 等数据类型。
使用场景如下所示。
- 对于表中的字段进行正则表达式匹配,实现更精准的查找。
- 对于已知字符串直接进行正则表达式匹配。
32.1. REGEXP_COUNT
-
功能
统计 source_char 中匹配到 pattern 的次数。
-
函数
REGEXP_COUNT(source_char, pattern[, position[, match_parameter]]) -
参数
表 regexp_count 参数说明
参数 说明 source_char 搜索值的字符表达式,数据类型支持字符类型、数值类型(包括浮点数),日期和时间型数据类型、大对象类型(clob,blob)。 pattern 匹配模式,支持字符类型,数值类型(包括浮点数)。 position 在 source_char 中开始搜索的起始位置,省略则默认为 1,从字符串第 1 个位置开始搜索,支持数字类型(整数和浮点数均可,浮点数会被四舍五入),支持数值类型的字符串比如 '12' 等,而 'abc' 不可以。除此之外的其他类型均不支持。 match_parameter 控制匹配的行为,如是否区分大小写等。如果省略,则使用数据库默认设置。uxdb 默认为 'gp'。支持字符类型。 -
返回值
返回
pattern在source_char字符串中匹配到的次数,没有匹配到则为 0,返回类型int4。 -
示例
时间类型的输出风格
datestyle为ISO, MDY。select regexp_count('2023-02-28'::timestamp, '8'); regexp_count -------------- 1 (1 行记录) select regexp_count('2023-02-28'::timestamptz, '8'); regexp_count -------------- 2 (1 行记录) select regexp_count('2023-02-28'::date, '8'); regexp_count -------------- 1 (1 行记录) select regexp_count('12:00:00'::time, ':'); regexp_count -------------- 2 (1 行记录) select regexp_count('2023-02-28'::timestamp, '2', 2, 'i'); regexp_count -------------- 3 (1 行记录) select regexp_count(123.455::real, '5'); regexp_count -------------- 2 (1 行记录) select regexp_count(1234.5676::double precision, '6'); regexp_count -------------- 2 (1 行记录) select regexp_count(12345678901234567890::numeric, '0'); regexp_count -------------- 2 (1 行记录) select regexp_count(12345678901234567890::numeric, '1', 2, 'i'); regexp_count -------------- 1 (1 行记录) select regexp_count(12345678901234567890::numeric, 1, 2, 'i'); regexp_count -------------- 1 (1 行记录) select regexp_count(12345678901234567890::numeric, 1, 2.11, 'i'); regexp_count -------------- 1 (1 行记录)
32.2. REGEXP_INSTR
-
功能
查找
source_char中第一个匹配指定正则表达式pattern的位置(下标)。该函数返回一个整数,指示匹配到的子串开始或者结束的子位置(这取决于return_option参数的值)。如果没有找到匹配,则函数返回 0。 -
函数
REGEXP_INSTR(source_char, pattern[, position[, occurrence[, return_option [, match_parameter[, subexpr]]]]] ) -
参数
表 regexp_instr 参数说明
参数 描述 source_char 搜索值的字符表达式,支持字符类型,数值类型(包括浮点数),日期和时间型数据类型,大对象类型(clob,blob)。 pattern 匹配模式,支持字符类型,数值类型(包括浮点数)。 position 在 source_char 中开始搜索的字符位置,省略则默认为 1,从字符串第 1 个位置开始搜索。支持数字类型(整数和浮点数均可,浮点数会被四舍五入),支持数值类型的字符串比如 '12' 等,而 'abc' 不可以。除此之外的其他类型均不支持。 occurrence 模式字符串中的第 n 个匹配位置。如果省略,默认为 1。支持数字类型(整数和浮点数均可,浮点数会被四舍五入),支持数值类型的字符串比如 '12' 等,而 'abc' 不可以。除此之外的其他类型均不支持。 return_option 指定返回的位置。如果指定 0,那么将返回出现的第一个字符的位置。如果指定 1,则返回字符之后发生的位置。默认为 0。支持数字类型(整数和浮点数均可,浮点数会被四舍五入),支持数值类型的字符串比如 '12' 等,而 'abc' 不可以。除此之外的其他类型均不支持。 match_parameter 控制匹配的行为,如是否区分大小写等。如果省略,则使用数据库默认设置。uxdb 默认为 'gp',支持字符类型。 subexpr 指定要返回的子表达式的位置。因为 pattern 的正则表达式,可以带有子表达式,该参数指示 subexpr 的位置。用于指定要返回的子表达式位置。子表达式是正则表达式中用 '()' 括起来的部分,也被称为“捕获组”。如果省略 subexpr 参数,则返回整个匹配的位置(下标)。一个正则表达式中可以有多个子表达式。当一个字符串被正则表达式匹配时,匹配到的子串也被保存到一个数组中,数组中第一个元素表示整个正则表达式匹配到的子串,后面的元素表示每个子表达式匹配到的子串。支持字符类型。 -
返回值
返回根据
pattern匹配到的子串在原字符串中的起始位置(下标),返回类型为int4。如果未找到匹配的子串,则返回 0。 -
示例
时间类型的输出风格
datestyle为ISO, MDY。select regexp_instr('2023-02-28'::timestamp, '8'); regexp_instr -------------- 10 (1 行记录) select regexp_instr('2023-02-28'::timestamptz, '8'); regexp_instr -------------- 10 (1 行记录) select regexp_instr('2023-02-28'::date, '8'); regexp_instr -------------- 10 (1 行记录) select regexp_instr('12:00:00'::time, '2'); regexp_instr -------------- 2 (1 行记录) select regexp_instr('2023-02-28'::timestamp, '2', 2, 1, 1); regexp_instr -------------- 4 (1 行记录) select regexp_instr('2023-02-28'::timestamp, '2023-02-28'::timestamp); regexp_instr -------------- 1 (1 行记录) select regexp_instr(123.456::real, '4'); regexp_instr -------------- 5 (1 行记录) select regexp_instr(1234.5678::double precision, '5'); regexp_instr -------------- 6 (1 行记录) select regexp_instr(12345678901234567890::numeric, '0'); regexp_instr -------------- 10 (1 行记录) select regexp_instr(12345678901234567890::numeric, '(123)(4(56)(78))', 1, 2, 0, 'i', 4); regexp_instr -------------- 17 (1 行记录) select regexp_instr(12345678901234567890::numeric, '(123)(4(56)(78))', 1.1, 2.22, 0.1, 'i', 4.33); regexp_instr -------------- 17 (1 行记录) select regexp_instr(12345678901234567890::numeric, '(123)(4(56)(78))', '1.1', '2.22', '0.1', 'i', '4.33'); regexp_instr -------------- 17 (1 行记录) select regexp_instr('My C'||chr(10)||'ts', 'C.t', 1, 1, 1, 'n'); REGEXP_INSTR -------------- 7 (1 行记录) select regexp_instr('My C'||chr(10)||'ts', 'C.t', 1, 1, 1); REGEXP_INSTR -------------- 0 (1 行记录)
32.3. REGEXP_SUBSTR
-
描述
根据正则表达式模式查找字符串,返回匹配成功的子字符串。此函数符合 POSIX 正则表达式标准(ERE)和(Unicode)正则表达式指南。
-
函数
regexp_substr(source_char, pattern[, position[, occurrence[, match_param[, subexpr]]]]) -
参数
表 regexp_substr 参数说明
参数 描述 source_char用作搜索值的字符表达式,它通常是一个字符列。 pattern正则表达式。 position一个正整数,表示在 source_char 中查找开始的位置。默认值为 1,表示从 source_char 的第一个字符开始查找。 occurrence一个正整数,表示 pattern 在 source_char 中查找的第几次出现,默认值为 1,表示查找 pattern 的第一次出现。 match_param一个字符表达式,允许更改函数的默认匹配行为。 match_param的值可以包含以下一个或多个字符,如下所示。
1. 'i' 指定不区分大小写的匹配。
2. 'c' 指定区分大小写。
3. 'n' 允许句点(.)(即正则表达式中匹配任何字符的字符)与换行符匹配。如果省略此参数,则句点与换行符不匹配。
4. 'm' 将源字符串视为多行。
5. 'x' 忽略空格字符。默认情况下,空格字符与自身匹配。
如果match_param的值包含多个矛盾字符,则使用最后一个字符。subexp一个从 0 到 9 的非负整数,指示函数将返回 pattern 中的哪个子表达式。子表达式可以嵌套。子表达式按照其左括号在模式中的显示顺序进行编号。例如以下表达式 0123(((abc)(de)f)ghi)45(678)有五个子表达式,顺序如下:“abcdefghi”、“abcdef”、“abc”、“de”和“678”。 -
返回值
返回匹配成功的子字符串,类型为
text。 -
示例
两参数使用字符串查找,如下所示。
SELECT REGEXP_SUBSTR('http://www.uxdb.com/products','http://www.uxdb.com/');两参数使用正则表达式查找,如下所示。
SELECT REGEXP_SUBSTR('http://www.uxdb.com/products','http://([[:alnum:]]+\.?){3,4}/?');六参数使用子表达式查找,如下所示。
SELECT REGEXP_SUBSTR('1234567890', '(123)(4(56)(78))', 1, 1, 'i', 4);
32.4. REGEXP_REPLACE_ORACLE
-
功能
REGEXP_REPLACE_ORACLE函数找到符合正则表达式的子字符串,并进行替换,输出替换后的字符串。 -
示例
表中字段的正则匹配,针对表中字段 emailID,从字符串首开始匹配,针对表中字段 empName,从字符串首开始匹配,如果源串中 Jane,就替换成 John,然后输出替换后的结果,默认替换所有匹配项。
SELECT empName, REGEXP_REPLACE_ORACLE(empName, 'Jane', 'John') "STRING_REPLACE" FROM regexp_temp; empname | STRING_REPLACE --------------------------------- John Doe | John Doe Jane Doe | John Doe (2 行记录)字符串直接进行正则匹配,搜索源字符串中,出现两个或两个以上的空格,将其替换成一个空格并输出替换后的字符串。
SELECT REGEXP_REPLACE_ORACLE('500 Oracle Parkway, Redwood Shores, CA', '( ){2,}', ' '); regexp_replace_oracle ------------------------------------------ 500 Oracle Parkway, Redwood Shores, CA (1 行记录)
32.5. regexp_like
-
功能
regexp_like函数从 string 中查找一个匹配并且 pattern 不包含带括号的子表达式,若匹配,返回 true,否则为 false。 -
函数
regexp_like(string, pattern [, flags ]) -
参数
flags参数是一个可选的文本字符串,它包含零个或者更多个可以改变该函数行为的单字母标志。所支持的标志请参见表 ARE 嵌入选项字母。 -
返回值
boolean -
示例
SELECT regexp_like('foobarbequebaz', 'bar.*que'); regexp_like ------------- t (1 row) SELECT regexp_like('foobarbequebaz', '(bar)(beque)'); regexp_like ------------- t (1 row) SELECT regexp_like('foobarbequebaz', '(xxx)'); regexp_like ------------- f (1 row)
33. 空值判断函数
33.1. isnull
-
功能
isnull返回参数列表中第一个非空参数的值,支持一个参数或两个参数,两个参数仅当两个参数都为空时才会返回空。它常用于在为显示目的检索数据时用缺省值替换空值。 -
函数
isnull (value1) isnull (value1, value2) -
返回值
isnull (value1)参数值为空时返回 1,不为空返回 0。参数个数大于二时报错。isnull (value1, value2)第一个参数不为空时返回第一个参数值,第一个参数为空时返回第二个参数值。 -
示例
isnull有一个参数的使用方式,如下所示。select ISNULL(NULL::int); select ISNULL(NULL::numeric); select ISNULL(NULL::varchar); select ISNULL(NULL::text); select ISNULL(NULL::date); select ISNULL(1134::int); select ISNULL(34.56543::numeric); select ISNULL('uxsinodb'::varchar); select ISNULL('fasdgerhgaehgwgwtrhwtg'::text); select ISNULL('2021-09-14'::date);isnull有两个参数的使用方式,如下所示。select isnull(v1, v2) from isnull_test; select isnull(v4, v1) from isnull_test; select isnull(v1) from isnull_test;
33.2. nvl
-
功能
nvl为空值置换函数,返回表达式中第一个参数不为 null 的表达式,如果表达式都是 null,则返回 null。它常用于在为显示目的检索数据时用缺省值替换空值。 -
函数
nvl(expr1, expr2) -
参数
expr1和expr2可以为任意类型,字符串,数值,时间等。 -
返回值
返回值为表达式非空表达式的值。当表达式中的
expr1为 null 时,返回expr2;当expr1不为 null,则返回expr1。 -
示例
select nvl(v1, v2) from nvl_test; nvl -------- 1 5 23123 123 (4 行记录)
34. 数值函数
数值函数主要用于执行数字操作,如对数字进行运算、转换、舍入等。
34.1. CONV
-
功能
CONV函数在不同数基之间对数字 N 进行进制转换。返回数字的字符串表示形式 N(从基数为from_base转换为基数为to_base)。 -
函数
CONV(N, from_base, to_base) -
参数
表 CONV 参数说明
参数 描述 支持类型 N 整数,该参数不可缺省,否则报错。 支持 int、text、bigint、numeric、timestamp、bit、varbinary/binary、bool 类型(注:uxdb 在 mysql 模式下不支持 varbinary 类型)。 from_base 整数,表示入参 N 进行进制转换的起始基数。 支持 int、text、bigint、numeric 四种类型。
支持数字和字符混合字符串。例 '1111abb' 识别为 1111。
支持接收任意长度数字。可接收无限大,但有效范围 64 位数字。
支持小数。
与 mysql-CONV 函数 8.0 版本运行结果一致。
差异:暂时不兼容 UXDB 的 mysql 模式下的 varbinary 类型。to_base 整数,表示入参 N 进行进制转换后的目标基数。 支持 int、text、bigint、numeric 四种类型。
支持数字和字符混合字符串。例 '1111abb' 识别为 1111。
支持接收任意长度数字。可接收无限大,但有效范围 64 位数字。
支持小数。
与 mysql-CONV 函数 8.0 版本运行结果一致。
差异:暂时不兼容 UXDB 的 mysql 模式下的 varbinary 类型。如果任何一个参数为
NULL则函数返回NULL。该参数 N 被解释为整数,但可以指定为整数或字符串。最小基数为 2,最大基数为 36。如果from_base是负数,N 则视为有符号数。否则,N 被视为无符号。CONV( )以 64 位精度工作。
34.2. OCT
-
功能
OCT(N)返回 N 的八进制值的字符串表示形式,相当于 Mysql 函数CONV(N,10,8)。 -
函数
OCT(N) -
参数
N 支持
int、text、bigint、numeric、timestamp、bit、varbinary/binary、bool类型。UXDB 的 mysql 模式下不支持:varbinary。
34.3. BIN_TO_NUM
-
功能
BIN_TO_NUM将位向量转换为等价的十进制数字。这个函数的每个参数(expr)表示位向量中的一个比特位。此函数返回类型NUMERIC。 -
函数
BIN_TO_NUM(expr [, expr ]... ) -
参数
这个函数接受任何数值数据类型,或者任何可以隐式转换为数值的非数值数据类型作为参数。每个
expr必须要求值为 0 或 1。