Oracle数据库(完整版)

Oracle数据库(完整版),第1张

Oracle数据库

文章目录 Oracle数据库学习目标1 OracleXE安装2 安装客户端3 数据库入门DBMSSQL语言 SQL的分类 4 数据库--表表(Table)表结构 5 SELECT(表查询)1 简单查询2 部分列3 所有列4 去除重复5 别名6 伪列7 虚表8 null(空)9 查询行(记录)1 比较条件2 逻辑运算3 集合 *** 作4 null (空)5 like:模糊查询6 in7 exists8 获取所有行记录 10 排序(order by) 6 函数1 单行函数1 日期函数2 转换函数to_dateto_char 3 其他函数 2 多行|聚合|组函数1 count:统计记录数2 max、min:最大值、最小值3 sum:求和4 avg:平均值 3 分组(group by)4 行转列5 rowid 与 rownumrowidrownum 7 表连接表连接(sql92)1 笛卡尔积2 等值连接3 非等值连接4 自连接5 外连接 表连接(sql99)1 交叉连接2 自然连接3 using连接4 on连接5 外连接6 全连接 8 视图与索引视图view索引(了解) 9 表设计三范式设计表创建表约束 10 DDL创建表删除表修改表 11 事务事务的特点(ACID)事务的隔离级别事务的开启事务的结束 12 DML1 insert2 delete3 update4 截断数据5 序列1 创建序列2 使用3 删除

学习目标

1 OracleXE安装

官方网站下载地址:

http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html

选择下一步,下一步…完成

测试:

开始—>运行SQL命令行—> 输入测试命令 conn sys as sysdba —>输入密码(密码不会显示)

2 安装客户端

选择下一步,下一步…完成

导入scott.sql文件:

1.使用管理员进入dos(SQL)
conn sys as sysdba;
2.查找scott.sql 文件位置
C:\oraclexe\app\oracle\product.2.0\server\rdbms\admin\scott.sql
3.执行脚本文件
@C:\oraclexe\app\oracle\product.2.0\server\rdbms\admin\scott.sql
;
4.使用 sql(dos) || plsql 登录
dos窗口:
conn scott as sysdba; 密码为TIGER
select * from scott.emp;
plsql登录
登录界面 scott/TIGER
数据库 XE 身份normal
select table_name from tabs;
desc emp;
select * from emp;

3 数据库入门

数据库(DataBase):按照数据结构来组织、存储和管理数据的仓库。

常用的数据有:

MySQLOracleServerSQLDB2sybase

DBMS

数据库管理系统(DataBase Management System)是一种 *** 纵和管理数据库的大型软件,用于建立、使用和维护数据库。

DBMS提供了数据定义语言DDL(Data Definition Language)、数据 *** 作语言DML(Data Management Language)供用户定义数据库的模式结构与权限约束,实现对数据的追加、删除等 *** 作。

根据存储模型可将数据库划分为关系型数据库和非关系型数据库。关系型数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。简单来说,关系模型指的就是二维表格模型,而一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织。

Oracle Database,又名 Oracle RDBMS,或简称 Oracle。是甲骨文公司的一款关系数据库管理系统。

SQL语言

SQL(Structured Query Language)结构化查询语言是的一种介于关系代数与关系演算之间的结构化查询语言,是一个通用的、功能极强的关系型数据库语言。

SQL的分类

DML:Data Manipulation Language 数据 *** 纵语言

DDL:Data Definition Language 数据定义语言

DCL:Data Control Language 数据库控制语言

DQL:Data Query Language 数据库查询语言

命令分类 *** 作:

分类描述命令
DDL数据定义语言create:创建;drop:删除;alter:修改;rename: 重命名; truncate:截断
DML数据 *** 作语言insert:插入;delete:删除;update:更新;select:查询
DCL数据控制语言grant:授权;revoke:回收权利;commit:提交事务;rollback:回滚事务
4 数据库–表 表(Table)

查询表(用户名.表名),当前用户查询自己的表时,用户名.可以省略,其他用户查询别的用户表 ,不能省略,同时必须存在权限。

表是逻辑表概念表,不是物理表。

