CASE_SENSITIVE 是达梦数据库的建库(初始化)参数,用于控制标识符(对象名)的大小写敏感。
官方定义:当大小写敏感时,小写的标识符应用双引号 "" 括起,否则被系统自动转换为大写;当大小写不敏感时,系统不自动转换标识符的大小写,系统比较函数会将大写字母全部转为小写字母再进行比较。
表格
| 影响对象 | 大小写敏感( Y ) | 大小写不敏感( N ) |
|---|---|---|
| 标识符(表名、列名、索引名、视图名等) | 不加双引号自动转大写;加双引号固定原大小写;可存在同名不同大小写的对象 | 加不加双引号都不转换大小写;不允许存在同名对象,即使大小写不同 |
| 业务数据(字符串值) | 数据存储及数据比较 都区分 大小写 | 数据 存储保持原有大小写 ,但 比较时默认不区分 |
| 模式( Schema ) | 可拥有两个同名不同大小写的模式(须属同一用户) | 只可拥有大写的模式名 |
| 用户名与密码 | 均不受该参数影响 :用户名始终强转为大写,密码始终区分大小写 | 同左 |
表格
| 项目 | 说明 |
|---|---|
| 参数名 | CASE_SENSITIVE |
| 功能 | 标识符大小写敏感 |
| 取值 | Y /y/ 1 表示敏感; N /n/ 0 表示不敏感 |
| 缺省值 | Y(敏感) |
| 参数性质 | 建库参数(初始化参数), 数据库创建成功后无法修改 |
| 查询函数 | SF_GET_CASE_SENSITIVE_FLAG () 或 CASE_SENSITIVE () |
CASE_SENSITIVE 只能在初始化数据库实例时设定。命令行方式如下。
实例一:开启大小写敏感(默认值,可省略 case_sensitive 参数)
[root@localhost bin]# ./dminit path=/dmdata/data DB_NAME=db1 instance_name=db1 port_num=6001 case_sensitive=1 SYSDBA_PWD=Dameng123 SYSAUDITOR_PWD=Dameng123
实例二:关闭大小写敏感
[root@localhost bin]# ./dminit path=/dmdata/data DB_NAME=db2 instance_name=db2 port_num=6002 case_sensitive=0 SYSDBA_PWD=Dameng123 SYSAUDITOR_PWD=Dameng123
三种方法任选其一,都可以查看大小写敏感状态。
表格
| 方法 | 操作 |
|---|---|
| 方法一 | 查看实例初始化目录下的 dminit*.log 初始化日志文件 |
| 方法二 | DM 管理工具 → 右键数据库 → 管理服务器 → 查看系统概览 |
| 方法三 | SQL 查询 |
方法三的 SQL 语句:
-- 系统函数:返回 1 = 大小写敏感,0 = 不敏感
SELECT CASE_SENSITIVE();
SELECT SF_GET_CASE_SENSITIVE_FLAG();
-- 也可从参数视图查询
SELECT PARA_NAME, PARA_VALUE FROM V$DM_INI
WHERE PARA_NAME LIKE '%CASE_SENSITIVE%';
图片占位:实例 1 disql 查询返回 1 截图
图片占位:实例 2 disql 查询返回 0 截图
CASE_SENSITIVE 属于「初始化时定死」的一组参数,一旦库初始化完成,无法通过 ALTER SYSTEM、SP_SET_PARA_VALUE 等任何方式修改,只能删除实例重新初始化。
表格
| 同为「初始化定死」的常见参数 | 查询函数 |
|---|---|
| CASE_SENSITIVE (大小写敏感) | SF_GET_CASE_SENSITIVE_FLAG() / CASE_SENSITIVE() |
| CHARSET / UNICODE_FLAG (字符集) | SF_GET_UNICODE_FLAG() / UNICODE() |
| PAGE_SIZE (页大小) | SF_GET_PAGE_SIZE() / PAGE() |
| EXTENT_SIZE (簇大小) | SF_GET_EXTENT_SIZE() |
| BLANK_PAD_MODE (空格填充模式) | 查 V$PARAMETER |
结论:CASE_SENSITIVE 必须在规划阶段就确定,选错了代价是重建数据库并迁移全部数据。
用 disql 连接 6001 端口,先确认参数状态。
-- 建表:表名与列名都不加双引号
create table Table1(id int, "id1" int, "iD2" int);
-- 查看数据字典中实际存储的对象名
select TABLE_NAME FROM dba_tables where OWNER='SYSDBA';
-- 查看表结构
desc Table1;
现象:不加双引号的表名和列名,存进数据字典后都是大写(TABLE1、ID);加了双引号的列名("id1"、"iD2")则保持原样。
结论:开启大小写敏感时,会把不加双引号的对象转换为大写,保持双引号内对象的大小写状态不变。
紧接着上一步,继续执行:
create table TABLE1(id int, "id1" int, "iD2" int);
create table table1(id int, "id1" int, "iD2" int);
create table "TAble1"(id int, "id1" int, "iD2" int);
图片占位:实验二执行结果截图
表格
| 语句 | 结果 | 原因 |
|---|---|---|
| create table Table1(...) | 成功 | 表名转大写 → TABLE1 |
| create table TABLE1(...) | 失败 | 也是 TABLE1 ,已存在 |
| create table table1(...) | 失败 | 转大写后仍为 TABLE1 ,已存在 |
| create table "TAble1"(...) | 成功 | 双引号固定大小写, TAble1 ≠ TABLE1 ,视为不同对象 |
结论:不加双引号时,字符串拼写相同、仅大小写不同的对象会被认定为等同;加上双引号之后,拼写相同但大小写不同的对象会被识别为不同对象。
-- 情形 A:建表时表名不加双引号 → 实际存储为 ABC
CREATE TABLE TEST.Abc(COL INT);
SELECT * FROM TEST.Abc; -- 执行成功
SELECT * FROM TEST.ABC; -- 执行成功
SELECT * FROM TEST."Abc"; -- error:语法分析报错
SELECT * FROM TEST."ABC"; -- 执行成功
图片占位:情形 A 执行截图
-- 情形 B:建表时表名加双引号 → 实际存储为 Abc
CREATE TABLE TEST."Abc"(COL INT); -- 执行之前需要drop掉情形A中的TEST.Abc
SELECT * FROM TEST.Abc; -- error:无效的表或视图名[ABC]
SELECT * FROM TEST.ABC; -- error:无效的表或视图名[ABC]
SELECT * FROM TEST."Abc"; -- 执行成功
SELECT * FROM TEST."ABC"; -- error:无效的表或视图名[ABC]
规律总结:
create table Table1(id int);
select TABLE_NAME FROM dba_tables where OWNER='SYSDBA';
desc Table1;
create table "tAble1"(id int);
create table TABLE1(id int);
表格
| 语句 | 结果 | 说明 |
|---|---|---|
| create table Table1(id int); | 成功 | 表名 未做大小写转换 ,原样存为 Table1 |
| desc Table1; | 成功 | 直接引用即可 |
| create table "tAble1"(id int); | 失败 | 报「对象已存在」 |
| create table TABLE1(id int); | 失败 | 报「对象已存在」 |
结论:大小写敏感状态关闭时,比较表名时字符均被转换为小写再比较,所以只要字符串拼写一样,无论大小写,对象均认为是等同的。
不敏感模式下,引号不再具备区分大小写的能力:
CREATE TABLE a(C1 INT);
SELECT * FROM a; -- 成功
SELECT * FROM A; -- 成功
SELECT * FROM "a"; -- 成功
SELECT * FROM "A"; -- 成功
图片占位:a 表查询截图
CREATE TABLE "b"(C1 INT);
SELECT * FROM b; -- 成功
SELECT * FROM B; -- 成功
SELECT * FROM "b"; -- 成功
SELECT * FROM "B"; -- 成功
图片占位:b 表查询截图
表格
| 对比项 | 大小写敏感( Y ) | 大小写不敏感( N ) |
|---|---|---|
| 不加双引号创建 | 自动转大写 | 原样保留 |
| 加双引号创建 | 固定原大小写 | 原样保留(引号无区分作用) |
| 同名不同大小写对象 | 允许(视为不同对象) | 不允许 |
| 表中同名字段(仅大小写不同) | 允许 | 不允许 |
| 查询不带引号 | 先转大写到库里找 | 转小写比较后找 |
| 查询带引号 | 精确匹配,大小写必须一致 | 照样能命中 |
CREATE TABLE MMJ(COL VARCHAR(100));
INSERT INTO MMJ VALUES ('Abc');
INSERT INTO MMJ VALUES ('ABC');
表格
| 查询语句 | 敏感库结果 | 不敏感库结果 |
|---|---|---|
| SELECT COUNT(*) FROM MMJ WHERE COL='Abc'; | 1 | 2 |
| SELECT COUNT(*) FROM MMJ WHERE COL='ABC'; | 1 | 2 |
表格
| 对象 | 是否受 CASE_SENSITIVE 影响 | 规则 |
|---|---|---|
| 用户名 | 不受影响 | 始终强转为 大写 ,无论是否使用双引号包裹; CREATE USER 、 ALTER USER 均如此 |
| 用户密码 | 不受影响 | 始终 区分大小写 |
| 模式名 | 受影响 | 敏感库:允许两个同名不同大小写的模式(须属同一用户);不敏感库:只允许大写的模式名 |
用户名规则的实测表现(两种库都一样):
create user "bb" identified by "Dameng@123"; -- 成功
create user "BB" identified by "Dameng@123"; -- 报错:对象[BB]已存在
表格
| 工具 | 敏感库 | 不敏感库 |
|---|---|---|
| disql | 小写对象必须双引号且大小写一致;密码含 @ 、 / 等需转义 | 双引号可有可无 |
| DM 管理工具(manager) | 图形化建小写对象会自动加双引号 → 查询必须带双引号、大小写一致 | 建对象、查对象都无需双引号 |
| DTS 迁移工具 | 想让源库的小写对象保持小写 → 必须勾选「保持对象名大小写」,之后查询 必须 用双引号;不勾选则统一转大写,查询无需双引号 | 勾不勾选都能保持小写,且查询都 不需要 双引号 |
表格
| 项目 | 说明 |
|---|---|
| 参数名 | CHARSET (别名 UNICODE_FLAG ) |
| 功能 | 字符集选项,决定字符在库内的编码方式与字节占用 |
| 取值 | 0 = GB18030 ; 1 = UTF-8 ; 2 = EUC-KR (韩文) |
| 缺省值 | 0(GB18030) |
| 参数性质 | 建库(初始化)参数, 数据库创建成功后无法修改 |
| 查询函数 | SF_GET_UNICODE_FLAG () 或 UNICODE () |
各编码的字节占用规则
表格
| 字符集 | 数字 / 字母 | 普通汉字 | 特殊字符 |
|---|---|---|---|
| GB18030 | 1 字节 | 2 字节 | 部分繁体及少数民族文字占 4 字节 |
| UTF-8 (达梦中的 Unicode 实现) | 1~2 字节 | 3 字节 | 附加字符占 4 字节 |
| EUC-KR | 1 字节 | — | 韩文字符 |
表格
| 项目 | 说明 |
|---|---|
| 参数名 | LENGTH_IN_CHAR |
| 功能 | VARCHAR 类型对象的长度是否以字符为单位 |
| 取值 | 1 / Y = 以字符为单位; 0 / N = 以字节为单位 |
| 缺省值 | 0(以字节为单位) |
| 参数性质 | 建库(初始化)参数, 数据库创建成功后无法修改 ; 新版本已废弃 |
| 查询函数 | SF_GET_LENGTH_IN_CHAR() |
表格
| CHARSET | LENGTH_IN_CHAR=1 时的放大倍数 | 依据 |
|---|---|---|
| GB18030 | 2 倍 | 一个字符理论上最多占 2 字节 |
| UTF-8 | 4 倍 | 一个字符理论上最多占 4 字节 |
VARCHAR (10) 在 LENGTH_IN_CHAR=1 下:
自 2024 年第二季度(Q2)之后的版本(例如 dm8_20240715 系列)起,LENGTH_IN_CHAR 参数已被正式废弃:
VARCHAR(n CHAR)。统一实验条件:按 GB18030 字符集、页大小 32K 建库,建表语句 CREATE TABLE t(name VARCHAR(10));
CREATE TABLE t(name VARCHAR(10));
INSERT INTO t VALUES('ABCDEFGHIJ'); -- 成功(10 个英文 = 10 字节)
INSERT INTO t VALUES('ABCDEFGHIJA'); -- 失败:超长(11 字节 > 10)
INSERT INTO t VALUES('测试一下测'); -- 成功(5 个汉字 = 10 字节)
INSERT INTO t VALUES('测试一下测试'); -- 失败:超长(6 个汉字 = 12 字节)
现象:英文能存 10 个、汉字只能存 5 个;定义值 10 就是 10 字节的硬上限。
结论:以字节为单位时,中文列的可存字数约为定义值的一半(GB18030)或三分之一(UTF-8)。按字符去估算必然算错。
新版本不必依赖库级参数,直接在建表时列级指定:
-- 明确表示「可存储 100 个字符」,与库级 LENGTH_IN_CHAR 无关
CREATE TABLE test (
name VARCHAR(100 CHAR)
);
-- CHAR 类型同样支持
CREATE TABLE test2 (
code CHAR(20 CHAR)
);
表格
| 做法 | 生效层级 | 适用版本 | 建议 |
|---|---|---|---|
| 库级 LENGTH_IN_CHAR=1 | 全库所有 VARCHAR | 老版本 | 仅在维护老库时沿用 |
| 列级 VARCHAR (n CHAR) | 单列 | 全部版本 | 新库一律用这个 |
| 手工放大精度 | 单列 | 全部版本 | 如 GB18030 按 ×2 、 UTF-8 按 ×3 预先放大 |
表格
| 插入内容 | GB18030 ( CHARSET=0 ) | UTF-8 ( CHARSET=1 ) |
|---|---|---|
| 10 个英文 | 成功 | 成功 |
| 11 个英文 | 失败 | 失败 |
| 3 个汉字 | 成功 | 成功 |
| 4 个汉字 | 成功( 8 字节) | 失败 ( 12 字节 > 10 ) |
| 5 个汉字 | 成功( 10 字节) | 失败 |
| 6 个汉字 | 失败 | 失败 |
| 5 汉字 + 1 英文 | 失败 ( 11 字节) | 失败 |
| 3 汉字 + 1 英文 | 成功 | 成功( 10 字节) |
| 3 汉字 + 2 英文 | 成功( 3×2+2 = 8 字节) | 失败( 3×3+2 = 11 字节) |
结论:同一张表结构,换字符集就等于换容量。UTF-8 下中文列的可存字数只有 GB18030 的约 2/3;中英混合列在 UTF-8 下尤其容易超长。
CHARSET 与 LENGTH_IN_CHAR 同属「初始化定死」清单,一旦选错,只能重建实例并迁移全部数据:
表格
| 参数 | 查询函数 | 建库后可否修改 |
|---|---|---|
| CHARSET / UNICODE_FLAG (字符集) | SF_GET_UNICODE_FLAG() / UNICODE() | 否 |
| LENGTH_IN_CHAR (长度单位) | SF_GET_LENGTH_IN_CHAR() | 否(新版本已废弃) |
| PAGE_SIZE (页大小) | SF_GET_PAGE_SIZE() / PAGE() | 否 |
| EXTENT_SIZE (簇大小) | SF_GET_EXTENT_SIZE() | 否 |
| CASE_SENSITIVE (大小写敏感) | SF_GET_CASE_SENSITIVE_FLAG() | 否 |
| BLANK_PAD_MODE (空格填充模式) | 查 V$PARAMETER | 否 |
SELECT '页大小' AS 参数, CAST(PARA_VALUE AS VARCHAR(20)) AS 值 FROM V$DM_INI WHERE PARA_NAME='PAGE_SIZE'
UNION ALL
SELECT '簇大小', CAST(SF_GET_EXTENT_SIZE() AS VARCHAR(20)) FROM DUAL
UNION ALL
SELECT '字符集', CASE SF_GET_UNICODE_FLAG()
WHEN 0 THEN 'GB18030'
WHEN 1 THEN 'UTF-8'
WHEN 2 THEN 'EUC-KR'
END FROM DUAL
UNION ALL
SELECT '大小写敏感', CAST(SF_GET_CASE_SENSITIVE_FLAG() AS VARCHAR(20)) FROM DUAL
UNION ALL
SELECT '长度是否以字符为单位', CAST(SF_GET_LENGTH_IN_CHAR() AS VARCHAR(20)) FROM DUAL;
图片占位:参数查询输出截图
同时,也可以从视图获取对应的参数值,执行的 sql 如下:
SELECT '页大小(字节)' AS 参数, PARA_VALUE AS 值 FROM V$DM_INI WHERE PARA_NAME='GLOBAL_PAGE_SIZE'
UNION ALL
SELECT 'UNICODE_FLAG(字符集)', PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='UNICODE_FLAG'
UNION ALL
SELECT 'CASE_SENSITIVE(大小写敏感)', PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='CASE_SENSITIVE'
UNION ALL
SELECT 'LENGTH_IN_CHAR(字符单位)', PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='LENGTH_IN_CHAR';
达梦数据库中的表,按照存储组织方式与使用场景可以划分为六大类,主要分为:普通表、堆表、列存表、分区表、全局临时表和外部表。
表格
| 表类型 | 内部名称 | 存储原理 | 适用场景 |
|---|---|---|---|
| 普通表(索引组织表) | INDEX ORGANIZED TABLE | B+ 树,按主键(聚集索引)组织 | 绝大多数 OLTP 业务表 |
| 堆表 | HEAP TABLE / LIST_TABLE | 无序堆 + 链表,物理 ROWID | 数据量中等、需要快速全表扫描 |
| 列存表( HUGE 表) | HUGE TABLE | HFS 文件系统,列式存储 | 分析型、大批量扫描聚合 |
| 分区表 | PARTITIONED TABLE | 逻辑上分而治之 | 大表按范围 / 哈希 / 列表切分 |
| 全局临时表 | GLOBAL TEMPORARY TABLE | 会话 / 事务级临时数据 | 中间结果集、批量加工暂存 |
| 外部表 | EXTERNAL TABLE | 数据在操作系统文件 | 数据装载 / 卸载、日志分析 |
-- 系统自动生成聚集索引
CREATE TABLE SYSDBA.T_EMP (
EMP_ID INT,
EMP_NAME VARCHAR(50),
DEPT_ID INT
);
堆表通过在 STORAGE 子句或表定义中指定 LIST_TABLE 参数创建。它把数据行无序地堆积在数据页中,行的定位依靠物理 ROWID(文件号 + 页号 + 页内偏移),而不是逻辑主键。
CREATE TABLE SYSDBA.T_LOG (
LOG_ID BIGINT,
LOG_TIME DATETIME,
CONTENT VARCHAR(200)
) STORAGE(NOBRANCH);
HUGE 表是达梦的列式存储表,基于达梦自研的 HFS(HUGE File System) 存储引擎,数据按列组织并压缩存放,一次读取只取用到的列,非常适合分析型场景。
CREATE TABLESPACE ... WITH HUGE PATH);-- 1) 建 HUGE 表空间
CREATE TABLESPACE TS_HUGE
DATAFILE '/dmdata/data/db3/DAMENG/TS_HUGE.dbf' SIZE 1024
WITH HUGE PATH '/dmdata/data/db3/DAMENG/TS_HUGE_HUGE';
-- 2) 建 HUGE 表
CREATE HUGE TABLE SYSDBA.T_SALES (
SALE_DATE DATE,
PRODUCT VARCHAR(50),
AMOUNT DECIMAL(18,2)
) STORAGE(SECTION(65536), FILESIZE(1024), ON TS_HUGE);
-- 3) 建 HUGE 表上的索引
CREATE INDEX IDX_SALES_DATE ON SYSDBA.T_SALES(SALE_DATE);
-- 4) 查看 HUGE 表信息
SELECT * FROM V$HUGE_TABLESPACE;
分区表把一张逻辑大表按规则切分为多个物理子表(分区),对外仍是一张表。好处是:查询可分区裁剪只扫相关分区、维护可分区级进行(截断 / 删除 / 交换)、I/O 可分散到不同存储。
-- 范围分区
CREATE TABLE SYSDBA.T_ORDER_2026 (
ORDER_ID INT,
ORDER_DATE DATE,
AMOUNT DECIMAL(18,2)
)
PARTITION BY RANGE (ORDER_DATE) (
PARTITION P_202601 VALUES LESS THAN ('2026-02-01'),
PARTITION P_202602 VALUES LESS THAN ('2026-03-01'),
PARTITION P_OTHER VALUES LESS THAN (MAXVALUE)
);
图片占位:范围分区执行截图
-- 列表分区
CREATE TABLE SYSDBA.T_CUST (
CUST_ID INT,
PROV VARCHAR(20)
)
PARTITION BY LIST (PROV) (
PARTITION P_NORTH VALUES ('北京','天津','河北'),
PARTITION P_SOUTH VALUES ('广东','广西','海南')
);
图片占位:列表分区执行截图
-- 哈希分区
CREATE TABLE SYSDBA.T_HASH (
ID INT,
DATA VARCHAR(100)
)
PARTITION BY HASH (ID) PARTITIONS 8;
-- 查看分区信息
SELECT * FROM DBA_TAB_PARTITIONS WHERE TABLE_NAME = 'T_ORDER_2026';
图片占位:分区查询结果截图
-- 新增分区(末尾存在MAXVALUE分区不能直接ADD,需要SPLIT拆分)
-- ALTER TABLE SYSDBA.T_ORDER_2026 ADD PARTITION P_202603 VALUES LESS THAN ('2026-04-01');
-- 删除分区(数据一并删除)
ALTER TABLE SYSDBA.T_ORDER_2026 DROP PARTITION P_202601;
-- 截断分区(保留分区结构,清空数据)
ALTER TABLE SYSDBA.T_ORDER_2026 TRUNCATE PARTITION P_202602;
全局临时表的表结构对所有会话可见,但数据只在当前会话可见,会话之间数据隔离。它适合存放中间结果集、批量加工过程的暂存数据,避免对正式表加压力。
-- 事务级临时表:提交即清空
CREATE GLOBAL TEMPORARY TABLE SYSDBA.T_TMP_TRX (
ID INT,
NAME VARCHAR(50)
) ON COMMIT DELETE ROWS;
-- 会话级临时表:会话结束才清空
CREATE GLOBAL TEMPORARY TABLE SYSDBA.T_TMP_SESS (
ID INT,
NAME VARCHAR(50)
) ON COMMIT PRESERVE ROWS;
外部表的数据不存放在数据库内,而是存放在操作系统的数据文件中,数据库只在数据字典里保存一层的表定义,读取时按定义解析文件。
操作系统前置操作:
mkdir -p /dmdata/ext_data
chown dmdba:dinstall /dmdata/ext_data
chmod 750 /dmdata/ext_data
-- 1) 建目录对象
CREATE OR REPLACE DIRECTORY DIR_EXT AS '/dmdata/ext_data';
-- 2) 授权
GRANT READ ON DIRECTORY DIR_EXT TO SYSDBA;
-- 3) 建外部表(DM8标准语法,注意不要直接照搬Oracle FROM语法)
CREATE EXTERNAL TABLE SYSDBA.EXT_EMP (
EMP_ID INT,
EMP_NAME VARCHAR(50),
SALARY DECIMAL(10,2)
)
FROM DATAFILE DEFAULT DIRECTORY DIR_EXT
LOCATION ('emp.txt')
PARMS (FIELDS DELIMITED BY '|');
-- 4) 查询与装载
SELECT * FROM SYSDBA.EXT_EMP;
INSERT INTO SYSDBA.T_EMP SELECT * FROM SYSDBA.EXT_EMP;
COMMIT;
文章
阅读量
获赞
