表达式是一个或多个值、运算符和 SQL 函数的组合, 计算结果为值。表达式通常假定其组件的数据类型。
可以在中使用表达式:
- select 语句的选择列表SELECT
- WHERE子句和HAVING子句的条件
- BY子句CONNECT、START WITH和ORDER BY
- INSERT语句的VALUES子句
- UPDATE语句的SET子句
简单表达式指定列、伪列、常量、序列号或 null
例子:
employees.last_name
'this is a text string'
10
N'this is an NCHAR string'
复合表达式指定其他表达式的组合。
例子:
('CLARK' || 'SMITH')
LENGTH('MOOSE') * 57
SQRT(144) + 72
my_fun(TO_CHAR(sysdate,'DD-MMM-YY'))
CASE表达式允许使用IF …THEN…ELSE SQL 语句中的逻辑, 而不必调用过程。
- CASE表达式中的最大参数数为65535。
- 可以使用嵌套
- 返回类型必须保持一致
对于示例oe.customers” 表中的每个客户, 以下语句将信用限额列出为 “低”,
如果它等于 $ 100, “高”, 如果它等于 5000, 和 “中等”, 如果它等于其他任何东西。
SELECT cust_last_name,
CASE credit_limit
WHEN 100 THEN
'Low'
WHEN 5000 THEN
'High'
ELSE
'Medium'
END AS credit
FROM oe.customers
ORDER BY cust_last_name, credit;
下面的语句查找示例表oe中雇员的平均工资oe.employees使用最低工资2000元:
SELECT AVG(CASE
WHEN e.salary > 2000 THEN
e.salary
ELSE
2000
END) "Average Salary"
FROM oe.employees e;
列表达式 (在后面的语法图中被指定为column_expression ) 是一个有限的expr形式。
列表达式可以是简单表达式、复合表达式、函数表达式或表达式列表, 但只能包含下列表达式:
- 主题表的列-正在创建、更改或索引的表
- 常量 (字符串或数字)
- 确定性函数-SQL 内置函数或用户定义函数
使用PRIOR的关键字的复合表达式不受支持, 也不是聚合函数。
可以为一下目的使用列表达式:
- 创建基于函数的索引。
- 以显式或隐式定义虚列。定义虚拟列时,
定义的column_expression必须仅引用在当前语句或前面的语句中已定义的主题表的列。- 列表达式的组合组件必须是确定性的。即, 同一组输入值必须返回同一组输出值。
CURSOR表达式返回嵌套游标。这种形式的表达式等效于 PL/SQL REF CURSOR, 可以作为REF CURSOR参数传递给函数。
在计算游标表达式时, 将隐式打开嵌套游标。
例如, 如果游标表达式出现在选择列表中, 则会为查询提取的每一行打开一个嵌套游标。
只有在以下情况下, 嵌套游标才会关闭:
- 嵌套游标由用户显式关闭
- 父游标为重新执行
- 父游标已关闭
- 父游标被取消
- 在读取其父游标之一时出现错误 (它作为清理的一部分关闭)
游标表达式的限制
下列限制适用于CURSOR表达式:
- 如果封闭语句不是SELECT语句, 则嵌套游标只能作为过程的REF CURSOR参数出现。
- 如果封闭语句是SELECT语句, 则嵌套游标也可以出现在查询规范的最外层选择列表中,
或者显示在另一个嵌套游标的最外层选择列表中。
- 嵌套游标不能出现在视图中。
- 不能对嵌套游标执行BIND和EXECUTE操作。
例子:下面的示例演示如何在查询的选择列表中使用CURSOR表达式:
SELECT department_name,
CURSOR (SELECT salary, commission_pct
FROM oe.employees e
WHERE e.department_id = d.department_id)
FROM oe.departments d
ORDER BY department_name;
演示如何将CURSOR表达式用作函数参数。该示例首先在示例OE架构中创建一个可以接受REF CURSOR参数的函数。
CREATE FUNCTION f(cur SYS_REFCURSOR, mgr_hiredate DATE) RETURN NUMBER IS
emp_hiredate DATE;
BEFORE NUMBER := 0;
AFTER NUMBER := 0;
BEGIN
LOOP
FETCH cur
INTO emp_hiredate;
EXIT WHEN cur%NOTFOUND;
IF emp_hiredate > mgr_hiredate THEN
AFTER := AFTER + 1;
ELSE
BEFORE := BEFORE + 1;
END IF;
END LOOP;
CLOSE cur;
IF BEFORE > AFTER THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END;
/
该函数接受游标和日期。该函数期望游标是返回一组日期的查询。下面的查询使用该函数在
“示例employees” 表中查找这些管理器, 其中大部分雇员是在经理之前雇用的。
SELECT e1.last_name
FROM oe.employees e1
WHERE f(CURSOR (SELECT e2.hire_date
FROM oe.employees e2
WHERE e1.employee_id = e2.manager_id),
e1.hire_date) = 1
ORDER BY last_name;
datetime 表达式生成日期时间数据类型之一的值。
初始expr是除标量子查询表达式外的任何表达式, 计算结果为数据类型TIMESTAMP的值、
WITH TIME ZONE时区的时间TIMESTAMP或时间TIMESTAMPWITHLOCALTIMEZONE。
不支持DATE数据类型。如果此expr本身是datetime_expression, 则必须用圆括号括起来。
Datetimes 和间隔可以根据表 3-5中定义的规则进行组合。产生日期时间值的三组合在 datetime 表达式中有效。
如果ATLOCAL指定, 则 Oracle 将使用当前会话时区。时区的设置AT TIME ZONE解释如下:
- 字符串’[+|-]hh:mi ’ 指定一个时区作为与 UTC 的偏移量。对于hh, 指定小时数。对于mi, 指定分钟数。
- DBTIMEZONE: Oracle 在创建数据库期间使用建立的数据库时区 (显式或默认)。
- SESSIONTIMEZONE: Oracle 使用默认情况下建立的会话时区或最近的ALTERSESSION语句。
- time_zone_name: Oracle 返回time_zone_name指示的时区中的datetime_value_expr 。
有关有效时区区域名称的列表, 请查询V$TIMEZONE_NAMES动态性能视图。注意:
时区区域名称由夏时制功能所需。这些名称存储在两种类型的时区文件中: 一个是大的, 一个是小的。
这些文件之一是默认文件, 具体取决于您所使用的环境和 Oracle 数据库的发布。
有关动态性能视图信息的 Oracle 数据库引用
expr: 如果expr返回具有有效时区格式的字符串, 则 Oracle 返回该时区中的输入。否则, Oracle 将返回一个错误。例子
下面的示例将一个时区的日期时间值转换为另一个时区:
SELECT from_tz(CAST(to_date('1999-12-01 11:00:00', 'YYYY-MM-DD HH:MI:SS') AS
TIMESTAMP),
'America/New_York') at TIME ZONE 'America/Los_Angeles' "West Coast Time"
FROM dual;
可以将任何内置 SQL 函数或用户定义函数用作表达式。一些有效的内置函数表达式为:
LENGTH('BLAKE')
ROUND(1234.567*43)
SYSDATE
对用户定义函数表达式的限制:不能将对象类型或XMLType的参数传递给远程函数和过程。
用户定义的函数表达式指定对以下内容的调用:
- oracle 提供的包中的函数
- 用户定义的包或类型或独立用户定义函数中的函数
- 用户定义的函数或运算符
某些有效的用户定义函数表达式为:
circle_area(radius)
payroll.tax_rate(empno)
hr.employees.comm_pct@remote(dependents, empno)
DBMS_LOB.getlength(column_name)
my_function(a_column)
在用作表达式的用户定义函数中, 支持位置、命名和混合表示法。例如, 下列所有符号都是正确的:
CALL my_function(arg1 => 3, arg2 => 4) ...
CALL my_function(3, 4) ...
CALL my_function(3, arg2 => 4) ...
间隔表达式将INTERVALYEAR的值生成TOMONTH或INTERVALDAYTOSECOND。.
表达式expr1和expr2可以是任何计算数据类型DATE、时间TIMESTAMP、TIME ZONETIMESTAMPWITH时区值的表达式
, 或者TIMESTAMPWITHLOCALTIMEZONE.Datetimes 和间隔可以根据表 3-5中定义的规则进行组合。产生间隔值的六组合在间隔表达式中有效。
- leading_field_precision和fractional_second_precision都可以是从0到9的任意整数。
- 如果省略leading_field_precision的任何DAY或YEAR, 则 Oracle 数据库将使用默认值2。
- 如果省略第二个fractional_second_precision , 则数据库使用默认值6。
- 如果查询返回的值包含默认精度的更多位数, 则 Oracle 数据库将返回错误。
- 因此, 最好的做法是指定您知道的精度至少与查询返回的任何值一样大。
例如, 以下语句从系统时间戳 (另一个 datetime 值) 中减去示例表orders(datetime 值) 中
的order_date列的值, 以产生间隔值表达式。尚不知道最早的订单是在多少天前被放置的,
因此指定了DAY前导字段精度的最大值 9:
SELECT (systimestamp - order_date) DAY(9) TO SECOND
FROM oe.orders
WHERE order_id = 2458;
模型表达式仅在SELECT语句的查询中使用, 然后仅用于模型规则的右侧。
它为先前在查询中定义的度量值列中的单元格生成值。在模型表达式中指定度量值列时, 指定的任何条件和表达式都必须解析为单个值。
在模型表达式中指定聚合函数时, 函数的参数是以前在查询中定义的度量值列。
聚合函数只能在模型规则的右侧使用。在模型规则的右侧指定一个解析函数, 可以直接在查询中表达复杂计算。
在模型表达式中使用解析函数时, 会应用以下限制:
- 解析函数只能在UPDATE规则中使用。
- 如果规则的左侧包含FOR循环或ORDER BY by 子句, 则不能在模型规则的右侧指定解析函数.
- 解析函数的OVER子句中的参数不能包含聚合。
- 解析函数的OVER子句之前的参数不能包含单元格引用。
当expr本身是模型表达式时, 它称为嵌套单元格引用。以下限制适用于嵌套单元格引用:
- 只允许一个级别的嵌套。
- 嵌套单元格引用必须是单单元格引用。
- 当在model_rules_clause中指定AUTOMATICORDER时, 只有在嵌套单元格引用中使用的度量值保持静态时,
才能在模型规则的左侧使用嵌套单元格引用。
下面显示的模型表达式基于以下SELECT语句的查询:
SELECT country,prod,year,s
FROM sales_view_ref
MODEL
PARTITION BY (country)
DIMENSION BY (prod, year)
MEASURES (sale s)
IGNORE NAV
UNIQUE DIMENSION
RULES UPSERT SEQUENTIAL ORDER
(
s[prod='Mouse Pad', year=2000] =
s['Mouse Pad', 1998] + s['Mouse Pad', 1999],
s['Standard Mouse', 2001] = s['Standard Mouse', 2000]
)
ORDER BY country, prod, year;
模型表达式表示使用符号表示法的单个单元格引用。它代表老鼠垫的销售为年2000。
sql
s[prod='Mouse Pad',year=2000]
下面的模型表达式使用CV函数表示使用位置表示法的多单元格引用。它代表2001年维度列的当前值的销售额prod 。
s[CV(prod), 2001]
下面的模型表达式表示聚合函数。它表示在维度列的当前值小于二和维度列的当前值之间的年份year中,
鼠标垫的销售额减去一年的总和year 。
SUM(s)['Mouse Pad',year BETWEEN CV()-2 AND CV()-1]
对象访问表达式指定属性引用和方法调用。
列参数可以是对象或REF列。如果指定expr, 则它必须解析为对象类型。当在 SQL 语句的上下文中调用类型的成员函数时, 如果SELF变量为 null, 则 Oracle 返回 null,
并且不调用该函数。例子
下面的示例根据oe.order_item_typ对象类型创建一个表, 然后显示如何从对象列属性中更新和选择。
CREATE TABLE short_orders (
sales_rep VARCHAR2(25), item order_item_typ);
UPDATE short_orders s SET sales_rep = 'Unassigned';
SELECT o.item.line_item_id, o.item.quantity FROM short_orders o;
占位符表达式提供 SQL 语句中的位置, 第三代语言绑定变量将提供一个值。
可以使用可选的指示器变量指定占位符表达式。
这种形式的表达式只能出现在 Oracle 调用接口 (保监) 程序中处理的嵌入式 sql 语句或 sql 语句中。某些有效的占位符表达式为:
- :employee_name INDICATOR :employee_name_indicator_var
- :department_location
Scalar Subquery表达式是一个子查询, 它只从一行返回一列值。
- 标量子查询表达式的值是子查询的选择列表项的值。
- 如果子查询返回0行, 则标量子查询表达式的值为NULL。
- 如果子查询返回多个行, 则 Oracle 将返回一个错误。可以在调用表达式 (expr) 的大多数语法中使用标量子查询表达式。
在所有情况下, 标量子查询必须括在其自己的圆括号中, 即使其语法位置已经将其定位在括号内
(例如, 当标量子查询用作内置函数的参数时)。标量子查询在以下位置不是有效的表达式:
- 作为列的默认值
- 作为群集的哈希表达式
- 在 DML 语句的RETURNING子句中
- 作为基于函数的索引的基础
- 在CHECK约束中
- 在 “GROUPBY” 子句中
- 在与查询无关的语句中, 如CREATE PROFILE
类型构造函数表达式指定对构造函数方法的调用。类型构造函数的参数是任何表达式。
可以在调用函数的任何位置调用类型构造函数。
对类型构造函数调用的限制在对类型构造函数方法的调用中, 即使对象类型具有超过999个属性, 指定的参数 (expr) 数也不能超过999。
此限制仅在从 SQL 调用构造函数时适用。对于来自 pl/sql 的调用, 将应用 pl/sql 限制。NEW关键字适用于对象类型的构造函数, 但不适用于集合类型。
它指示 Oracle 通过调用适当的构造函数来构造一个新对象。NEW关键字的使用是可选的, 但是指定它是很好的做法。如果type_name是对象类型, 则表达式必须是有序列表, 其中第一个参数是其类型与对象类型的第一个属性匹配的值,
第二个参数是一个值, 其类型与第二个对象类型的属性, 等等。
构造函数的参数总数必须与对象类型的属性总数匹配。如果type_name是varray或嵌套表类型, 则表达式列表可以包含零个或多个参数。
零参数意味着构造空集合。否则, 每个参数对应于其类型为集合类型的元素类型的元素值。表达式示例
本示例使用示例oe架构中的cust_address_typ类型在对构造函数方法的调用中显示表达式的用法 (PL/SQL 以斜体显示):
CREATE TYPE address_book_t AS TABLE OF cust_address_typ;
DECLARE
myaddr cust_address_typ :=cust_address_typ(
'500 Oracle Parkway', 94065, 'Redwood Shores', 'CA','USA');
alladdr address_book_t := address_book_t();
BEGIN
INSERT INTO customers VALUES (
666999, 'Joe', 'Smith', myaddr, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
END;
/
子查询示例
本示例使用示例架构oe中的warehouse_typ类型说明子查询在对构造函数方法的调用中的使用。
CREATE TABLE warehouse_tab OF warehouse_typ;
INSERT INTO warehouse_tab
VALUES (warehouse_typ(101, 'new_wh', 201));
CREATE TYPE facility_typ AS OBJECT (
facility_id NUMBER,
warehouse_ref REF warehouse_typ);
CREATE TABLE buildings (b_id NUMBER, building facility_typ);
INSERT INTO buildings VALUES (10, facility_typ(102,
(SELECT REF(w) FROM warehouse_tab w
WHERE warehouse_name = 'new_wh')));
SELECT b.b_id, b.building.facility_id "FAC_ID",
DEREF(b.building.warehouse_ref) "WH" FROM buildings b;
表达式列表是其他表达式的组合
表达式列表可以显示在比较和成员条件中, 并BY查询和子查询的子句GROUP。
比较或成员条件中的表达式列表有时称为行值构造函数或行构造函数.
比较和成员条件出现在WHERE子句的条件中。
它们可以包含一个或多个逗号分隔的表达式或一个或多个表达式集合, 其中每个集合包含一个或多个逗号分隔表达式。
在后一种情况下 (多组表达式):
- 每个集合都由圆括号限定
- 每个集合必须包含相同数量的表达式
- 每个集合中的表达式数必须与比较条件中运算符之前的表达式数和成员条件IN的 in 关键字之前的
表示形式匹配。以逗号分隔的表达式列表可以包含不超过1000个表达式。以逗号分隔的表达式集列表可以包含任意数量的集合,
但每个集合可以包含不超过1000个表达式。
下面是某些条件下的有效表达式列表:
(10, 20, 40)
('SCOTT', 'BLAKE', 'TAYLOR')
( ('Guy', 'Himuro', 'GHIMURO'),('Karen', 'Colmenares', 'KCOLMENA') )
在第三个示例中, 每个集合中的表达式数必须等于条件的第一部分中的表达式数。例如:
SELECT * FROM employees
WHERE (first_name, last_name, email) IN
(('Guy', 'Himuro', 'GHIMURO'),('Karen', 'Colmenares', 'KCOLMENA'))
“比较条件”和在条件条件下
在简单GROUP BY子句中, 可以使用表达式列表的上或下形式:
SELECT department_id, MIN(salary) min, MAX(salary) max FROM employees
GROUP BY department_id, salary
ORDER BY department_id, min, max;
SELECT department_id, MIN(salary) min, MAX(salary) max FROM employees
GROUP BY (department_id, salary)
ORDER BY department_id, min, max;
在 “ROLLUP”、”CUBE” 和 “GROUPING SETS方式”GROUPBY子句中,
可以将单个表达式与同一表达式列表中的表达式集组合在一起。
下面的示例在一个 SQL 语句中显示几个有效的分组集表达式列表:
SELECT
prod_category, prod_subcategory, country_id, cust_city, count(*)
FROM products, sales, customers
WHERE sales.prod_id = products.prod_id
AND sales.cust_id=customers.cust_id
AND sales.time_id = '01-oct-00'
AND customers.cust_year_of_birth BETWEEN 1960 and 1970
GROUP BY GROUPING SETS
(
(prod_category, prod_subcategory, country_id, cust_city),
(prod_category, prod_subcategory, country_id),
(prod_category, prod_subcategory),
country_id
)
ORDER BY prod_category, prod_subcategory, country_id, cust_city;