📖 目录
达梦数据库 基础概念
什么是达梦数据库?
达梦数据库(DM Database)是由武汉达梦数据库有限公司自主研发的关系型数据库管理系统,具有自主知识产权,广泛应用于政务、金融、能源、电信等关键领域。
核心特性
- 自主可控:完全自主知识产权,符合国产化要求
- 高性能:优化的查询引擎和存储引擎,支持高并发
- 高可用性:支持主备、读写分离、集群等架构
- 兼容性强:兼容 Oracle、MySQL、SQL Server 等数据库语法
- 安全可靠:提供完善的安全机制和审计功能
- ACID 兼容:支持完整的事务特性
- 跨平台:支持 Windows、Linux、Unix 等操作系统
应用场景
- 政务系统:电子政务、数字政府等
- 金融行业:银行、证券、保险等核心业务系统
- 能源行业:电力、石油、煤炭等企业信息化
- 电信行业:运营商核心业务系统
- 企业信息化:ERP、CRM 等企业应用系统
数据库架构
- 实例(Instance):运行中的数据库服务进程,一个实例对应一个数据库
- 数据库(Database):按照一定方式组织、存储和管理数据的集合
- 表空间(Tablespace):数据库的逻辑存储单元
- 表(Table):数据存储的基本单元
- 用户(User):数据库访问的主体
- 角色(Role):权限的集合
安装与启动
安装环境要求
- 操作系统:Linux(RedHat、CentOS、Ubuntu 等)、Windows Server
- 内存:建议 ≥4GB(生产环境建议 ≥8GB)
- 磁盘空间:建议 ≥50GB(根据数据量调整)
- CPU:建议 2 核以上
安装步骤
bash
# 1. 创建达梦用户和用户组
groupadd dinstall
useradd -g dinstall -m -d /home/dmdba -s /bin/bash dmdba
passwd dmdba
# 2. 设置环境变量(在 dmdba 用户下)
export DM_HOME=/opt/dmdbms
export PATH=$DM_HOME/bin:$PATH
export LD_LIBRARY_PATH=$DM_HOME/bin:$LD_LIBRARY_PATH
# 3. 运行安装程序
./DMInstall.bin -i
# 4. 初始化数据库实例
./dminit PATH=/opt/dmdbms/data DB_NAME=DAMENG INSTANCE_NAME=DMSERVER PORT_NUM=5236
# 5. 注册服务(Linux)
./dm_service_installer.sh -t dmserver -p DMSERVER -dm_ini /opt/dmdbms/data/DAMENG/dm.ini启动和停止服务
bash
# 启动数据库服务
systemctl start DmServiceDMSERVER
# 或
service DmServiceDMSERVER start
# 停止数据库服务
systemctl stop DmServiceDMSERVER
# 或
service DmServiceDMSERVER stop
# 重启数据库服务
systemctl restart DmServiceDMSERVER
# 查看服务状态
systemctl status DmServiceDMSERVER连接数据库
bash
# 使用 disql 命令行工具连接
disql SYSDBA/SYSDBA@localhost:5236
# 连接远程数据库
disql SYSDBA/SYSDBA@192.168.1.100:5236
# 使用 DM 管理工具(图形化界面)
# 启动 DM 管理工具,输入服务器地址、端口、用户名、密码基本命令
sql
-- 查看版本
SELECT * FROM V$VERSION;
-- 查看当前数据库
SELECT SYS_CONTEXT('USERENV', 'DB_NAME') FROM DUAL;
-- 查看当前用户
SELECT USER FROM DUAL;
SELECT SYS_CONTEXT('USERENV', 'SESSION_USER') FROM DUAL;
-- 查看当前时间
SELECT SYSDATE FROM DUAL;
-- 查看数据库信息
SELECT * FROM V$DATABASE;
-- 退出
EXIT;
-- 或
QUIT;数据类型
数值类型
sql
-- 整数类型
TINYINT -- 1 字节,-128 到 127
SMALLINT -- 2 字节,-32768 到 32767
INT/INTEGER -- 4 字节,-2147483648 到 2147483647
BIGINT -- 8 字节,-9223372036854775808 到 9223372036854775807
-- 浮点数类型
REAL -- 4 字节,单精度浮点数
FLOAT -- 8 字节,双精度浮点数
DOUBLE -- 8 字节,双精度浮点数
-- 精确数值类型
DECIMAL(p, s) -- 精确数值,p 是精度,s 是小数位数
NUMERIC(p, s) -- DECIMAL 的别名
-- 示例
CREATE TABLE numbers (
id INTEGER PRIMARY KEY,
price DECIMAL(10, 2),
ratio REAL
);字符串类型
sql
-- 固定长度
CHAR(n) -- 固定长度,最多 32767 字节
-- 可变长度
VARCHAR(n) -- 可变长度,最多 32767 字节
VARCHAR2(n) -- VARCHAR 的别名(兼容 Oracle)
-- 大文本类型
TEXT -- 文本类型,最大 2GB
CLOB -- 字符大对象,最大 2GB
-- 示例
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(255),
bio TEXT
);日期时间类型
sql
-- 日期时间类型
DATE -- 日期(年月日)
TIME -- 时间(时分秒)
TIMESTAMP -- 日期和时间(年月日时分秒)
DATETIME -- 日期和时间(兼容 MySQL)
-- 示例
CREATE TABLE events (
id INTEGER PRIMARY KEY,
event_date DATE,
event_time TIME,
created_at TIMESTAMP DEFAULT SYSDATE
);
-- 插入日期时间
INSERT INTO events (event_date, event_time, created_at)
VALUES (DATE '2024-01-15', TIME '14:30:00', SYSDATE);二进制类型
sql
-- 二进制类型
BINARY(n) -- 固定长度二进制
VARBINARY(n) -- 可变长度二进制
BLOB -- 二进制大对象,最大 2GB
IMAGE -- 图像类型(兼容 SQL Server)
-- 示例
CREATE TABLE files (
id INTEGER PRIMARY KEY,
filename VARCHAR(255),
content BLOB
);其他类型
sql
-- 布尔类型
BOOLEAN -- TRUE 或 FALSE
-- 位类型
BIT -- 位类型
-- 示例
CREATE TABLE tasks (
id INTEGER PRIMARY KEY,
title VARCHAR(255),
completed BOOLEAN DEFAULT FALSE
);DDL 操作
创建数据库
sql
-- 创建数据库(通常在初始化时创建)
-- 使用 dminit 工具初始化数据库实例创建表
sql
-- 基本创建表
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT SYSDATE
) STORAGE (
INITIAL 50,
NEXT 50,
MINEXTENTS 1,
MAXEXTENTS UNLIMITED
);
-- 创建表(指定表空间)
CREATE TABLE products (
id INTEGER PRIMARY KEY,
name VARCHAR(255),
price DECIMAL(10, 2)
) TABLESPACE MAIN;
-- 从查询结果创建表
CREATE TABLE users_backup AS
SELECT * FROM users WHERE created_at < DATE '2024-01-01';
-- 创建表(如果不存在)
CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY,
name VARCHAR(255)
);修改表
sql
-- 添加列
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
-- 添加列(指定位置)
ALTER TABLE users ADD COLUMN phone VARCHAR(20) AFTER email;
-- 删除列
ALTER TABLE users DROP COLUMN phone;
-- 修改列类型
ALTER TABLE users MODIFY COLUMN email VARCHAR(100);
-- 修改列名
ALTER TABLE users RENAME COLUMN email TO email_address;
-- 重命名表
ALTER TABLE users RENAME TO customers;
-- 或
RENAME TABLE users TO customers;删除表
sql
-- 删除表
DROP TABLE users;
-- 删除表(如果存在)
DROP TABLE IF EXISTS users;
-- 清空表数据
TRUNCATE TABLE users;
-- 删除多个表
DROP TABLE users, orders, products;表空间
sql
-- 创建表空间
CREATE TABLESPACE tbs_data
DATAFILE '/opt/dmdbms/data/tbs_data01.dbf' SIZE 100;
-- 扩展表空间
ALTER TABLESPACE tbs_data
ADD DATAFILE '/opt/dmdbms/data/tbs_data02.dbf' SIZE 100;
-- 查看表空间
SELECT * FROM DBA_TABLESPACES;
-- 删除表空间
DROP TABLESPACE tbs_data;DML 操作
INSERT
sql
-- 插入单行
INSERT INTO users (username, email) VALUES ('john', 'john@example.com');
-- 插入多行
INSERT INTO users (username, email) VALUES
('alice', 'alice@example.com'),
('bob', 'bob@example.com'),
('charlie', 'charlie@example.com');
-- 从查询插入
INSERT INTO users_backup (username, email)
SELECT username, email FROM users WHERE created_at < DATE '2024-01-01';
-- 插入并返回(使用 RETURNING)
INSERT INTO users (username, email) VALUES ('david', 'david@example.com')
RETURNING id, username, email;
-- 使用 MERGE 语句(合并插入或更新)
MERGE INTO users u
USING (SELECT 'john' AS username, 'john@example.com' AS email FROM DUAL) s
ON (u.username = s.username)
WHEN MATCHED THEN
UPDATE SET email = s.email
WHEN NOT MATCHED THEN
INSERT (username, email) VALUES (s.username, s.email);UPDATE
sql
-- 更新单行
UPDATE users SET email = 'newemail@example.com' WHERE id = 1;
-- 更新多列
UPDATE users
SET email = 'newemail@example.com', updated_at = SYSDATE
WHERE id = 1;
-- 使用子查询更新
UPDATE users
SET email = (SELECT email FROM users_backup WHERE users_backup.id = users.id)
WHERE EXISTS (SELECT 1 FROM users_backup WHERE users_backup.id = users.id);
-- 使用 JOIN 更新
UPDATE users u
SET u.last_order_date = (
SELECT MAX(order_date) FROM orders o WHERE o.user_id = u.id
)
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);DELETE
sql
-- 删除行
DELETE FROM users WHERE id = 1;
-- 删除所有行
DELETE FROM users;
-- 使用子查询删除
DELETE FROM users
WHERE id IN (SELECT id FROM users_backup WHERE created_at < DATE '2020-01-01');
-- 使用 EXISTS 删除
DELETE FROM users
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.user_id = users.id AND o.order_date < DATE '2020-01-01'
);查询操作
SELECT 基础
sql
-- 基本查询
SELECT * FROM users;
-- 选择特定列
SELECT id, username, email FROM users;
-- 使用别名
SELECT id, username AS name, email FROM users;
-- 去重
SELECT DISTINCT email FROM users;
-- 限制结果数量
SELECT * FROM users WHERE ROWNUM <= 10;
-- 分页查询(使用 ROWNUM)
SELECT * FROM (
SELECT ROW_NUMBER() OVER (ORDER BY id) AS rn, *
FROM users
) WHERE rn BETWEEN 21 AND 30;WHERE 条件
sql
-- 基本条件
SELECT * FROM users WHERE id = 1;
SELECT * FROM users WHERE username = 'john';
SELECT * FROM users WHERE created_at > DATE '2024-01-01';
-- 多个条件
SELECT * FROM users WHERE id > 10 AND email LIKE '%@example.com';
SELECT * FROM users WHERE id < 5 OR username = 'admin';
-- IN 操作符
SELECT * FROM users WHERE id IN (1, 2, 3, 4, 5);
-- NOT IN
SELECT * FROM users WHERE id NOT IN (1, 2, 3);
-- BETWEEN
SELECT * FROM users WHERE id BETWEEN 1 AND 100;
-- LIKE 和 NOT LIKE
SELECT * FROM users WHERE username LIKE 'j%'; -- 以 j 开头
SELECT * FROM users WHERE username LIKE '%john%'; -- 包含 john
SELECT * FROM users WHERE username LIKE 'j__n'; -- j 开头,n 结尾,中间两个字符
-- IS NULL 和 IS NOT NULL
SELECT * FROM users WHERE email IS NULL;
SELECT * FROM users WHERE email IS NOT NULL;
-- 正则表达式(REGEXP_LIKE)
SELECT * FROM users WHERE REGEXP_LIKE(email, '^[a-z]+@example\.com$');排序
sql
-- 升序排序
SELECT * FROM users ORDER BY created_at ASC;
-- 降序排序
SELECT * FROM users ORDER BY created_at DESC;
-- 多列排序
SELECT * FROM users ORDER BY created_at DESC, username ASC;
-- NULL 值处理
SELECT * FROM users ORDER BY email NULLS LAST;
SELECT * FROM users ORDER BY email NULLS FIRST;聚合函数
sql
-- 计数
SELECT COUNT(*) FROM users;
SELECT COUNT(DISTINCT email) FROM users;
-- 求和、平均值、最大值、最小值
SELECT SUM(price) FROM products;
SELECT AVG(price) FROM products;
SELECT MAX(price) FROM products;
SELECT MIN(price) FROM products;
-- GROUP BY
SELECT category, COUNT(*) AS count, AVG(price) AS avg_price
FROM products
GROUP BY category;
-- HAVING
SELECT category, COUNT(*) AS count
FROM products
GROUP BY category
HAVING COUNT(*) > 10;
-- ROLLUP 和 CUBE
SELECT category, COUNT(*) AS count
FROM products
GROUP BY ROLLUP(category);
SELECT category, brand, COUNT(*) AS count
FROM products
GROUP BY CUBE(category, brand);JOIN
sql
-- INNER JOIN
SELECT u.username, o.order_id, o.total
FROM users u
INNER JOIN orders o ON u.id = o.user_id;
-- LEFT JOIN
SELECT u.username, o.order_id, o.total
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
-- RIGHT JOIN
SELECT u.username, o.order_id, o.total
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;
-- FULL OUTER JOIN
SELECT u.username, o.order_id, o.total
FROM users u
FULL OUTER JOIN orders o ON u.id = o.user_id;
-- 多表 JOIN
SELECT u.username, o.order_id, p.product_name, oi.quantity
FROM users u
INNER JOIN orders o ON u.id = o.user_id
INNER JOIN order_items oi ON o.id = oi.order_id
INNER JOIN products p ON oi.product_id = p.id;
-- 自连接
SELECT e1.name AS employee, e2.name AS manager
FROM employees e1
LEFT JOIN employees e2 ON e1.manager_id = e2.id;子查询
sql
-- 标量子查询
SELECT username, (
SELECT COUNT(*) FROM orders WHERE orders.user_id = users.id
) AS order_count
FROM users;
-- EXISTS
SELECT * FROM users
WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id);
-- NOT EXISTS
SELECT * FROM users
WHERE NOT EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id);
-- IN 子查询
SELECT * FROM users
WHERE id IN (SELECT user_id FROM orders WHERE total > 1000);
-- 相关子查询
SELECT u.username, (
SELECT MAX(total) FROM orders WHERE user_id = u.id
) AS max_order_total
FROM users u;窗口函数
sql
-- ROW_NUMBER
SELECT username, email,
ROW_NUMBER() OVER (ORDER BY created_at) AS row_num
FROM users;
-- RANK 和 DENSE_RANK
SELECT username, total,
RANK() OVER (ORDER BY total DESC) AS rank,
DENSE_RANK() OVER (ORDER BY total DESC) AS dense_rank
FROM (
SELECT u.username, SUM(o.total) AS total
FROM users u
JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.username
) AS user_totals;
-- 分区窗口函数
SELECT username, category, price,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY price DESC) AS rank_in_category
FROM products;
-- 累计聚合
SELECT date, revenue,
SUM(revenue) OVER (ORDER BY date) AS cumulative_revenue
FROM daily_sales;集合操作
sql
-- UNION(去重)
SELECT username FROM users
UNION
SELECT username FROM admins;
-- UNION ALL(不去重)
SELECT username FROM users
UNION ALL
SELECT username FROM admins;
-- INTERSECT(交集)
SELECT username FROM users
INTERSECT
SELECT username FROM admins;
-- MINUS(差集)
SELECT username FROM users
MINUS
SELECT username FROM admins;索引
创建索引
sql
-- 创建普通索引
CREATE INDEX idx_users_email ON users(email);
-- 创建唯一索引
CREATE UNIQUE INDEX idx_users_username ON users(username);
-- 创建复合索引
CREATE INDEX idx_orders_user_date ON orders(user_id, order_date);
-- 创建函数索引
CREATE INDEX idx_users_lower_email ON users(LOWER(email));
-- 创建位图索引
CREATE BITMAP INDEX idx_products_status ON products(status);
-- 在创建表时定义索引
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(255),
CONSTRAINT idx_email UNIQUE (email)
);索引类型
sql
-- B-Tree 索引(默认)
CREATE INDEX idx_btree ON table_name(column_name);
-- 位图索引(适用于低基数列)
CREATE BITMAP INDEX idx_bitmap ON table_name(column_name);
-- 唯一索引
CREATE UNIQUE INDEX idx_unique ON table_name(column_name);
-- 函数索引
CREATE INDEX idx_function ON table_name(FUNCTION(column_name));管理索引
sql
-- 查看索引
SELECT * FROM USER_INDEXES WHERE table_name = 'USERS';
-- 查看索引列
SELECT * FROM USER_IND_COLUMNS WHERE table_name = 'USERS';
-- 重建索引
ALTER INDEX idx_users_email REBUILD;
-- 删除索引
DROP INDEX idx_users_email;
-- 分析索引
ANALYZE INDEX idx_users_email;约束
主键约束
sql
-- 创建表时定义主键
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username VARCHAR(50)
);
-- 添加主键约束
ALTER TABLE users ADD CONSTRAINT pk_users PRIMARY KEY (id);
-- 复合主键
CREATE TABLE order_items (
order_id INTEGER,
product_id INTEGER,
quantity INTEGER,
PRIMARY KEY (order_id, product_id)
);外键约束
sql
-- 创建表时定义外键
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER,
total DECIMAL(10, 2),
CONSTRAINT fk_orders_user FOREIGN KEY (user_id) REFERENCES users(id)
);
-- 添加外键约束
ALTER TABLE orders
ADD CONSTRAINT fk_orders_user
FOREIGN KEY (user_id) REFERENCES users(id);
-- 级联删除
ALTER TABLE orders
ADD CONSTRAINT fk_orders_user
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
-- 级联更新
ALTER TABLE orders
ADD CONSTRAINT fk_orders_user
FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE;
-- 设置 NULL
ALTER TABLE orders
ADD CONSTRAINT fk_orders_user
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;唯一约束
sql
-- 创建表时定义唯一约束
CREATE TABLE users (
id INTEGER PRIMARY KEY,
email VARCHAR(255) UNIQUE
);
-- 添加唯一约束
ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE (email);
-- 复合唯一约束
CREATE TABLE user_roles (
user_id INTEGER,
role_id INTEGER,
UNIQUE (user_id, role_id)
);检查约束
sql
-- 创建表时定义检查约束
CREATE TABLE products (
id INTEGER PRIMARY KEY,
name VARCHAR(255),
price DECIMAL(10, 2) CHECK (price > 0),
stock INTEGER CHECK (stock >= 0)
);
-- 添加检查约束
ALTER TABLE products
ADD CONSTRAINT products_price_positive CHECK (price > 0);非空约束
sql
-- 创建表时定义非空约束
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(255) NOT NULL
);
-- 添加非空约束
ALTER TABLE users MODIFY email VARCHAR(255) NOT NULL;
-- 移除非空约束
ALTER TABLE users MODIFY email VARCHAR(255) NULL;默认值
sql
-- 创建表时定义默认值
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username VARCHAR(50),
created_at TIMESTAMP DEFAULT SYSDATE,
active BOOLEAN DEFAULT TRUE
);
-- 添加默认值
ALTER TABLE users MODIFY created_at TIMESTAMP DEFAULT SYSDATE;
-- 移除默认值
ALTER TABLE users MODIFY created_at TIMESTAMP;视图
创建视图
sql
-- 基本视图
CREATE VIEW active_users AS
SELECT id, username, email
FROM users
WHERE active = TRUE;
-- 可更新视图
CREATE VIEW user_orders AS
SELECT u.id AS user_id, u.username, o.id AS order_id, o.total
FROM users u
JOIN orders o ON u.id = o.user_id;
-- 创建或替换视图
CREATE OR REPLACE VIEW active_users AS
SELECT id, username, email
FROM users
WHERE active = TRUE AND deleted_at IS NULL;
-- 物化视图
CREATE MATERIALIZED VIEW monthly_sales AS
SELECT
TO_CHAR(order_date, 'YYYY-MM') AS month,
SUM(total) AS total_sales,
COUNT(*) AS order_count
FROM orders
GROUP BY TO_CHAR(order_date, 'YYYY-MM');
-- 刷新物化视图
REFRESH MATERIALIZED VIEW monthly_sales;管理视图
sql
-- 查看视图定义
SELECT * FROM USER_VIEWS WHERE view_name = 'ACTIVE_USERS';
-- 查看视图数据
SELECT * FROM active_users;
-- 删除视图
DROP VIEW active_users;
-- 删除物化视图
DROP MATERIALIZED VIEW monthly_sales;存储过程和函数
创建存储过程
sql
-- 基本存储过程
CREATE OR REPLACE PROCEDURE get_user_count
AS
v_count INTEGER;
BEGIN
SELECT COUNT(*) INTO v_count FROM users;
DBMS_OUTPUT.PUT_LINE('User count: ' || v_count);
END;
/
-- 调用存储过程
EXEC get_user_count;
-- 或
CALL get_user_count();
-- 带参数的存储过程
CREATE OR REPLACE PROCEDURE get_user_by_id(
p_user_id IN INTEGER,
p_username OUT VARCHAR,
p_email OUT VARCHAR
)
AS
BEGIN
SELECT username, email INTO p_username, p_email
FROM users
WHERE id = p_user_id;
END;
/
-- 调用带参数的存储过程
DECLARE
v_username VARCHAR(50);
v_email VARCHAR(255);
BEGIN
get_user_by_id(1, v_username, v_email);
DBMS_OUTPUT.PUT_LINE('Username: ' || v_username || ', Email: ' || v_email);
END;
/创建函数
sql
-- 创建函数
CREATE OR REPLACE FUNCTION calculate_order_total(p_order_id INTEGER)
RETURNS DECIMAL(10, 2)
AS
v_total DECIMAL(10, 2);
BEGIN
SELECT SUM(quantity * price) INTO v_total
FROM order_items
WHERE order_id = p_order_id;
RETURN NVL(v_total, 0);
END;
/
-- 调用函数
SELECT calculate_order_total(1) FROM DUAL;管理存储过程和函数
sql
-- 查看存储过程
SELECT * FROM USER_PROCEDURES WHERE object_type = 'PROCEDURE';
-- 查看函数
SELECT * FROM USER_PROCEDURES WHERE object_type = 'FUNCTION';
-- 查看存储过程定义
SELECT * FROM USER_SOURCE WHERE name = 'GET_USER_COUNT' AND type = 'PROCEDURE';
-- 删除存储过程
DROP PROCEDURE get_user_count;
-- 删除函数
DROP FUNCTION calculate_order_total;触发器
创建触发器
sql
-- 自动更新时间戳的触发器
CREATE OR REPLACE TRIGGER update_users_updated_at
BEFORE UPDATE ON users
FOR EACH ROW
BEGIN
:NEW.updated_at := SYSDATE;
END;
/触发器示例
sql
-- 审计日志触发器
CREATE OR REPLACE TRIGGER audit_users_trigger
AFTER INSERT OR UPDATE OR DELETE ON users
FOR EACH ROW
DECLARE
v_operation VARCHAR(10);
BEGIN
IF INSERTING THEN
v_operation := 'INSERT';
INSERT INTO audit_log (table_name, operation, new_data, changed_at)
VALUES ('users', v_operation,
'{"id":' || :NEW.id || ',"username":"' || :NEW.username || '"}',
SYSDATE);
ELSIF UPDATING THEN
v_operation := 'UPDATE';
INSERT INTO audit_log (table_name, operation, old_data, new_data, changed_at)
VALUES ('users', v_operation,
'{"id":' || :OLD.id || ',"username":"' || :OLD.username || '"}',
'{"id":' || :NEW.id || ',"username":"' || :NEW.username || '"}',
SYSDATE);
ELSIF DELETING THEN
v_operation := 'DELETE';
INSERT INTO audit_log (table_name, operation, old_data, changed_at)
VALUES ('users', v_operation,
'{"id":' || :OLD.id || ',"username":"' || :OLD.username || '"}',
SYSDATE);
END IF;
END;
/
-- 创建审计日志表
CREATE TABLE audit_log (
id INTEGER PRIMARY KEY,
table_name VARCHAR(255),
operation VARCHAR(10),
old_data TEXT,
new_data TEXT,
changed_at TIMESTAMP DEFAULT SYSDATE
);管理触发器
sql
-- 查看触发器
SELECT * FROM USER_TRIGGERS WHERE table_name = 'USERS';
-- 启用触发器
ALTER TRIGGER update_users_updated_at ENABLE;
-- 禁用触发器
ALTER TRIGGER update_users_updated_at DISABLE;
-- 删除触发器
DROP TRIGGER update_users_updated_at;事务管理
基本事务
sql
-- 开始事务(隐式)
-- 达梦数据库默认自动提交,需要关闭自动提交
SET AUTOCOMMIT OFF;
-- 执行操作
INSERT INTO users (username, email) VALUES ('john', 'john@example.com');
UPDATE users SET email = 'newemail@example.com' WHERE id = 1;
-- 提交事务
COMMIT;
-- 回滚事务
ROLLBACK;
-- 开启自动提交
SET AUTOCOMMIT ON;保存点
sql
SET AUTOCOMMIT OFF;
INSERT INTO users (username, email) VALUES ('alice', 'alice@example.com');
-- 创建保存点
SAVEPOINT sp1;
INSERT INTO users (username, email) VALUES ('bob', 'bob@example.com');
-- 回滚到保存点
ROLLBACK TO SAVEPOINT sp1;
-- 提交事务
COMMIT;事务隔离级别
sql
-- 查看当前隔离级别
SELECT @@ISOLATION_LEVEL;
-- 设置会话隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- 在事务中设置
SET AUTOCOMMIT OFF;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- ... 执行操作 ...
COMMIT;用户和权限管理
用户管理
sql
-- 创建用户
CREATE USER test_user IDENTIFIED BY "password123";
-- 修改用户密码
ALTER USER test_user IDENTIFIED BY "newpassword123";
-- 锁定用户
ALTER USER test_user ACCOUNT LOCK;
-- 解锁用户
ALTER USER test_user ACCOUNT UNLOCK;
-- 删除用户
DROP USER test_user;
-- 查看用户
SELECT * FROM DBA_USERS WHERE username = 'TEST_USER';角色管理
sql
-- 创建角色
CREATE ROLE app_user_role;
-- 授予角色权限
GRANT SELECT, INSERT, UPDATE ON users TO app_user_role;
GRANT SELECT ON products TO app_user_role;
-- 将角色授予用户
GRANT app_user_role TO test_user;
-- 撤销角色
REVOKE app_user_role FROM test_user;
-- 删除角色
DROP ROLE app_user_role;
-- 查看角色
SELECT * FROM DBA_ROLES;权限管理
sql
-- 授予对象权限
GRANT SELECT, INSERT, UPDATE, DELETE ON users TO test_user;
GRANT SELECT ON products TO test_user;
-- 授予系统权限
GRANT CREATE TABLE TO test_user;
GRANT CREATE VIEW TO test_user;
-- 撤销权限
REVOKE SELECT ON users FROM test_user;
REVOKE CREATE TABLE FROM test_user;
-- 查看用户权限
SELECT * FROM DBA_TAB_PRIVS WHERE grantee = 'TEST_USER';
SELECT * FROM DBA_SYS_PRIVS WHERE grantee = 'TEST_USER';表空间管理
创建表空间
sql
-- 创建表空间
CREATE TABLESPACE tbs_data
DATAFILE '/opt/dmdbms/data/tbs_data01.dbf' SIZE 100;
-- 创建表空间(自动扩展)
CREATE TABLESPACE tbs_data
DATAFILE '/opt/dmdbms/data/tbs_data01.dbf' SIZE 100
AUTOEXTEND ON NEXT 50 MAXSIZE 1000;
-- 扩展表空间
ALTER TABLESPACE tbs_data
ADD DATAFILE '/opt/dmdbms/data/tbs_data02.dbf' SIZE 100;
-- 查看表空间
SELECT * FROM DBA_TABLESPACES;
SELECT * FROM DBA_DATA_FILES WHERE tablespace_name = 'TBS_DATA';
-- 删除表空间
DROP TABLESPACE tbs_data;
DROP TABLESPACE tbs_data INCLUDING CONTENTS AND DATAFILES;表空间维护
sql
-- 设置表空间为只读
ALTER TABLESPACE tbs_data READ ONLY;
-- 设置表空间为读写
ALTER TABLESPACE tbs_data READ WRITE;
-- 重命名表空间
ALTER TABLESPACE tbs_data RENAME TO tbs_data_new;备份与恢复
逻辑备份
sql
-- 使用 DM 管理工具进行逻辑备份
-- 或使用命令行工具 dexp
-- 导出整个数据库
dexp SYSDBA/SYSDBA@localhost:5236 FILE=backup.dmp FULL=Y
-- 导出指定用户
dexp SYSDBA/SYSDBA@localhost:5236 FILE=backup.dmp OWNER=test_user
-- 导出指定表
dexp SYSDBA/SYSDBA@localhost:5236 FILE=backup.dmp TABLES=users,orders
-- 导入数据
dimp SYSDBA/SYSDBA@localhost:5236 FILE=backup.dmp FULL=Y物理备份
bash
# 使用 DM 管理工具进行物理备份
# 或使用命令行工具
# 联机备份
BACKUP DATABASE BACKUPSET '/backup/full_backup';
# 增量备份
BACKUP DATABASE INCREMENT WITH BACKUP_DIR '/backup/full_backup' BACKUPSET '/backup/inc_backup';
# 表空间备份
BACKUP TABLESPACE MAIN BACKUPSET '/backup/tbs_backup';恢复
sql
-- 恢复数据库
RESTORE DATABASE '/opt/dmdbms/data/DAMENG' FROM BACKUPSET '/backup/full_backup';
-- 恢复表空间
RESTORE TABLESPACE MAIN FROM BACKUPSET '/backup/tbs_backup';
-- 恢复归档日志
RECOVER DATABASE '/opt/dmdbms/data/DAMENG' FROM BACKUPSET '/backup/full_backup' WITH ARCHIVEDIR '/archive';性能优化
EXPLAIN 分析
sql
-- 基本 EXPLAIN
EXPLAIN SELECT * FROM users WHERE email = 'john@example.com';
-- 查看执行计划
SELECT * FROM V$SQL_PLAN WHERE sql_text LIKE '%SELECT * FROM users%';统计信息
sql
-- 收集表统计信息
ANALYZE TABLE users;
-- 收集所有表统计信息
DBMS_STATS.GATHER_TABLE_STATS('SYSDBA', 'USERS');
-- 查看表统计信息
SELECT * FROM USER_TAB_STATISTICS WHERE table_name = 'USERS';查询优化技巧
sql
-- 使用索引
CREATE INDEX idx_users_email ON users(email);
-- 避免 SELECT *
SELECT id, username, email FROM users;
-- 使用 ROWNUM 限制结果
SELECT * FROM users WHERE ROWNUM <= 10;
-- 使用 EXISTS 而不是 COUNT
SELECT * FROM users u
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);
-- 避免在 WHERE 子句中使用函数
-- 不好:WHERE TO_CHAR(created_at, 'YYYY') = '2024'
-- 好:WHERE created_at >= DATE '2024-01-01' AND created_at < DATE '2025-01-01'配置优化
sql
-- 查看配置参数
SELECT * FROM V$PARAMETER WHERE name LIKE '%BUFFER%';
SELECT * FROM V$PARAMETER WHERE name LIKE '%CACHE%';
-- 常用配置项(在 dm.ini 中设置)
-- BUFFER = 1000
-- MAX_BUFFER = 2000
-- SORT_BUF_SIZE = 2
-- HASH_JOIN_SIZE = 50常用实用方法
字符串函数
sql
-- 连接字符串
SELECT CONCAT('Hello', ' ', 'World') FROM DUAL; -- 'Hello World'
SELECT 'Hello' || ' ' || 'World' FROM DUAL; -- 'Hello World'
-- 字符串长度
SELECT LENGTH('Hello') FROM DUAL; -- 5
SELECT LEN('Hello') FROM DUAL; -- 5
-- 大小写转换
SELECT UPPER('hello') FROM DUAL; -- 'HELLO'
SELECT LOWER('HELLO') FROM DUAL; -- 'hello'
SELECT INITCAP('hello world') FROM DUAL; -- 'Hello World'
-- 子字符串
SELECT SUBSTR('Hello World', 1, 5) FROM DUAL; -- 'Hello'
SELECT SUBSTRING('Hello World', 7) FROM DUAL; -- 'World'
-- 替换
SELECT REPLACE('Hello World', 'World', 'DM') FROM DUAL; -- 'Hello DM'
-- 去除空格
SELECT TRIM(' Hello ') FROM DUAL; -- 'Hello'
SELECT LTRIM(' Hello') FROM DUAL; -- 'Hello'
SELECT RTRIM('Hello ') FROM DUAL; -- 'Hello'
-- 填充
SELECT LPAD('123', 5, '0') FROM DUAL; -- '00123'
SELECT RPAD('123', 5, '0') FROM DUAL; -- '12300'
-- 查找位置
SELECT INSTR('Hello World', 'World') FROM DUAL; -- 7
SELECT POSITION('World' IN 'Hello World') FROM DUAL; -- 7日期时间函数
sql
-- 当前日期时间
SELECT SYSDATE FROM DUAL; -- 当前日期时间
SELECT CURRENT_DATE FROM DUAL; -- 当前日期
SELECT CURRENT_TIME FROM DUAL; -- 当前时间
SELECT CURRENT_TIMESTAMP FROM DUAL; -- 当前时间戳
-- 提取日期部分
SELECT EXTRACT(YEAR FROM SYSDATE) FROM DUAL;
SELECT EXTRACT(MONTH FROM SYSDATE) FROM DUAL;
SELECT EXTRACT(DAY FROM SYSDATE) FROM DUAL;
SELECT TO_CHAR(SYSDATE, 'YYYY') FROM DUAL;
SELECT TO_CHAR(SYSDATE, 'MM') FROM DUAL;
SELECT TO_CHAR(SYSDATE, 'DD') FROM DUAL;
-- 日期运算
SELECT SYSDATE + 1 FROM DUAL; -- 加一天
SELECT SYSDATE - 7 FROM DUAL; -- 减七天
SELECT ADD_MONTHS(SYSDATE, 1) FROM DUAL; -- 加一月
SELECT ADD_MONTHS(SYSDATE, -1) FROM DUAL; -- 减一月
SELECT SYSDATE + INTERVAL '1' YEAR FROM DUAL; -- 加一年
-- 日期格式化
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') FROM DUAL;
SELECT TO_CHAR(SYSDATE, 'YYYY年MM月DD日') FROM DUAL;
SELECT TO_DATE('2024-01-15', 'YYYY-MM-DD') FROM DUAL;
-- 日期差
SELECT SYSDATE - TO_DATE('2024-01-01', 'YYYY-MM-DD') FROM DUAL; -- 天数差
SELECT MONTHS_BETWEEN(SYSDATE, TO_DATE('2024-01-01', 'YYYY-MM-DD')) FROM DUAL; -- 月数差
-- 日期截取
SELECT TRUNC(SYSDATE) FROM DUAL; -- 截取到日期
SELECT TRUNC(SYSDATE, 'MM') FROM DUAL; -- 截取到月初
SELECT TRUNC(SYSDATE, 'YYYY') FROM DUAL; -- 截取到年初数值函数
sql
-- 四舍五入
SELECT ROUND(123.456, 2) FROM DUAL; -- 123.46
SELECT ROUND(123.456) FROM DUAL; -- 123
-- 向上取整
SELECT CEIL(123.456) FROM DUAL; -- 124
-- 向下取整
SELECT FLOOR(123.456) FROM DUAL; -- 123
SELECT TRUNC(123.456) FROM DUAL; -- 123
-- 绝对值
SELECT ABS(-123) FROM DUAL; -- 123
-- 随机数
SELECT DBMS_RANDOM.VALUE FROM DUAL; -- 0 到 1 之间的随机数
SELECT TRUNC(DBMS_RANDOM.VALUE(0, 100)) FROM DUAL; -- 0 到 99 的随机整数
-- 最大值和最小值
SELECT GREATEST(1, 2, 3, 4, 5) FROM DUAL; -- 5
SELECT LEAST(1, 2, 3, 4, 5) FROM DUAL; -- 1
-- 取模
SELECT MOD(10, 3) FROM DUAL; -- 1
SELECT 10 % 3 FROM DUAL; -- 1
-- 幂运算
SELECT POWER(2, 3) FROM DUAL; -- 8
-- 平方根
SELECT SQRT(16) FROM DUAL; -- 4条件函数
sql
-- DECODE 函数
SELECT DECODE(status, 'A', 'Active', 'I', 'Inactive', 'Unknown') FROM users;
-- CASE 语句
SELECT CASE
WHEN score >= 90 THEN 'A'
WHEN score >= 80 THEN 'B'
WHEN score >= 70 THEN 'C'
ELSE 'F'
END AS grade
FROM students;
-- NVL 和 NVL2
SELECT NVL(email, 'No Email') FROM users; -- 如果为 NULL 则返回默认值
SELECT NVL2(email, 'Has Email', 'No Email') FROM users; -- 如果为 NULL 返回第二个值,否则返回第三个值
-- COALESCE
SELECT COALESCE(email, phone, 'No Contact') FROM users; -- 返回第一个非 NULL 值系统函数
sql
-- 数据库信息
SELECT SYS_CONTEXT('USERENV', 'DB_NAME') FROM DUAL;
SELECT USER FROM DUAL;
SELECT SYS_CONTEXT('USERENV', 'SESSION_USER') FROM DUAL;
SELECT * FROM V$VERSION;
-- 序列
CREATE SEQUENCE seq_users START WITH 1 INCREMENT BY 1;
SELECT seq_users.NEXTVAL FROM DUAL;
SELECT seq_users.CURRVAL FROM DUAL;
-- 系统时间
SELECT SYSDATE FROM DUAL;
SELECT SYSTIMESTAMP FROM DUAL;常用查询模式
sql
-- 分页查询
SELECT * FROM (
SELECT ROW_NUMBER() OVER (ORDER BY id) AS rn, *
FROM users
) WHERE rn BETWEEN 21 AND 30;
-- 查找重复记录
SELECT email, COUNT(*) AS count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;
-- 查找缺失的 ID
SELECT t1.id + 1 AS missing_id
FROM users t1
LEFT JOIN users t2 ON t1.id + 1 = t2.id
WHERE t2.id IS NULL
AND ROWNUM <= 1;
-- 随机抽样
SELECT * FROM (
SELECT * FROM users ORDER BY DBMS_RANDOM.VALUE
) WHERE ROWNUM <= 10;
-- 查找最近 N 天的记录
SELECT * FROM orders
WHERE order_date >= SYSDATE - 7;
-- 查找每个分类的最新记录
SELECT p1.*
FROM products p1
INNER JOIN (
SELECT category, MAX(created_at) AS max_date
FROM products
GROUP BY category
) p2 ON p1.category = p2.category AND p1.created_at = p2.max_date;最佳实践
数据库设计
- 合理使用数据类型:选择合适的数据类型,避免过度使用 VARCHAR
- 规范化设计:遵循数据库规范化原则,避免数据冗余
- 使用外键约束:确保数据完整性
- 合理使用索引:为经常查询的列创建索引,但不要过度索引
- 使用序列:使用序列生成主键值
查询优化
- 使用 EXPLAIN:分析查询执行计划
- **避免 SELECT ***:只选择需要的列
- 使用 ROWNUM:限制结果集大小
- 合理使用 JOIN:避免笛卡尔积
- 使用 EXISTS 而不是 COUNT:检查存在性时使用 EXISTS
索引优化
- 为 WHERE 子句中的列创建索引
- 为 JOIN 条件创建索引
- 为 ORDER BY 和 GROUP BY 创建索引
- 使用复合索引:为多列查询创建复合索引
- 定期分析索引使用情况:删除未使用的索引
维护
- 定期收集统计信息:使用 ANALYZE TABLE 或 DBMS_STATS
- 定期备份:制定并执行定期备份策略
- 监控数据库大小:定期检查数据库和表的大小
- 监控性能:使用 V$ 视图监控数据库性能
- 定期清理:清理无用的数据和对象
故障排查
查看日志
sql
-- 查看错误日志位置
SELECT * FROM V$PARAMETER WHERE name = 'LOG_FILE_PATH';
-- 查看告警日志
-- 日志文件通常在 $DM_HOME/log 目录下连接问题
sql
-- 查看当前连接
SELECT * FROM V$SESSIONS;
-- 查看连接数
SELECT COUNT(*) FROM V$SESSIONS;
-- 终止连接
ALTER SYSTEM KILL SESSION 'sid,serial#';
-- 查看锁
SELECT * FROM V$LOCK;
SELECT * FROM V$LOCKED_OBJECT;性能问题
sql
-- 查看慢查询
SELECT * FROM V$SQL WHERE elapsed_time > 1000000;
-- 查看表统计信息
SELECT * FROM USER_TAB_STATISTICS WHERE table_name = 'USERS';
-- 查看索引使用情况
SELECT * FROM USER_INDEXES WHERE table_name = 'USERS';空间问题
sql
-- 查看数据库大小
SELECT
tablespace_name,
ROUND(SUM(bytes) / 1024 / 1024, 2) AS size_mb
FROM DBA_DATA_FILES
GROUP BY tablespace_name;
-- 查看表大小
SELECT
segment_name,
ROUND(SUM(bytes) / 1024 / 1024, 2) AS size_mb
FROM USER_SEGMENTS
WHERE segment_type = 'TABLE'
GROUP BY segment_name
ORDER BY size_mb DESC;学习资源
💡 常用命令速查
sql
-- 数据库操作
SELECT * FROM V$DATABASE;
SELECT SYS_CONTEXT('USERENV', 'DB_NAME') FROM DUAL;
-- 表操作
SELECT * FROM USER_TABLES;
DESC table_name;
SELECT * FROM USER_TAB_COLUMNS WHERE table_name = 'USERS';
-- 查询
SELECT * FROM table;
EXPLAIN SELECT * FROM table;
-- 索引
SELECT * FROM USER_INDEXES WHERE table_name = 'USERS';
CREATE INDEX idx ON table(column);
DROP INDEX idx;
-- 用户和权限
SELECT * FROM DBA_USERS;
CREATE USER user IDENTIFIED BY password;
GRANT privilege TO user;
REVOKE privilege FROM user;🔧 实用脚本
备份脚本
bash
#!/bin/bash
# 备份脚本
BACKUP_DIR="/backup/dameng"
DATE=$(date +%Y%m%d_%H%M%S)
DB_USER="SYSDBA"
DB_PASS="SYSDBA"
DB_HOST="localhost"
DB_PORT="5236"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 逻辑备份
dexp $DB_USER/$DB_PASS@$DB_HOST:$DB_PORT FILE=$BACKUP_DIR/backup_${DATE}.dmp FULL=Y
# 删除 7 天前的备份
find $BACKUP_DIR -name "*.dmp" -mtime +7 -delete监控脚本
sql
-- 查看数据库统计信息
SELECT
'Connections' AS Metric,
COUNT(*) AS Value
FROM V$SESSIONS
UNION ALL
SELECT
'Active Sessions',
COUNT(*)
FROM V$SESSIONS
WHERE status = 'ACTIVE'
UNION ALL
SELECT
'Database Size (MB)',
ROUND(SUM(bytes) / 1024 / 1024, 2)
FROM DBA_DATA_FILES;