4、SQL语言概述:SQL分类(DDL、DML、DQL、DCL)、SQL语法基础、数据类型(数值型、字符型、日期时间型等)

SQL(Structured Query Language,结构化查询语言)是关系型数据库的标准操作语言。在openGauss数据库中,SQL语言是用户与数据库交互的核心桥梁,无论是创建表结构、查询业务数据,还是管理用户权限,都离不开SQL语句。本章将系统讲解SQL语言的四大分类(DDL、DML、DQL、DCL),梳理SQL语法的基础构成要素,并深入解析openGauss中常用的数据类型体系。掌握本章内容,是后续学习表设计、索引优化、事务管理以及存储过程开发的重要前提。

SQL语言分类与数据类型知识框架 SQL 语言 DDL 数据定义语言 DML 数据操纵语言 DCL 数据控制语言 DQL 数据查询语言 CREATE / ALTER / DROP TRUNCATE / RENAME COMMENT / 表结构管理 INSERT / UPDATE / DELETE MERGE / CALL 数据行级操作 GRANT / REVOKE CREATE USER / ALTER USER 权限与角色管理 SELECT / FROM / WHERE GROUP BY / HAVING / ORDER BY JOIN / 子查询 / 聚合函数 数据类型:数值型(INT/NUMERIC) | 字符型(VARCHAR/TEXT) | 日期时间型(TIMESTAMP/DATE) | 其他(BOOLEAN/JSON)

4.1 SQL四大分类:DDL、DML、DQL、DCL

4.1.1 核心原理:SQL分类的职责边界

SQL语言按照功能职责划分为四大类别,每一类解决不同层次的数据操作问题。理解分类的核心在于明确“操作对象”和“操作性质”:DDL操作的是数据库对象的结构(如表、索引、视图、序列),DML操作的是表中的数据行,DQL负责数据的检索与聚合,DCL管理访问权限与用户安全。在openGauss中,这四类语句的执行机制、锁行为以及事务影响各不相同。例如,DDL语句在openGauss中通常采用隐式提交方式,执行后立即生效且不可回滚;而DML语句则受事务控制,可以通过COMMIT或ROLLBACK决定最终结果。

4.1.2 分类详解与操作流程

分类 核心关键字 操作对象 典型场景 事务特性
DDL CREATE、ALTER、DROP、TRUNCATE 表、索引、视图、序列、模式 创建订单表、修改字段类型、删除过期表 隐式提交,不可回滚
DML INSERT、UPDATE、DELETE、MERGE 表中的数据行 新增订单记录、修改库存数量、删除失效数据 受事务控制,可回滚
DQL SELECT、FROM、WHERE、GROUP BY 查询结果集 统计月度销售额、关联查询用户订单 只读,不修改数据
DCL GRANT、REVOKE、CREATE USER 用户、角色、权限 授予应用账号只读权限、回收离职员工权限 隐式提交

在实际操作中,判断一条SQL语句属于哪一类别,可以遵循以下流程:第一步,观察语句的第一个关键字;第二步,判断操作目标是“结构”还是“数据”;第三步,确认是否需要事务控制。例如,ALTER TABLE修改的是表结构,属于DDL;UPDATE修改的是数据内容,属于DML。

经验提示:在openGauss中,TRUNCATE虽然删除的是数据,但被归类为DDL,因为它直接释放存储空间且不可通过事务回滚。如果业务需要可回滚的“清空表”操作,应使用DELETE FROM(DML)而非TRUNCATE。

4.1.3 案例拆解:电商订单表的结构与数据操作

假设某电商平台需要新建一张订单表,并完成日常数据维护。整个操作链路清晰地展示了四类SQL的协同工作:

  1. DDL阶段:使用CREATE TABLE创建订单表,定义字段、主键和约束。
  2. DML阶段:业务系统通过INSERT写入新订单,通过UPDATE更新订单状态。
  3. DQL阶段:运营人员使用SELECT统计每日订单量、销售额等指标。
  4. DCL阶段:DBA创建只读账号供数据分析师使用,通过GRANT SELECT授权。
