达梦:用户 User 即 模式 schema
-- 模式就类似于mysql中的数据库
-- 创建用户达梦是默认创建同名的模式
DROP USER IF EXISTS app CASCADE;
-- with admin option:形同于 mysql中的 with grant option
-- 意思是:你创建的这个用户可以给别人继续赋值权限
create user app indentified by "ITcast888!" with admin option;
-- 密码:8位、大小写、数字、特殊字符
-- 给所有的权限
grant dba to app;
-- 切换模式
set schema 模式名称;
-- 在指定用户下创建模式 【可以不用】
create schema 名称 authorization 用户名;
在达梦里:
- 创建用户
app,会自动生成一个同名的模式app; - 模式(SCHEMA)就是存放表、视图、索引的 "文件夹"。
切换模式之后,再建表,表自动创建到 app 用户自己的模式里。
不切模式,表自动创建到 app 用户自己的模式里。CREATE TABLE SYSDBA.student(id int);
字段类型对照
|------|----------------------|---------------------------|-----------------|
| 场景 | MySQL | 达梦 DM8 | 说明 |
| 整数 | INT/BIGINT | 同名支持 | 范围略有差异 |
| 定点数 | DECIMAL(p,s) | DECIMAL/NUMBER | 财务推荐 |
| 浮点数 | FLOAT/DOUBLE | FLOAT/DOUBLE | 非精确 |
| 字符 | VARCHAR、TEXT | VARCHAR2、VARCHAR、CLOB | TEXT → CLOB |
| 二进制 | BLOB/VARBINARY | BLOB/RAW | 大对象用 BLOB |
| 日期时间 | DATETIME/TIMESTAMP | DATE/TIMESTAMP | DATE 含时分秒 |
| 布尔 | BOOLEAN | TINYINT/CHAR(1) | 用 0/1 或 Y/N |
varchar2 和 varchar 有什么区别?
varchar2 是 Oracle 当中主推的类型。
varchar和varchar2
varchar中 '' ≠ null
varchar2中 '' = null
登录
# 写绝对路径执行脚本看状态
/home/dmdba/dmdbms/bin/DmServiceDMSERVER status
#登录
disql SYSDBA/Sysdba123@localhost:5236
建表示例
删表
drop table if exists app.users;
建表
create table app.users(
id bigint primary key,
username varchar2(50) not null,
email varchar2(200) unique,
status char(1) default 'a' check (status in ('a','d')),
created_at timestamp default current_timestamp
);
看表
select table_name from dba_tables where owner='APP';
select * from users;
创建序列(自增主键)
create sequence app.auto_increments
start with 1
increment by 2
nocache
no cycle;
create sequence app.auto_increments在app模式下,创建名为auto_increments的序列。start with 1序列初始值:从数字 1 开始。increment by 2每次取值自增 2,取值依次为:1 → 3 → 5 → 7...... 只生成奇数。nocache不缓存序列号。每次都从数据库读取最新值,避免并发场景下出现序号跳号。no cycle序号达到最大值后不再循环,再次取值会直接报错。
删除序列
drop sequence auto_increments;
插入数据
insert into app.users(id,username,email)
values (app.seq_users.nextval,'alice','a@x.com');
insert into app.users(id,username,email)
values (app.seq_users.nextval,'bob','b@x.com');
- 第一次执行
app.seq_users.nextval拿到数字:1,序列内部计数器变成 2 - 第二次再执行
app.seq_users.nextval拿到数字:2,计数器变成 3
正好用来给主键 ID 自动生成 1、2、3、4...... 自增编号。
select * from app.users;
select app.seq_users.currval as last_id from dual;
currval:读取当前会话里刚刚拿到的序列号,不会让序号继续增长。as last_id:给查询结果列起别名。from dual:达梦 / Oracle 必须带的虚拟空表。
用途:刚插入完一条数据,立刻拿到这条记录的自增主键 ID。
查询五子句
#分组统计每个状态的人数
select status,count(*) as cnt
from app.users
group by status;
#只保留数量大于 1 的分组
select status,count(*) as cnt
from app.users
group by status
having count(*) >1;
#按创建时间倒序排列
select id,username,users.created_at
from app.users
order by created_at desc;
#分页查询:跳过前 10 条,再取出后面 5 条
select id,username,users.created_at
from app.users
order by created_at asc
offset 10 rows fetch next 5 rows only;
-
offset 10 rows:跳过前 10 行; -
fetch next 5 row only:只读取接下来的 5 行;select * from users limit 0,2;
select * from users limit 2,2;
select * from users limit 3;
select * from users offset 4 rows fetch next 3 rows only;
select * from users order by id fetch next 3 rows only;select rownum from users;
select rownum from stus;
select rownum from users2;select * from (select *,rownum rn from users) w
where w.rn between 1 and 2;select * from (select *,rownum rn from users) w
where w.rn = 2;
rownum是 Oracle / 达梦的伪列,会给每一行自动生成行号 1,2,3......
核心知识点(rownum 陷阱)
rownum是动态生成的,只能用:rownum < Nrownum <= Nrownum = 1
- 直接写
rownum=2、rownum>2查不出结果,必须把行号放到子查询里变成普通字段,再在外层过滤。
多表查询
建表
CREATE TABLE app.orders (
id INT PRIMARY KEY, -- 订单ID
user_id INT NOT NULL, -- 下单用户ID,外键关联 users.id
amount DECIMAL(12,2) NOT NULL, -- 订单金额
status CHAR(1) ,
-- N=新建, P=已支付, C=已取消
created_at TIMESTAMP,
CONSTRAINT fk_orders_user FOREIGN KEY (user_id)
REFERENCES app.users(id)
);
-- 插入一些订单
INSERT INTO app.orders (id, user_id, amount, status)
VALUES (1001, 1, 99.90, 'P');
INSERT INTO app.orders (id, user_id, amount, status)
VALUES (1002, 2, 199.50, 'N'); -- 用户必须存在
INSERT INTO app.orders (id, user_id, amount, status)
VALUES (1003, 2, 49.99, 'C');
内连接
SELECT u.username, o.amount
FROM app.users u
INNER JOIN app.orders o ON u.id = o.user_id;
- 效果:只查询同时存在用户和对应订单的数据;
- 没有订单的用户,不会出现在结果集中。
左连接
SELECT u.username, o.amount
FROM app.users u
LEFT JOIN app.orders o ON u.id = o.user_id;
- 效果:以左表
users为主,所有用户全部保留; - 没有订单的用户,订单字段会显示为
NULL。
子查询
查出金额大于 100 元订单的用户 ID,再找出这些用户的姓名。
SELECT username
FROM app.users
WHERE id IN (SELECT user_id FROM app.orders WHERE amount > 100);
自关联
自关联就是一张表自己和自己 JOIN,一张表起两个不同别名。以订单表举例:查询同一个用户下金额更大的订单记录
SELECT o1.*, o2.amount
FROM app.orders o1
JOIN app.orders o2
ON o1.user_id = o2.user_id
AND o1.amount < o2.amount;
用户与权限
创建用户与授权
-- 创建用户 report,密码带大小写+特殊字符,双引号严格保留格式
CREATE USER report IDENTIFIED BY "Report123!";
-- 授予登录数据库的会话权限
GRANT CREATE SESSION TO report;
-- 授予 report 用户只能查询 app.users 这张表,不能增删改
GRANT SELECT ON app.users TO report;
- 系统权限(用户、角色、会话、建库建表权限)→ 用
with admin option - 表 / 视图的增删改查权限 → 用
with grant option
给 app 用户授予一系列开发常用权限,让该账号可以登录数据库、创建模式、建表、视图、序列、触发器,满足日常开发需求。
-- 允许用户登录数据库,建立会话连接
GRANT CREATE SESSION TO app;
-- 允许用户创建自己的模式(schema)
GRANT CREATE SCHEMA TO app;
-- 允许创建数据表
GRANT CREATE TABLE TO app;
-- 允许创建视图
GRANT CREATE VIEW TO app;
-- 允许创建序列(自增主键用)
GRANT CREATE SEQUENCE TO app;
-- 允许创建触发器
GRANT CREATE TRIGGER TO app;
| 权限 | 作用 |
|---|---|
CREATE SESSION |
核心登录权限,没有这条,用户无法连接数据库 |
CREATE SCHEMA |
可以新建自定义模式 |
CREATE TABLE |
在自己模式下建表 |
CREATE VIEW |
基于数据表创建视图 |
CREATE SEQUENCE |
创建自增序列,实现主键自增 |
CREATE TRIGGER |
编写触发器,实现数据自动联动 |
系统权限统一使用
WITH ADMIN OPTION。
-- 允许创建存储过程、自定义函数
GRANT CREATE PROCEDURE TO app;
-- 允许在自己的表上创建索引
GRANT CREATE INDEX TO app;
-- 或
GRANT RESOURCE TO app;
GRANT CREATE SESSION TO app;
CREATE PROCEDURE:系统权限,用来编写存储过程、函数,封装复杂业务逻辑。CREATE INDEX:允许给数据表建立索引,优化查询速度。
角色
角色(role)就是权限打包容器:把一堆权限先放进角色里,再把角色分配给多个用户,不用一条条给每个用户单独授权,批量管理权限。
-- 1. 创建角色
create role app_dev;
-- 2. 给角色授予权限(把权限打包进角色)
grant create session, create table, create sequence to app_dev;
grant select on app.users to app_dev;
-- 3. 把角色分配给用户,用户自动继承角色内所有权限
grant app_dev to app;
grant app_dev to report;
-
权限 → 授予给角色
-
角色 → 授予给用户
-
用户 = 自身直接权限 + 所有被分配角色的权限
-- 回收用户身上的角色
revoke app_dev from report;-- 删除角色
drop role app_dev;
回收权限
回收 report 用户对 app.users 这张表的查询(SELECT)对象权限
REVOKE SELECT ON app.users FROM report;
对象权限 + WITH GRANT OPTION,回收时会连带级联回收
执行后:
- report 自身权限被收回
- test 从 report 获得的同一张表查询权限也会自动消失
对比:系统权限
WITH ADMIN OPTION回收不会级联下级权限。
查询这条权限是否生效
-- 管理员查看
select grantee,table_name,privilege,grantable
from dba_tab_privs
where table_owner='APP' and table_name='USERS';
GRANTABLE 字段会显示为 YES,代表支持转授。
查看权限
user_tab_privs 是数据字典视图,用来查看当前登录用户自己拥有的所有表对象权限(SELECT、INSERT、UPDATE、DELETE 等
-- 查看所有的
select * from user_tab_privs;
三条同类字典视图区别
user_tab_privs只看当前自己账号拥有的表权限。
all_tab_privs查看当前用户自己 + 被授予角色带来的所有表权限。
dba_tab_privs管理员视图,查看全库所有用户的表权限(需要 DBA 权限才能查询)
修改权限
grant 新权限 on 模式.表名 to 用户名
grant 新权限 to 用户名;
限定用户信息
-- 允许哪些ip使用app用户登录
ALTER USER APP ALLOW_IP '192.168.1.10','192.168.1.11';
-- 用户只能查,不能增删改任何表
ALTER USER APP READ ONLY;
-- 恢复正常读写
ALTER USER APP NOT READ ONLY;
备份与恢复
导出命令:
/home/dmdba/dmdbms/bin/dexp导入命令:
/home/dmdba/dmdbms/bin/dimp备份存放:/home/dmdba/backup/
dexp导出工具(逻辑备份)
mkdir -p /home/dmdba/backup
chown dmdba:dmdba /home/dmdba/backup
chmod 700 /home/dmdba/backup
su - dmdba
# 注意:密码中千万别带@
/home/dmdba/dmdbms/bin/dexp app/'ITcast888!'@127.0.0.1:5236 \
FILE=/home/dmdba/backup/app_$(date +%F).dmp \
LOG=/home/dmdba/backup/app_$(date +%F).log
-- 如果只导出某个模式,可以添加 schemas=模式名称
-p:多级目录自动创建,不报错chown:把文件夹归属改为数据库运行用户 dmdba700:仅 dmdba 可读写,安全权限
必须 dmdba 用户执行导出工具,root 会环境异常。
SCHEMAS=APP:只导出 APP 这一个模式(用户)$(date +%F):自动拼接当天日期- 注意:密码里不能包含
@,会被 Shell 截断
dimp导入
/home/dmdba/dmdbms/bin/dimp app/'ITcast888!'@127.0.0.1:5236 FILE=/home/dmdba/backup/备份生成的文件名.dmp LOG=/home/dmdba/backup/备份生成的文件名.log FULL=y
FULL=Y 全量完全导入:把 dmp 里所有对象(用户、表、数据、视图、序列、存储过程)全部恢复到库中