块(8k) —>区(连续块)–>段(连续区) -->表(多个段) ,数据段不全是表,表一定是数据段。还有其他段:如索引段

表结构

表由表名、字段(名称+类型+约束)、记录 组成。与Java对应。

DBJava
表名类名
字段名属性名
字段类型:numeric char varchar date…属性类型:基本数据类型、引用数据类型
字段约束:约束行为->创建表结构时加入, *** 作数据时生效方法检查条件
记录:数据对象:new

注意:Mysql命令不区分大小写(SELECT 与 select), 存储数据|内容 区分大小写

5 SELECT(表查询) 1 简单查询
select 字段名称列表 from 表名;
2 部分列
select 列名1,列名2 from 表名; 
eg:
select deptno,dname,loc from dept;
-- 查询部门表的deptno,dname, loc字段的数据
3 所有列
select * from;

通配符 * ( 书写方便、可以检索未知列;但是降低检索的性能)

eg:
-- 1)、检索所有列1
select * from dept; -- 查询部门的所有信息
-- 2)、检索所有列2
select deptno,dname,loc from dept; -- 查询部门的所有信息
4 去除重复

使用 distinct 去重,确保查询结果的唯一性

select distinct 字段名 from 表名;
5 别名

使用别名便于 *** 作识别 、隐藏底层信息。存在字段别名和表别名

as:字段别名可以使用as;表别名不能使用as

“”:原样输出,可以存在空格与区分大小写

select 字段名 as "字段别名" from 表名 表别名;
select 字段名 "字段别名" from 表名 表别名;
eg:
select ename as 雇员姓名 from emp e;
select ename "Ename" from emp e;
6 伪列

不存在的列,构建虚拟的列

select empno,1*2 as count,'cmj' as name,deptno from emp;
7 虚表

dual表:用于计算表达式,显示单条记录的值

select 1+1 from dual;
8 null(空)

null 遇到数字参与运算的结果为 null,遇到字符串为空串

1.筛选 where

判断是null: 字段名 is null

判断不是null: 字段名 is not null

​ not 字段名 is null

2.处理具有null的字段

nvl()函数:nvl(expression, alt_value)

如果第一个参数的表达式 expression 为 NULL,则返回第二个参数的备用值

eg: 
nvl(comm,0)
-- 解释:当comm值为null时,取0替代。 
9 查询行(记录)

where 过滤行记录,条件有:

a)、= 、 >、 <、 >=、 <=、 !=、 <>、 between and
b)、and 、or、 not、 union、 union all、intersect、minus
c)、null :is null、 is not null、 – not is null
d)、like :模糊查询 % _ escape(‘单个字符’)
f )、in 、 exists(难点) 及子查询

1 比较条件

= 、>、 <、 >=、 <=、 !=、 <>(不等于)

between (最小值) and (最大值):在最小值到最大值之间,[min,max]

2 逻辑运算

and:与、和

or:或

not:非、不

3 集合 *** 作

union:并集(去重),对两个结果集进行并集 *** 作,不包括重复行同时进行默认规则的排序

union all:全集(不去重),对两个结果集进行并集 *** 作,包括重复行,不进行排序

intersect:交集(找出重复), 对两个结果集进行交集 *** 作,不包括重复行,同时进行默认规则的排序

minus:差集(减去重复),对两个结结果集进行差 *** 作,不包括重复行,同时进行默认规则排序

4 null (空)

null不能使用条件判断,只能使用 is

is null:为空的

not is null || is not null :不为空的

5 like:模糊查询 %:0个及以上(任意个)字符_:一个任意字符escape:遇到内容中包含 % _ 使用escape(‘单个字符’)指定转义符 6 in

in相当于使用or的多个等值,定值集合 ,如果存在子查询,确保类型相同、字段数为1,如果记录多,效率不高,用于 一些少量定值判断上

7 exists

exists条件为true,存在记录则返回结果,后续不再继续比较查询,与查询的字段无关,与记录有关

8 获取所有行记录
select * form 表名;
select * from 表名 where 1=1;
select * from 表名 where 字段名 like '%';
10 排序(order by)

排序不是真实改变存储结构的顺序,而是获取的集合的顺序