-- 1. DDL:创建订单表
CREATE TABLE orders (
    order_id     BIGINT PRIMARY KEY,
    customer_id  INT NOT NULL,
    amount       NUMERIC(10,2) CHECK (amount >= 0),
    status       VARCHAR(20) DEFAULT 'PENDING',
    created_at   TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 2. DML:插入新订单
INSERT INTO orders (order_id, customer_id, amount) VALUES (1001, 501, 299.00);

-- 3. DQL:查询今日订单总额
SELECT SUM(amount) AS total_amount FROM orders WHERE created_at >= CURRENT_DATE;

-- 4. DCL:创建只读用户并授权
CREATE USER analyst WITH PASSWORD 'Secure@123';
GRANT SELECT ON orders TO analyst;
风险提醒:DDL语句(如DROP TABLE)执行后无法恢复,在生产环境操作前务必确认对象名称,并建议先进行逻辑备份或使用pg_dump导出表结构。

4.2 SQL语法基础

4.2.1 核心原理:SQL语句的组成要素

一条完整的SQL语句由多个语法元素构成,包括关键字(如SELECT、FROM)、标识符(表名、列名)、表达式(计算逻辑)、运算符(比较、逻辑)、字面量(字符串、数字)以及注释。openGauss遵循SQL标准,同时扩展了部分语法特性。SQL语句的书写不区分大小写(字符串内容区分),但习惯上关键字使用大写以增强可读性。每条SQL语句以分号(;)结尾,openGauss支持多条SQL语句批量执行。

4.2.2 语法规范与执行顺序

SQL语句的书写顺序与逻辑执行顺序并不完全一致。以最常用的SELECT查询为例,其书写顺序为:SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT。而数据库引擎的逻辑执行顺序为:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT。理解这一差异对于编写高效SQL至关重要,例如在WHERE子句中不能使用SELECT中定义的别名,因为WHERE先于SELECT执行。

-- 示例:查询每个客户的订单总额,仅显示订单总额大于1000的客户,按金额降序排列
SELECT customer_id, SUM(amount) AS total_spent
FROM orders
WHERE status = 'COMPLETED'
GROUP BY customer_id
HAVING SUM(amount) > 1000
ORDER BY total_spent DESC;

4.2.3 常见误区与总结复盘

  • 误区一:混淆WHERE与HAVING。WHERE用于过滤原始行,HAVING用于过滤分组后的结果。
  • 误区二:在GROUP BY查询中,SELECT子句只能包含分组列或聚合函数,否则openGauss会报错。
  • 误区三:忽略NULL值的处理。在WHERE条件中使用= NULL永远不成立,必须使用IS NULL。
复盘要点:SQL语法基础的核心是“先确定数据源(FROM),再逐步过滤(WHERE)、分组(GROUP BY)、筛选分组(HAVING),最后投影(SELECT)和排序(ORDER BY)”。掌握这一思维模型,复杂查询也能拆解为简单步骤。

4.3 数据类型详解

4.3.1 核心原理:数据类型的作用与选择原则

数据类型定义了列中可存储数据的种类、取值范围以及存储空间。在openGauss中,选择合适的数据类型不仅影响存储效率,还直接关系到查询性能和计算精度。数据类型的选择应遵循最小化原则(够用就好)、精度优先原则(涉及金额使用NUMERIC而非FLOAT)以及兼容性原则(考虑与业务系统的数据交互)。

4.3.2 常用数据类型对比

类别 数据类型 存储大小 取值范围/说明 适用场景
数值型 SMALLINT 2字节 -32,768 ~ 32,767 小范围整数,如年龄
INTEGER (INT) 4字节 -2^31 ~ 2^31-1 常规整数,如订单号
BIGINT 8字节 -2^63 ~ 2^63-1 大整数,如流水号
NUMERIC(p,s) 可变 精确小数,p为精度,s为小数位 金额、税率等精确计算
字符型 VARCHAR(n) 可变 变长字符串,n为最大长度 用户名、地址等变长文本
CHAR(n) 定长n字节 定长字符串,不足补空格 固定长度编码,如身份证号
TEXT 可变 无限长度文本 文章内容、备注字段
日期时间型 DATE 4字节 日期,格式YYYY-MM-DD 生日、入职日期
TIME 8字节 时间,格式HH:MM:SS 营业时间、定时任务
TIMESTAMP 8字节 日期+时间,精确到微秒 订单创建时间、日志时间
其他 BOOLEAN 1字节 TRUE / FALSE / NULL 状态开关、逻辑标记

4.3.3 实战场景:订单表的数据类型设计

在设计订单表时,数据类型的选择直接影响业务正确性。以下是一个经过优化的设计示例:

CREATE TABLE order_detail (
    order_id      BIGINT NOT NULL,              -- 订单ID,使用BIGINT避免溢出
    product_code  VARCHAR(32) NOT NULL,         -- 商品编码,变长字符串
    quantity      SMALLINT CHECK (quantity > 0), -- 数量,小整数足够
    unit_price    NUMERIC(10,2) NOT NULL,       -- 单价,精确到分
    discount_rate NUMERIC(4,2) DEFAULT 1.00,    -- 折扣率,如0.85表示85折
    order_time    TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 下单时间
    is_gift       BOOLEAN DEFAULT FALSE,        -- 是否赠品
    remark        TEXT                          -- 备注,允许长文本
);
设计建议:金额字段务必使用NUMERIC类型,避免使用FLOAT/DOUBLE导致的精度丢失。例如,0.1 + 0.2在浮点运算中可能得到0.30000000000000004,而NUMERIC可以精确表示。

4.3.4 常见误区与总结复盘

  • 误区一:过度使用TEXT类型存储短字符串,导致索引效率下降。对于长度固定的短文本,优先使用VARCHAR(n)并设置合理上限。
  • 误区二:忽略TIMESTAMP的时区问题。openGauss的TIMESTAMP不带时区,如果需要存储全球统一时间,应使用TIMESTAMP WITH TIME ZONE。
  • 误区三:使用INT存储手机号或身份证号,导致精度丢失。这类数据应使用VARCHAR存储。
总结复盘:数据类型是SQL语言的基石。在openGauss中,合理的数据类型设计能够减少存储空间、提升查询性能、避免计算误差。建议在创建表之前,先梳理业务字段的“数据特征”(长度、精度、取值范围),再对照数据类型表进行选择。对于不确定的场景,优先参考openGauss官方文档中的数据类型兼容性矩阵。