注意:
- 本教程需要访问 Oracle Cloud。要注册免费账户,请参阅开始使用 Oracle Cloud Infrastructure 免费套餐。
- 它使用 Oracle Cloud Infrastructure 身份证明、租户和区间的示例值。完成实验室时,请将这些值替换为特定于云环境的值。
了解 Oracle Database 23ai 中的 SQL 特性
简介
我们将在本教程中学习 10 个你需要知道的功能,以及它们如何与现有功能进行比较。这些功能包括:
FROM
子句(可选)。BOOLEAN
表示 SQL。IF NOT EXISTS
数据定义语言 (Data Definition Language,DDL) 子句。INSERT
多值。- 新建表
VALUE
构造器。 GROUP BY
子句中的别名。UPDATE
和MERGE
语句的RETURNING
子句。- 在
UPDATE
和DELETE
中进行联接。 - 注释,数据库对象的新元数据。
- 具有 SQL 域的轻量级对象类型。
目标
-
不使用
FROM
子句使用 SQL:通过在选择表达式或内置函数时删除使用FROM
子句的要求来启用更简单的查询。 -
在 SQL 中实施本机
BOOLEAN
数据类型:在 SQL 表、查询和条件中利用本机BOOLEAN
数据类型进行更直观的真/假逻辑处理。 -
在 DDL 语句中使用
IF NOT EXISTS
:通过有条件地执行CREATE
和DROP
语句而不执行额外的 PL/SQL 检查来简化对象创建和删除逻辑。 -
执行多值
INSERT
操作:在单个INSERT
语句中插入多行,以提高代码可读性并减少对数据库的往返次数。 -
使用内嵌数据集的表值构造函数:使用
VALUES
构造函数直接在 SQL 中创建临时行集,支持MERGE
、SELECT
或比较等操作。 -
GROUP BY 子句中的引用列别名:允许在
GROUP BY
中使用SELECT
别名而不是重复表达式,从而提高查询可读性。 -
在
UPDATE
和MERGE
中使用RETURNING
子句:直接从UPDATE
和MERGE
语句检索受影响的数据,而无需后续查询。 -
在
UPDATE
和DELETE
语句中执行联接:直接在UPDATE
和DELETE
操作中使用JOIN
逻辑,以根据相关的表条件修改或删除记录。 -
使用元数据为数据库对象添加注释:使用
ANNOTATION
为数据库对象添加文档来存储描述性元数据(例如,所有者、用途),以便于维护和自测。 -
使用 SQL 域定义轻量级对象类型:创建具有约束力的可重用域类型,以强制在多个表中实现一致性和强类型化。
先决条件
-
基本 SQL 知识。
-
了解 SQL 语法:
SELECT
、INSERT
、UPDATE
、DELETE
、JOIN
、GROUP BY
等。 -
熟悉关系数据库概念和数据类型。
-
-
具备 Oracle Database 23ai 及其早期版本的经验。
-
了解 DDL、数据操纵语言 (Data Manipulation Language,DML) 和 PL/SQL 如何在 Oracle Database 19c、Oracle Database 21c 及更早版本中发挥作用。
-
了解 Oracle 特定的功能,例如
DUAL
、MERGE
、RETURNING INTO
等。
-
-
访问 Oracle Database 23ai 环境。
-
可以访问 Oracle Database 23ai(本地设置、云实例或 Oracle Live SQL)。
-
某些功能(例如 SQL 域或
BOOLEAN
)仅在 Oracle Database 23ai 中有效。
-
-
SQL*Plus、SQLcl 或 GUI 工具(例如 SQL Developer 或 DataGrip)。能够在兼容的界面中运行和测试 SQL 语句。
-
PL/SQL 基础知识(用于高级功能)。对于使用
RETURNING INTO
、过程块和处理动态 SQL。 -
了解约束条件和数据完整性规则。需要了解 SQL 域和表约束条件。
-
熟悉 Oracle 数据字典视图。用于查询注释或元数据。例如,
USER_TABLES
、USER_ANNOTATIONS
。 -
Oracle Database 中的角色和权限。能够创建/变更表、域和注释,需要相应的用户特权。
-
版本感知。确保您的工具和客户端支持 Oracle Database 23ai 功能(较旧的驱动程序或工具可能会失败)。
-
(可选)暴露于其他现代 SQL 方言(PostgreSQL、MySQL 等)。这将帮助您了解
VALUES
、BOOLEAN
和IF EXISTS
等新功能的交叉兼容性。
功能 1:使用 FROM
子句
Oracle Database 23ai 中引入的一个有趣功能是在 SELECT
语句中可选使用 FROM
子句。在此版本之前,需要 FROM
子句。
以下是 Oracle Database 23ai 中没有 FROM
功能的 SELECT
的一些潜在优势。
-
选择当前日期以简化数据处理。
SELECT CURRENT_DATE;
-
不涉及表数据的数学运算或计算。
SELECT 25.50*25.25; 25.50*25.25 ----------- 643.875 Elapsed: 00:00:00.002 1 rows selected.
-
PL/SQL 块,不使用
FROM
子句。CREATE SEQUENCE empno_seq INCREMENT BY 1 START WITH 1 MINVALUE 1 MAXVALUE 1000; Sequence EMPNO_SEQ created. Elapsed: 00:00:00.005 declare v1 number; begin select empno_seq.nextval into v1; dbms_output.put_line ('v1= '||v1); end; / v1= 1 PL/SQL procedure successfully completed. Elapsed: 00:00:00.009
-
用于执行操作或检索值的内置或用户定义的函数。
SELECT DBMS_RANDOM.VALUE() as random_number;
-
字符串操作或转换,不依赖于表数据。
SELECT UPPER('oracle') AS uppercase_text;
-
条件表达式或逻辑表达式,不使用表。
SELECT CASE WHEN 10 > 5 THEN 'True' ELSE 'False' END AS result;
功能 2:使用 BOOLEAN
数据类型
Oracle Database 23ai 引入了新的 BOOLEAN
数据类型。这使用真正的布尔值列/变量,而不是用数字值或 Varchar 模拟它们。编写布尔谓词的功能简化了 SQL 语句的语法。
-
创建一个名为
TEST_BOOLEAN
的表。CREATE TABLE IF NOT EXISTS TEST_BOOLEAN (name VARCHAR2(100), IS_SLEEPING BOOLEAN); Table TEST_BOOLEAN created. Elapsed: 00:00:00.004
-
将数据输入新表中。值
IS_SLEEPING
将NOT NULL
设置为FALSE
作为默认值。ALTER TABLE TEST_BOOLEAN modify (IS_SLEEPING boolean NOT NULL);
ALTER TABLE TEST_BOOLEAN modify (IS_SLEEPING default FALSE); Table TEST_BOOLEAN altered. Elapsed: 00:00:00.014
在这里,您可以看到 Mick、Keith 和 Ron 的不同类型的布尔值输入。所有项都有效。对于 Mick,使用缺省的 FALSE 值 - Mick 未休眠。
1 row inserted. Elapsed: 00:00:00.006
对于 Keith,我们使用 NO 值 -Keith 没有休眠。
INSERT INTO TEST_BOOLEAN (name, is_sleeping) values ('Keith','NO'); 1 row inserted. Elapsed: 00:00:00.002
对于 Ron,我们使用 1 值 - Ron 正在休眠。
-
根据布尔值查看一些结果。
SELECT * FROM test_boolean;
您不再需要记住您设置了什么类型的布尔系统。如前所述,使用 0/1、True/False、Yes/No 或任何其他公用输入将返回准确的表值。
功能 3:使用 IF NOT EXISTS
DDL 子句
从 Oracle Database 23ai 开始,新的 IF NOT EXISTS
DDL 子句允许您决定如何处理 DDL 错误。这简化了 DDL 脚本编写过程,因为脚本可以隐藏由于对象存在或不存在而导致的潜在错误。
-
首先,在不使用此新功能的情况下进行测试。运行以下语句。
DROP TABLE DEPT;
由于没有要删除的现有
DEPT
表,我们将看到一个错误:ORA-00942: table or view does not exist
。 -
但是,在 Oracle Database 23ai 中,我们能够毫无错误地使用
DROP IF EXISTS
。这使我们安心,同时避免错误。现在,运行相同的语句,但包括此新的IF EXISTS
功能。DROP TABLE IF EXISTS DEPT;
-
同样,如果表尚不存在,也可以使用此功能来创建表。创建该
DEPT
表。CREATE TABLE IF NOT EXISTS DEPT (DEPTNO NUMBER(2) CONSTRAINT PK_DEPT PRIMARY KEY, DNAME VARCHAR2(14) , LOC VARCHAR2(13) ) ;
-
使用此功能可以在本教程中创建更多样例表。这里,我们将创建一个名为
EMP
的雇员表。CREATE TABLE IF NOT EXISTS EMP (EMPNO NUMBER(4) CONSTRAINT PK_EMP PRIMARY KEY, ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4), HIREDATE DATE, SAL NUMBER(7,2), COMM NUMBER(7,2), DEPTNO NUMBER(2) CONSTRAINT FK_DEPTNO REFERENCES DEPT); Table EMP created. Elapsed: 00:00:00.006
功能 4:对多个行使用 INSERT
确保与其他常用数据库管理系统更好地共存和兼容的另一个有趣功能是多值 INSERT
语句。
-
例如,在以前版本的 Oracle 数据库中,插入多个行需要为每行单独使用插入语句。
INSERT INTO DEPT VALUES (10,'ACCOUNTING','NEW YORK'); INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS'); INSERT INTO DEPT VALUES (30,'SALES','CHICAGO'); INSERT INTO DEPT VALUES (40,'OPERATIONS','BOSTON'); INSERT INTO DEPT VALUES (50,'HR','LOS ANGELES'); INSERT INTO DEPT VALUES (60,'IT','SAN FRANCISCO'); INSERT INTO DEPT VALUES (70,'MANUFACTURING','DETROIT');
Oracle Database 23ai 引入了允许在单个
INSERT
语句中插入所有这些行的新语法,因此可以在一个 DML 中插入多个元组。运行以下语句。INSERT INTO DEPT VALUES (10,'ACCOUNTING','NEW YORK'), (20,'RESEARCH','DALLAS'), (30,'SALES','CHICAGO'), (40,'OPERATIONS','BOSTON'), (50,'HR','LOS ANGELES'), (60,'IT','SAN FRANCISCO'), (70,'MANUFACTURING','DETROIT');
除了与其他数据库更好的兼容性外,此语句还可用于确保某些插入操作在自动提交模式下的一致性。例如,对于使用此模式处理数据的 Oracle APEX 应用程序,这可能很重要。
-
运行以下语句以使用此功能填写
EMP
表的值。INSERT INTO EMP VALUES (7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,NULL,20), (7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30), (7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30), (7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,NULL,20), (7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30), (7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,NULL,30), (7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,NULL,10), (7788,'SCOTT','ANALYST',7566,to_date('13-JUL-87')-85,3000,NULL,20), (7839,'KING','PRESIDENT',NULL,to_date('17-11-1981','dd-mm-yyyy'),5000,NULL,10), (7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30), (7876,'ADAMS','CLERK',7788,to_date('13-JUL-87')-51,1100,NULL,20), (7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,NULL,30), (7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,NULL,20), (7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,NULL,10);
功能 5:使用新的 VALUE
构造器
从 Oracle 数据库 23ai 开始,扩展了表值构造器。现在,可以在 INSERT
语句中使用它,在单个命令中创建多个行。它也可以在 SELECT
语句和视图因式分解语法中使用。在最后一种情况下,它将简化语句的语法,并避免使用 DUAL
表。
以下语句在飞行中看起来像是一种表函数。
SELECT * FROM (VALUES (50,'HR'), (60,'DEV'), (70,'AI')) virt_dept (deptno, dname);
功能 6:在 GROUP BY
子句中使用别名
Oracle Database 23ai 引入了在 SELECT
语句的 GROUP BY
子句中使用别名的功能。此功能简化了使用复杂表达式编写查询的过程,并可确保与 Teradata、MySQL 和 PostgreSQL 等其他关系数据库更好地兼容。
例如:
SELECT to_char(hiredate,'YYYY') "Year", count(*)
FROM emp
GROUP BY to_char(hiredate,'YYYY');
在 Oracle Database 23ai 中,可以采用更简单的方式编写,如下图所示:
功能 7:使用 UPDATE
和 MERGE
语句的 RETURNING
子句
此子句早先已作为 EXECUTE IMMEDIATE
语句的一部分实施。但是,在 Oracle Database 23ai 中,我们可以将其作为传统静态 DML 语句的一部分进行查找。
-
在这种情况下,它允许从处理的行获取列的旧值和新值。首先,让我们看看王的工资。
SELECT ename, sal FROM emp WHERE ename = 'KING';
-
要在 LiveSQL 中使用变量,我们将总结 PL/SQL 中的语句。运行此脚本。它首先为旧薪金和新薪金创建变量,然后使用
RETURNING
子句更新 King 的薪金以设置变量。然后,我们将查看结果。BEGIN DECLARE old_salary NUMBER; new_salary NUMBER; BEGIN UPDATE emp SET sal = sal + 1000 WHERE ename = 'KING' RETURNING OLD sal, NEW sal INTO old_salary, new_salary; DBMS_OUTPUT.PUT_LINE('Old Salary: ' || old_salary); DBMS_OUTPUT.PUT_LINE('New Salary: ' || new_salary); END; END;
Old Salary: 6000 New Salary: 7000
此示例使用了
UPDATE
语句,但是RETURNING
子句可以与MERGE
语句类似使用。
功能 8:在 UPDATE
和 DELETE
中使用联接
您可以使用基于外部表条件的联接来更新表数据。无需子选择或 IN
子句。
-
运行以下语句以查看研究部门的员工薪金信息。
select e.sal, e.empno from emp e, dept d where e.deptno=d.deptno and d.dname='RESEARCH';
-
要更新薪金信息,在 Oracle Database 23ai 之前,我们需要使用嵌套语句。
UPDATE emp e set e.sal=e.sal*2 WHERE e.deptno in (SELECT d.deptno FROM dept d WHERE e.deptno=d.deptno and d.dname='RESEARCH');
对于 Oracle Database 23ai,您可以按如下方式使用它:
UPDATE emp e set e.sal=e.sal*2 FROM dept d WHERE e.deptno=d.deptno and d.dname='RESEARCH';
-
您可以看到工资已成功更新。
select e.sal, e.empno from emp e, dept d where e.deptno=d.deptno and d.dname='RESEARCH';
功能 9:使用注释
注释是数据库对象的可选元数据。注释可以是名称 - 值对,也可以是名称本身。名称和可选值是自由格式文本字段。注释表示为已添加注释的数据库对象的从属元素。支持的方案对象包括表、视图、实体化视图和索引。使用注释,您可以存储和检索有关数据库对象的元数据。您可以使用它来定制业务逻辑、用户界面或向元数据资料档案库提供元数据。可以在表级别或列级别上添加 CREATE
或 ALTER
语句。
通过注释,您可以存储和检索有关数据库对象的元数据。您可以使用它来定制业务逻辑、用户界面或向元数据资料档案库提供元数据。
-
创建带列和表注释的带注释的表
EMP_ANNOTATED_NEW
。CREATE TABLE emp_annotated_new (empno number annotations(identity, display 'person_identity', details 'person_info'), ename varchar2(50), salary number annotations (display 'person_salary', col_hidden)) annotations (display 'employee_table');
-
数据字典视图(如
USER_ANNOTATIONS
和USER_ANNOTATIONS_USAGE
)有助于监视使用情况。SELECT object_name, object_type, column_name, annotation_name, annotation_value FROM user_annotations_usage;
功能 10:使用 SQL 域
SQL 域是属于方案的字典对象,它封装了一组可选属性和约束条件,并使用 CREATE DOMAIN
语句创建。域提供约束、显示、排序和注释属性。在定义 SQL 域之后,可以定义要与该域关联的表列,从而显式地将域的可选属性和约束条件应用于这些列。
SQL 域允许用户声明列的预期用法。它们是数据字典对象,因此可以轻松重用特定于抽象域的知识。
-
创建名为
yearbirth
的域和名为person
的表。CREATE DOMAIN yearbirth as number(4) constraint check ((trunc(yearbirth) = yearbirth) and (yearbirth >= 1900)) display (case when yearbirth < 2000 then '19-' ELSE '20-' end)||mod(yearbirth, 100) order (yearbirth -1900) annotations (title 'yearformat');
CREATE TABLE person (id number(5), name varchar2(50), salary number, person_birth number(4) DOMAIN yearbirth ) annotations (display 'person_table');
``` 说明人;
Name Null?类型
ID 编号 (5) 名称 VARCHAR2(50) 薪金编号 PERSON_BIRTH 编号 (4) 域名出生年份
INSERT INTO 人员值 (1,'MARTIN',3000,1988);
2. With the new function `DOMAIN_DISPLAY` you can display the property.
SELECT DOMAIN_DISPLAY(person_birth) FROM 人员;

3. Domain usage and annotations can be monitored with data dictionary views. Let us view `user_annotations_usage`.
从 user_annotations_usage 选择 *;
Define reusable domain types (lightweight objects).
创建域 EmailAddress 作为 VARCHAR2(100) 检查(REGEXP_LIKE(值,‘ ^[^@]+@[^@]+.[^@]+$ ’));
CREATE TABLE 用户( user_id NUMBER,电子邮件 EmailAddress );```
Oracle Database 23ai 功能的限制和限制
-
FROM
子句。-
仅适用于函数、文字或变量等简单表达式。
-
不能与涉及表、联接或子查询的查询一起使用。
-
PL/SQL 上下文不支持游标循环需要
FROM
子句。
-
-
本机
BOOLEAN
数据类型。-
可以在表列和表达式中使用。
-
不可索引,无法为具有
BOOLEAN
数据类型的列编制索引。 -
没有在所有客户端工具或报告工具中直接支持(可能需要翻译为 0/1 或 Y/N)。
-
某些较旧的 API 或驱动程序不支持(JDBC/ODBC 客户端可能需要更新)。
-
-
DDL 中的
IF NOT EXISTS
。-
简化幂等的 DDL 脚本。
-
仅适用于特定对象:
TABLE
、INDEX
、SEQUENCE
、VIEW
等。 -
并非所有对象类型都支持此功能(例如,
TRIGGER
和SYNONYM
仍可能需要手动检查)。 -
在较旧的 Oracle 版本中不受支持。
-
-
多值
INSERT
。-
批插入的清除语法。
-
仅限于显式值集不能使用
SELECT
或子查询在同一VALUES
子句中插入。 -
不能在一个步骤中为所有插入的行与
RETURNING
子句组合。
-
-
表值构造器(
VALUES
子句)。-
非常适合小型临时行集。
-
具有行限制(通常为 999 或更少,具体取决于上下文)。
-
未针对大规模负载进行优化,最好对大型数据集使用临时表或暂存。
-
-
GROUP BY
子句中的别名。-
使查询更易于阅读和编写。
-
不受所有分析函数或涉及子查询列的复杂查询支持。
-
在别名重载(例如,内部查询中同名)的查询中,可能会导致混淆。
-
-
RETURNING
第UPDATE
/MERGE
条。-
减少 DML 后对
SELECT
的需求。 -
只能从实际修改的行返回值。
-
不适用于没有
FORALL
的批量更新,必须将 PL/SQL 与显式RETURNING BULK COLLECT
一起使用。
-
-
在
UPDATE
和DELETE
中进行联接。-
使多表逻辑更简单。
-
在某些上下文中仅支持
INNER JOIN
和LEFT JOIN
类型。 -
如果使用较旧的工具或需要与较早的 Oracle 版本兼容,则可能需要对
MERGE
逻辑进行重写。
-
-
注释。
-
非常适合文档记录。
-
注释仅是元数据,在运行时不可执行。
-
需要使用 Oracle 数据字典视图 (
*_ANNOTATIONS
) 进行检索。 -
尚未集成到 Oracle Data Pump 导出/导入或复制工具中。
-
-
具有 SQL 域的轻量级对象类型。
-
可重复使用且一致的类型实施。
-
比完整对象类型(没有方法、属性)更强大。
-
没有继承或组合,仅用于执行基元约束条件。
-
无法在域本身中定义默认值(仍是在列级指定的默认值)。
-
一般限制
-
工具兼容性:许多 GUI 工具和较旧的 Oracle 客户机库可能尚未完全支持 Oracle Database 23ai 语法(尤其是
VALUES
、BOOLEAN
、DOMAIN
)。 -
导出/导入:某些功能(如注释或域)可能不会保留在较早的
expdp
/impdp
工作流中。 -
实验行为:由于这些功能是新功能,因此有些功能可能在次要版本中有所发展—请经常查看补丁程序说明和文档。
相关链接
确认
- 作者 — Aditya Srivastawa(首席云架构师)
更多学习资源
通过 docs.oracle.com/learn 浏览其他实验室,或者通过 Oracle Learning YouTube 频道访问更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 以成为 Oracle Learning Explorer。
有关产品文档,请访问 Oracle 帮助中心。
Explore SQL Features in Oracle Database 23ai
G35702-01
Copyright ©2025, Oracle and/or its affiliates.