顺序 :asc(默认升序)、 desc (降序) ascending 升序 ,descending 降序多字段: 在前面字段相等时,使用后面的字段排序空排序: 降序为 desc,注意 null 为最后
select 字段列表 from 表名 order by 要排序的字段名 asc|desc;
eg:
select ename,sal from emp order by sal desc;
-- 将sal字段进行降序排列;
6 函数

函数主要分为系统内置函数、自定义函数

根据函数的返回结果,将函数分为单行函数和多行函数

单行函数:一条记录返回一个结果

多行函数:多条记录返回一个结果---->组函数|聚合函数

1 单行函数 1 日期函数

区分 db数据库时间 和 java应用服务器时间

oracle以内部数字格式存储日期年月日时分秒

当前时间:sysdate/current_date

修改日期:sysdate+-x

修改月份:add_months(d, x)

最后一天:last_day(d)

月份之差:months_between(date1,date2)

下个星期:next_day(sysdate,星期数)

2 转换函数 to_date

字符串以指定格式转换为日期

to_char

日期以指定格式转换为字符串

3 其他函数

1)nvl

nvl(string1, string2)
-- 如果string1为null,则结果为string2的值,否则为string1的值

2)decode

decode(condition,case1,express1,case2,express2,... casen,expressn,expressionm)
-- decode(条件,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值)

3)case when then else end

case [<表达式>]
when <表达式条件值1> then <满足条件时返回值1> 
[when <表达式条件值2> then <满足条件时返回值2> 
......
[else  <不满足上述条件时返回值>]]
end
/* 
当<表达式>=<表达式条件值1……n>时,返回对应<满足条件时返回值1……n>
当<表达式条件值1……n>不为条件表达式时,与函数decode()相同,
*/
2 多行|聚合|组函数

多条记录 返回一个结果

1 count:统计记录数
select count(1) from emp;
select count(empno) from emp;
2 max、min:最大值、最小值
select max(sal) from emp;
select min(sal) from emp;
3 sum:求和
select sum(sal) from emp;
4 avg:平均值
select avg(sal) from emp;

注意:

1、组函数仅在选择列表和 having 子句中有效

2、出现组函数,select只能有组函数或分组字段

3、组信息与单条记录不能同时查询

4、组函数 不能用在 where中,能使用的地方 select 、having

5、null 不参与运算

3 分组(group by)

分组:group by ,将符合条件的记录 进一步的分组

过滤组:having,过滤组信息 ,表达式同where 一致

到目前为止的结构如下:

select distinct *|字段列表|表示式|函数  as 别名
from 表 表别名
where 过滤行记录条件
group by 要分组的字段列表
having 过滤组
order by 要排序的字段列表 asc | desc ;

执行顺序:

from --> where --> group by --> having --> select --> order by

where 与 having 的区别:

where:过滤行记录,不能使用组函数

having:过滤组,可以使用组函数

4 行转列

使用 decode 函数转换

优点:

解耦(与记录之间) + 扩展(与结构之间)

5 rowid 与 rownum rowid

用于定位数据库中一条记录的一个相对唯一地址值,该值在该行数据插入到数据库表时即被确定且唯一。

rowid它是一个伪列,它并不实际存在于表中,它是ORACLE 在读取表中数据行时,根据每一行数据的物理地址信息编码而成的一个伪列,使用ROWID 来进行单记录定位,用于删除重复数据

思路:

将所有记录按照某种特定规律分组(相同的记录为一组),保留下每组中的一条记录即可,其他记录删除

select e.*,rowid from emp e;
rownum

rownum是一种伪列,它会根据返回记录生成一个序列化的数字,排序后的结果集的顺序号,每一个结果集都有自己顺序号 ,不能直接查询大于 1 的数,用于实现分页 *** 作

-- 查询工资为前5面的员工
select temp.*,rownum from 
  (select * from emp order by sal desc) temp
where rownum <=5; 

-- 查询工资在3-5名的员工
select * from (
  select e.*, rownum rn
    from (
      select * from emp order by sal desc) e
  where rownum <= 5) t
where t.rn >= 3
7 表连接

当我们获取的数据不是来自于同一张表而是来自于多张表时就需要使用到表连接

表连接(sql92) 1 笛卡尔积

表1有m行,表2有n行,结果为m*n行

select * from emp,dept;
select ename,dname,from emp,dept;
select ename,dname,e.deptno from emp e,dept d;
2 等值连接

在笛卡尔积基础上取条件列相同的值

-- 员工名称及部门名称 
select ename, dname, e.deptno from emp e, dept d where e.deptno = d.deptno;
3 非等值连接
-- 查询员工姓名,工资及等级,900 属于哪个等级 
select grade from salgrade where 900 > losal and 900 < hisal;
4 自连接

特殊的等值连接,来自同一张表

-- 找出存在上级的员工姓名及上级名称
select e.ename, m.ename from emp e, emp m where e.mgr = m.empno;
5 外连接

主要看逗号, 主表在逗号的左边就叫左外连接,主表在逗号的右边叫右外连接

-- 找出所有部门的员工数及部门名称 
select dname, nu from dept d, 
  (select count(1) nu, deptno from emp group by deptno) e 
where d.deptno(+) = e.deptno;
表连接(sql99) 1 交叉连接

相当于笛卡尔积

cross join

select * from emp cross join dept;
2 自然连接

natural join :自动做等值连接

select * from emp natural join dept;
3 using连接

using(字段名):指定同名字段做等值连接

select deptno,e.ename,d.dname from emp e join dept d using(deptno);
4 on连接

join … on

-- 查询部门编号为30的员工姓名及部门名称
select ename,dname from emp join dept
on emp.detpno = dept.deptno
where emp.deptno = 30;
5 外连接

左外连接:left outer join … on

左表不加限制,保留左表的数据,匹配右表,右表没有匹配到的行中的列显示为null。

右外连接:right outer join … on

右表不加限制,保留右表的数据。匹配左表,左表没有匹配到的行中列显示为null。

-- 所有部门的部门名称及员工数
-- 左外连接
select dname, n from dept d left outer join 
  (select deptno, count(1) n from emp group by deptno) i 
on d.deptno = i.deptno;
-- 右外连接
select dname, n from 
  (select deptno, count(1) n from emp group by deptno) i 
  right outer join dept d 
on d.deptno = i.deptno;
6 全连接

full join 关键字会从表中返回所有的行,即使表没有的行,也会返回空行

select * from 
  (select 1 no, 'a' "name" from dual 
   union 
   select 2 no, 'b' "name" from dual) a 
  full join 
    (select 1 no, 'c' "name" from dual 
     union 
     select 3 no, 'd' "name" from dual) b 
on a.no = b.no;
8 视图与索引 视图view

建立在建立在表|结果集|视图上的虚拟表,有以下作用:

1、简化:select查询语句

2、重用:封装select语句、命名

3、隐藏:隐藏内部的细节

4、区分:相同数据不同查询

不是所有的用户都有创建视图的权限

1、前提: create view -->组 connect resource dba

2、授权: -->sqlplus /nolog

1)sys登录 conn sys/123456 as sysdba

2)授权:grant dba to scott;

回收:revoke dba from scott;

3)重新登录

创建视图:

create or replace view 视图名 as select语句 [with read only];

要求:所有列必须存在名称

索引(了解)

提高查询速度的一种手段 -->目录

1、唯一性较好字段适合建立索引

2、大数据量才有效果

3、主键|唯一: 唯一索引

创建索引:

create index 索引名 on 表名(字段列表);

删除索引:

drop index 索引名;
9 表设计 三范式

在设计数据库时,存在行业的标准,这个标准也称为条件,即范式 Normal Form。

一般遵循三个条件即可,也就是”三范式”(3NF)。

1NF:

指数据库的每一列都是不可分割的基本数据项,同一列中不能有多个值。即实体中的某个属性不能有多个值或者不能有重复的属性。

如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。

2NF:

要求数据库表中的每个实例或行必须可以被唯一地区分,为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。

唯一属性列被称为主关键字或主键、主码

满足第二范式(2NF)必须先满足第一范式(1NF)

3NF:

要求一个数据库表中不包含已在其它表中已包含的非主关键字信息

第三范式就是属性不依赖于其它非主属性。

必须先满足第二范式(2NF)

简而言之,最终的目的避免数据重复冗余

1NF–>列不可再分最小原子 (避免重复)

2NF–>主键依赖(确定唯一)

3NF–>消除传递依赖(建立主外键关联 拆分表)

设计表

前提:遵循三范式

1、确定表名

2、确定字段名:类型 + 约束(主键 外键 非空 默 检查认 唯一)

创建表

表名必须唯一,如果存在 ,必须删除

create table 表名( 

	字段名 类型(长度) 约束, 

	...其他字段.... 

	..约束.....
);
约束

在 oracle中所有的一切都是对象, 约束也是一个个的对象,除了能创建约束我们还能对约束进行一些其他的 *** 作:

常见的约束有:

主键: 唯一标识一条记录(唯一并且非空)

唯一: 唯一

非空:不能为空

默认: 当没给值时使用给定一个默认值

外键:参考其他表(自己)的某个(某些)字段

检查:自定义的规则

1、查看某个用户的约束

select constraint_name, constraint_type 
 from user_constraints 
where owner = upper('SCOTT');

2、 查看表的约束

select constraint_name, constraint_type 
 from user_constraints 
where table_name = upper('emp');

3、 查看 字段名+约束

select constraint_name, column_name 
 from user_cons_columns 
 where table_name = upper('emp');

4、 约束的禁用与启用

ALTER TABLE tb_user disable constraint nn_user_name; 
ALTER TABLE tb_user enable constraint nn_user_name;

5、删除约束

alter table tb_user drop constraint uq_user_email cascade;

6、修改约束

-- 非空 
alter table tb_user modify (username varchar2(20)); 
-- 默认 
alter table tb_user modify (age default null);
10 DDL

DDL(Data Definition Language 数据定义语言)用于 *** 作对象和对象的属性,这种对象包括数据库本身,以及数据库对象,像:表、视图等等,DDL 对这些对象和属性的管理和定义具体表现在 create、drop 和 alter 上。

语句作用
create可以创建数据库和数据库的一些对象
drop可以删除数据表、索引、条件约束等
alter修改数据表定义及属性
创建表

表名必须唯一,如果存在 ,必须删除

create table 表名( 
	字段名 类型(长度) 约束, 
	...其他字段.... 
	..约束.....
);
删除表

1、删除表

drop table 表名;

2、主从表下删除表

先删除从表 再删除主表 ;同时删除约束

drop table 从表名 cascade constraints; 
drop table 主表名 cascade constraints;

3、删除主表的同时级联删除约束

drop table 主表名 cascade constraints;
修改表

1、修改表名:rename to

rename 原表名 to 新表名;

2、修改列名:

alter table 表名 rename column 原字段名 to 新字段名;

3、修改类型:

alter table 表名 modify(字段 类型);

4、添加列:

alter table 表名 add 字段 类型;

5、删除列:

alter table 表名 drop column 字段
11 事务

事务是指作为单个逻辑工作单元执行的一组相关 *** 作

这些 *** 作要求全部完成或者全部不完成

使用事务是为了保证数据的安全有效

事务的特点(ACID)

1、原子性(Atomic):事务中的所有数据的修改,要么全部执行,要么全部不执行

2、一致性(Consistence):事务完成时,要使所有所有的数据都保持一致的状态

3、隔离性(Isolation):事务应该在另一个事务对数据的修改前或者修改后进行访问

4、持久性(Durability):保证事务对数据库的修改是持久有效的,即使发生系统故障,也不应该丢失

事务的隔离级别

Oracle 默认的隔离级别是 read committed

隔离级别脏读不可重复读幻读
Read uncommitted(读未提交)
Read committed(读已提交)
Repeatable read(可重复读)
Serialzable(串行读)

Oracle 支持上述四种隔离级别中的两种:read committed 和 serializable

除此之外,Oralce 中还定义Read only 和 Read write 隔离级别

Read only:事务中不能有任何修改数据库中数据的 *** 作语句,是 Serializable 的一个子集

Read write:它是默认设置,该选项表示在事务中可以有访问语句、修改语句,但不经常使用

丢失更新:两个事务同时存储, 一个存储 100 , 一个存储 200,最终可能至存储了 200 或者 100,那另一个的更新就没成功,即结果不为预想的 300

脏读:事务 T1 更新了一行数据,还没有提交所做的修改,T2 读取更新后的数据,T1回滚,T2 读取的数据无效,这种数据称为脏读数据

不可重复读:事务 T1 读取一行数据,T2 修改了 T1 刚刚读取的记录,T1 再次查询,发现与第一次读取的记录不相同,称为不可重复读

幻读:事务 T1 读取一条带 WHERE 条件的语句,返回结果集,T2 插入一条新纪录,恰好也是 T1 的WHERE 条件,T1 再次查询,结果集中又看到 T2 的记录,新纪录就叫做幻读

事务的开启

自动开启于 DML 之 insert delete update

事务的结束

成功:

正常执行完成的 DDL 语句:create、alter、drop

正常执行完 DCL 语句 GRANT、REVOKE

正常退出的 SQLPlus 或者 SQL Developer 等客户端

如果人工要使用隐式事务,SET AUTOCOMMIT ON (只针对一个连接)

手动提交 :使用 commit

失败:

rollback ,手动回滚

非法退出 意外的断电

注意:

rollback 只能对未提交的数据撤销,已经 Commit 的数据是无法撤销的,因为 commit 之后已经持久化到数据库中

12 DML

DML(Data Manipulation Language 数据 *** 控语言)用于 *** 作数据库对象中包含的数据

*** 作的单位是记录

主要语句:

语句作用使用场景
insert向数据表张插入一条记录注册
delete删除数据表中的一条或多条记录退出
update修改已存在数据表中的记录的内容修改密码
1 insert

添加记录时需要满足一下条件:

类型 长度 兼容:字段 兼容值

值满足约束:

主键 (唯一+非空)
非空(必填)
唯一(不重复 )
默认(没有填写使用默认值)
检查(满足条件)
外键(参考主表主键列的值)

个数必须相同:

指定列,个数顺序与列相同;
没有指定,个数与表结构的列个数和顺序相同 (null也得占位,没有默认值)

添加数据:

insert into 表名 values(和表结构顺序和个数和类型一致的数据可以手写也可以从别的表中获取的); 
insert into 表名(指定列名) values(和指定的列个数、顺序、类型一致的列数据)
2 delete

delete 可以删除指定部分记录,删除全部记录

记录上存在主外键关联时, 删除存在关联的主表的记录时,注意参考外键约束,约束强制不让删除先删除从表,再删除主表

删除数据:

1、删除全部数据

delete from 表名 where 1=1;

2、删除指定数据

delete from 表名 where 过滤条件;

3、主外键关联时,注意 参考约束, 约束强制不让删除

默认先删除从表,再删除主表

delete from 从表名 where 1=1; 
delete from 主表名 where 1=1; 
3 update

要求:

1、记录存在

2、类型 长度 兼容: 字段 兼容值

3、个数相同

更改数据:(从已有表中查询数据更改字段值)

update 表名 
set (字段列表) = (select 字段列表 from 原表 where 过滤原表记录) 
where 更新记录的条件手动更改字段值;
4 截断数据

truncate:截断所有的数据

如果截断的是主表,结构不能存在外键关联,截断数据同时从结构上检查

截断数据:

truncate table 从表名;

截断数据与删除数据区别 truncate 与delete 区别:

1、事务上:

truncate -->ddl ,不涉及事务,就不能回滚
delete -->dml ,涉及事务,可以回滚

2、truncate 截断所有的数据,delete 可以删除全部或者部分记录

3、结构上:

truncate从结构上检查是否存在主外键,如果存在,不让删除
delete 从记录上检查是否存在主外键,如果存在,按参考外键约束进行删除。

5 序列

使用工具|程序管理流水号,序列在创建时 没有与表关联 ,在 *** 作数据时与表关联

1 创建序列

用于主键自增

create sequence 序列名|字段名 start with 起始值 increment by 步进;
2 使用

在 *** 作数据 添加、更新

1)当前值:currval

2)下个值:nextval

select 序列名.nextval from dual;
select 序列名.currval from dual;
3 删除

删除序列

drop sequence 序列名;

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/991253.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存