用户与模式
- 用户:对数据库的访问,需要以适当用户身份通过验证,并具有相关权限来完成一系列动作。
- 模式(schema):是某个用户拥有所有对象的集合。具有创建对象权限并创建了对象的用户称为拥有某个模式。
- 注意:创建数据库对象(视图,表等)的任一用户都拥有一个以该用户名称开头的模式,且被视为模式用户。
新建用户
-- 新建一个叫user的用户,密码为password
CREATE USER user IDENTIFIED BY password;
修改用户密码
-- 将user的密码更改为password1
ALTER USER user IDENTIFIED BY password1;
锁定/解锁密码
-- 将user的密码锁定
ALTER USER user ACCOUNT LOCK;
-- 将user的密码解锁
ALTER USER user ACCOUNT UNLOCK
删除用户
DROP USER user CASCADE;
注:drop user xxx必须是这个用户下面没有任何对象,这样才可以使用这个命令,否则就会报错;如果用户下面有对象,就得用drop user xxx cascade来删除这个用户以及这个用户下的所有对象。
数据库权限
系统权限:允许用户执行特定的数据库动作,如创建表、创建索引、连接实例等(对用户而言)
- DBA:拥有全部特权,是系统最高权限,只有DBA才可以创建数据库结构。
- RESOURCE:拥有Resource权限的用户只可以创建实体,不可以创建数据库结构。
- CONNECT:拥有Connect权限的用户只可以登录Oracle,不可以创建实体,不可以创建数据库结构。
对象权限:允许用户操纵一些特定的对象,如读取视图,可更新某些列、执行存储过程等(是针对表或视图而言的)
给用户授权
GRANT CONNECT, RESOURCE TO user;
GRANT CONNECT, RESOURCE, DBA TO user;
-- 以下按英文字面意义理解即可
GRANT CREATE SESSION, CREATE TABLE TO user;
创建角色
-- 创建名为manager的角色
CREATE ROLE manager;
给角色授权
-- 给manager赋予创建表格和创建使徒的授权
GRANT CREATE TABLE, CREATE VIEW TO manager;
把角色授权给用户
-- 把manager这个角色赋予给用户user
GRANT manager TO user;
赋予用户查询表的权限
/*
假设我们拥有表 employees
下面语句赋予user查询employees的权限
*/
GRANT select ON employees TO user;
赋予用户和角色更新表指定字段的权限
/*
假设我们拥有表 employees
表中至少有salary和last_name两个字段
下面语句赋予user和manager更改employees中salary和last_name两个字段的权限
user:之前创建的用户
manager:之前创建的角色
*/
GRANT update (salary, last_name)
ON employees
TO user, manager;
赋予用户拥有赋予其他用户的权限
-- 差不多就是让别人也有给别人权限的能力
-- user可以给别人添加在表employees中选取和添加的能力
GRANT select, insert
ON employees
TO user
WITH GRANT OPTION;
赋予所有用户某些权限
-- 赋予所有用户查询表employees的权限
GRANT select ON employees TO PUBLIC;
收回权限
-- 从user里撤回从employees里查询和添加的权限
REVOKE select, insert
ON employees
FROM user;
表操作
建表
/*
新建表dept
字段deptno是长度为2的数字
字段dname是长度为14的字符
字段loc是长度为13的字符
字段create_date是日期
*/
create table dept (
deptno number(2)
,dname varchar2(14)
,loc varchar2(13)
,create_date date);
-- 查询表dept的属性,在这里,您会看到列名称,然后是列类型。
describe dept;
-- 下面是上面的缩写格式
desc dept;
-- 在dept中插入值
insert into dept values (1,'yunjisuan','beijing','28-8月 -22');
insert into dept values (2,'caiwubu','shanghai','27-8月 -22');
insert into dept values (3,'jishubu','shenzhen','26-8月 -22');
-- 用commit来告诉数据库上面的插入可以正式插入
commit;
-- 从dept里查询所有值
select * from dept;
使用字段默认值建表
-- 表dept2中create_date的默认值被设为了sysdate
create table dept2 (
deptno number(2)
,dname varchar2(14)
,loc varchar2(13)
,create_date date default sysdate);
-- 查询sysdate格式,方便输出
select sysdate from dual;
--通过字段名进行赋值,这样就不必按顺序赋值
-- 下面是给deptno, dname, loc分别赋值为1, 'yunjisuan', 'beijing'
insert into dept2(deptno,dname,loc) values (1,'yunjisuan','beijing');
insert into dept2(deptno,dname,loc) values (2,'caiwubu','shanghai');
insert into dept2(deptno,dname,loc) values (3,'jishubu','shenzhen');
commit;
select * from dept2;
约束
行级约束
也叫列级约束,只能应用于一列上。
行级约束包含在列定义中,直接跟在该列的其它定义之后 ,用空格分隔;不必指定列名。
表级约束
可以应用于一列上,也可以应用在一个表中的多个列上。
即:如果你创建的约束涉及到该表的多个属性列,则必须创建的是表级约束(必须定义在表级上);否则既可以定义在列级上也可以定义在表级上此时只是SQL语句格式不同而已。
与列定义相互独立,不包含在列定义中;与定义用‘,’分隔;必须指出要约束的列的名称。
注:因为在创建列级约束时,只需将创建列约束的语句添加到该字段(列)的定义子句后面;而在创建表级约束时,需要将创建表级约束的语句添加到各个字段(列)定义语句的后面,因为并不是每个定义的字段都要创建约束,所以必须指明需要创建的约束的列名。
主键约束
-- 主键约束
-- 行级约束
-- 下面给employee_id设置了名为emp_emp_id_pk的主键约束
-- 同时下面也是一个行级约束
create table employees_pk(
employee_id NUMBER(6) constraint emp_emp_id_pk primary key
,last_name VARCHAR2(25) NOT NULL
,email VARCHAR2(25)
,salary NUMBER(8,2)
,commission_pct NUMBER(8,2)
,hire_date DATE NOT NULL);
-- 表级约束
drop table employees_pk;
create table employees_pk(
employee_id NUMBER(6)
,last_name VARCHAR2(25) NOT NULL
,email VARCHAR2(25)
,salary NUMBER(8,2)
,commission_pct NUMBER(8,2)
,hire_date DATE NOT NULL
,CONSTRAINT emp_emp_id_pk PRIMARY KEY(employee_id));
-- 插入数据
insert into employees_pk values (100,'King','king@qq.com',3000,2,'29-8月 -22');
insert into employees_pk values (101,'Kochhar','Kochhar@qq.com',5000,12,'29-8月 -22');
insert into employees_pk values (102,'De Haan','Dehaan@qq.com',4200,21,'27-8月 -22');
insert into employees_pk values (103,'Hunold','Hunold@qq.com',3000,2,'29-8月 -22');
insert into employees_pk values (104,'Ernst','Ernst@qq.com',3500,12,'28-8月 -22');
insert into employees_pk values (105,'Lorentz','Lorentz@qq.com',3200,21,'29-8月 -22');
insert into employees_pk values (106,'Smith',NULL,3200,21,'29-8月 -22');
commit;
-- 主键不能为空值,插入数据失败
insert into employees_pk values (NULL,'Mith',NULL,'3200',21,'29-8月 -22');
唯一约束
-- 删除表employees_uq,防止有已经存在的表产生冲突
-- 不是必须要写
drop table employees_uq;
-- 这也是一个表级约束,给email添加了唯一约束
CREATE TABLE employees_uq(
employee_id NUMBER(6)
,last_name VARCHAR2(25) NOT NULL
,email VARCHAR2(25)
,salary NUMBER(8,2)
,commission_pct NUMBER(8,2)
,hire_date DATE NOT NULL
,CONSTRAINT emp_email_uk UNIQUE(email));
-- 插入数据
insert into employees_uq values (100,'King','king@qq.com',3000,2,'29-8月 -22');
insert into employees_uq values (101,'Kochhar','Kochhar@qq.com',5000,12,'29-8月 -22');
insert into employees_uq values (102,'De Haan','Dehaan@qq.com',4200,21,'27-8月 -22');
insert into employees_uq values (103,'Hunold','Hunold@qq.com',3000,2,'29-8月 -22');
insert into employees_uq values (104,'Ernst','Ernst@qq.com',3500,12,'28-8月 -22');
insert into employees_uq values (105,'Lorentz','Lorentz@qq.com',3200,21,'29-8月 -22');
insert into employees_uq values (106,'Smith',NULL,3200,21,'29-8月 -22');
commit;
-- 违反唯一约束,插入数据失败(email和105号的那个冲突了)
insert into employees values (107,'Jisth','Lorentz@qq.com','3200',21,'29-8月 -22');
外键约束
create table t_customer(
id number primary key
,name varchar2(200) not null
);
insert into t_customer values (10,'Fay');
insert into t_customer values (11,'Whalen');
insert into t_customer values (12,'Higgins');
insert into t_customer values (13,'Ciets');
commit;
-- 设置表t_customer的id为t_order中customer_id的外键
-- 如果customer_id的值不在t_customer的id中就会报错
create table t_order(
id number primary key
,content varchar2(200) not null
,customer_id number
,foreign key(customer_id) references t_customer(id)
);
insert into t_order values (1,'dingdan01',10);
insert into t_order values (2,'dingdan02',10);
insert into t_order values (3,'dingdan03',12);
insert into t_order values (4,'dingdan04',12);
commit;
-- 违反外键约束,插入数据失败
insert into t_order values (5,'dingdan05',15);
-- 删除被外键引用的表
-- 方法1
drop table t_customer; -- 直接删除失败,因为表中字段为其他表的外键
drop table t_order; -- 先删除引用过t_customer的表
drop table t_customer; -- 删除成功
-- 方法2
drop table t_customer cascade constraints; -- 自动连有外键约束的一起删除
检查约束
-- 给salary添加了约束,让salary必须大于0才能插入
CREATE TABLE employees_ck(
employee_id NUMBER(6)
,last_name VARCHAR2(25) NOT NULL
,email VARCHAR2(25)
,salary NUMBER(8,2) CONSTRAINT emp_salary_min CHECK (salary > 0)
,commission_pct NUMBER(8,2)
,hire_date DATE NOT NULL);
insert into employees_ck values (100,'King','king@qq.com',3000,2,'29-8月 -22');
insert into employees_ck values (101,'Kochhar','Kochhar@qq.com',5000,12,'29-8月 -22');
insert into employees_ck values (102,'De Haan','Dehaan@qq.com',4200,21,'27-8月 -22');
insert into employees_ck values (103,'Hunold','Hunold@qq.com',3000,2,'29-8月 -22');
insert into employees_ck values (104,'Ernst','Ernst@qq.com',3500,12,'28-8月 -22');
insert into employees_ck values (105,'Lorentz','Lorentz@qq.com',3200,21,'29-8月 -22');
insert into employees_ck values (106,'Smith',NULL,3200,21,'29-8月 -22');
commit;
-- 违反检查约束条件,插入数据失败
insert into employees_ck values (107,'Jisth','Lorentz@qq.com',0,21,'29-8月 -22');
联合约束和非空约束
- 联合约束必须使用表级约束来声明
- 非空约束(not null)必须使用行级约束
--例如联合唯一约束:
create table student(
id number primary key,
class varchar2(50) not null,
name varchar2(50) not null,
unique(class, name)
);
增加字段
-- 新建表t_user
create table t_user(
id number constraint user_id_pk primary key,
name varchar2(100),
salary number
);
-- 查看表属性
desc t_user;
-- 给t_user添加数据类型为date的birthday字段
alter table t_user add birthday date;
desc t_user;
删除字段
alter table t_user drop column birthday;
desc t_user;
给表添加约束
-- 给t_user的name添加唯一约束,约束名为user_name_uq
alter table t_user add constraint user_name_uq unique(name);
删除表中的约束
-- 给t_user删除名为user_name_uq的约束
alter table t_user drop constraint user_name_uq;
修改表名
-- 把t_user重命名为mytest
rename t_user to mytest;
-- 把mytest重命名为t_user
rename mytest to t_user;
修改字段长度
alter table t_user modify name varchar2(200);
desc t_user;
删除表(表结构和数据都被删除)
drop table t_user;
-- 报错,因为表没了
desc t_user;
清空表(表结构还在,数据被删除)
truncate table dept;
-- 正常显示
desc dept;
-- 空
select * from dept;
创建索引
CREATE TABLE NEW_EMP
(employee_id NUMBER(6) PRIMARY KEY
,first_name VARCHAR2(20)
,last_name VARCHAR2(25)
);
CREATE INDEX idx_emp_id_last_name ON NEW_EMP(employee_id, last_name);
删除索引
DROP INDEX idx_emp_id_last_name;
查看索引信息
SELECT * FROM USER_INDEXES WHERE TABLE_NAME = 'NEW_EMP';
DML
-- 先新建个表
create table employees(
employee_id NUMBER(6) constraint emp_emp_id_pk primary key
,last_name VARCHAR2(25) NOT NULL
,email VARCHAR2(25)
,salary NUMBER(8,2)
,commission_pct NUMBER(8,2)
,hire_date DATE NOT NULL);
查询数据
select * from employees;
查询指定字段
-- 只从employees查询last_name和salary两列
select last_name ,salary from employees;
新增数据
-- 新增数据
insert into employees values (200,'King','king2@qq.com',3000,2,TO_DATE('8月 03, 2022', 'MON DD, YYYY'));
insert into employees values (201,'Kochhar','Kochhar2@qq.com',5000,12,'29-8月 -22');
insert into employees values (202,'De Haan','Dehaan2@qq.com',4200,21,'27-8月 -22');
insert into employees values (203,'Hunold','Hunold2@qq.com',3000,2,'29-8月 -22');
insert into employees values (204,'Ernst','Ernst2@qq.com',3500,12,'28-8月 -22');
insert into employees values (205,'Lorentz','Lorentz3@qq.com',3200,NULL,'29-8月 -22');
insert into employees values (206,'Smith',NULL,3200,21,'29-8月 -22');
insert into employees values (207,'Smith','',3200,21,TO_DATE('8月 03, 2022', 'MON DD, YYYY'));
commit;
select * from employees;
修改数据
-- 让所有的 salary都减少200
update employees set salary=salary-200;
-- 查询employee_id为200的行
select * from employees where employee_id=200;
-- 设置employee_id为200行中salary数值减少200
update employees set salary=salary-200 where employee_id=200;
-- 查询employee_id为200的行
select * from employees where employee_id=200;
删除数据
select * from employees where salary>4000;
-- 删除salary大于4000的所有行
delete from employees where salary>4000;
select * from employees;
-- 清空表,等同于truncate
delete from employees;
运算操作
-- 数字运算
select employee_id,last_name ,salary, 12*salary+100 from employees;
select employee_id,last_name ,salary, 12*(salary+100) from employees;
-- 对于包含空值的运算操作,结果也为空值
SELECT last_name, 12*salary*commission_pct FROM employees;
-- 拼接字段值,字段别名
SELECT last_name ||' salary is '||salary AS "Employee Salary" FROM employees;
-- 比较运算符
select * from employees where salary>3000;
select * from employees where last_name='Kochhar';
SELECT last_name, salary FROM employees WHERE salary BETWEEN 2500 AND 3500 ;
-- 只选择employee_id在100、101和201中的
SELECT employee_id, last_name, salary
FROM employees
WHERE employee_id IN (100, 101, 201) ;
/*使用Like操作进行模式匹配
_代表一个字符
%代表0或者多个字符
*/
-- 查询首字母为大写S的名字
SELECT *
FROM employees
WHERE last_name LIKE 'S%' ;
-- 查询第二个字母为o的名字
SELECT *
FROM employees
WHERE last_name LIKE '_o%' ;
-- 查询空值
SELECT last_name, commission_pct
FROM employees
WHERE commission_pct IS NULL ;
-- 逻辑操作符
SELECT employee_id, last_name, salary
FROM employees
WHERE salary >= 5000
AND last_name LIKE '%ch%' ;
-- 排序
-- 正序
SELECT last_name, employee_id, hire_date,salary
FROM employees
ORDER BY salary ;
-- 倒序
SELECT last_name, employee_id, hire_date,salary
FROM employees
ORDER BY salary desc ;
-- 以查询字段序号排序
SELECT last_name, employee_id, hire_date,salary
FROM employees
ORDER BY 4;
-- 多字段排序
SELECT last_name, employee_id, hire_date,salary
FROM employees
ORDER BY last_name,salary ;
-- 查询所有结果中前五行的信息
SELECT employee_id, last_name
FROM employees
ORDER BY employee_id
FETCH FIRST 5 ROWS ONLY;
-- 查询所有结果中,先跳过前五行后,展示后面的5条数据
SELECT employee_id, last_name
FROM employees
ORDER BY employee_id
OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY;
-- 组函数
-- 查询8月29日的平均工资,最大工资,最小工资,工资总和
SELECT AVG(salary), MAX(salary),
MIN(salary), SUM(salary)
FROM employees
WHERE hire_date ='29-8月 -22';
-- 查看表中的所有记录数
SELECT COUNT(*)
FROM employees;
SELECT COUNT(*)
FROM employees
WHERE salary>3000;
-- 查询不为null的值的数据记录数
SELECT COUNT(commission_pct)
FROM employees
WHERE commission_pct is not null ;
-- 使用DSITINCT关键字去重
SELECT COUNT(DISTINCT last_name)
FROM employees;
-- 分组
SELECT last_name, AVG(salary)
FROM employees
GROUP BY last_name ;
-- 分组+排序
SELECT employee_id, last_name, SUM(salary)
FROM employees
WHERE employee_id > 200
GROUP BY employee_id, last_name
ORDER BY employee_id;
-- 错误示例
SELECT last_name, AVG(salary)
FROM employees;
SELECT employee_id, last_name, SUM(salary)
FROM employees
GROUP BY employee_id;
-- 使用Having语法对分组后的显示结果进行筛选
SELECT last_name, MAX(salary)
FROM employees
GROUP BY last_name
HAVING MAX(salary)> 3000 ;
-- 表连接
select * from employees;
select * from employees_pk;
-- 全连接:FULL JOIN 它表示返回两个表全部记录,表示两个表的所有记录
select *
from employees em1
full join employees_pk em2
on em1.employee_id=em2.employee_id;
-- 内连接:INNER JOIN 它表示返回两个表或记录集连接字段的匹配记录,表示两个表中相互包含的部分
select *
from employees em1
inner join employees_pk em2
on em1.employee_id=em2.employee_id;
-- 左连接:左外连接又叫左连接,意思是包含左边表所有记录,右边所有的匹配的记录,如果没有则用空补齐.换句话说就是,列出左边表全部的,及右边表符合条件的,不符合条件的以空值代替
select *
from employees em1
left join employees_pk em2
on em1.employee_id=em2.employee_id;
-- 右连接
select *
from employees em1
right join employees_pk em2
on em1.employee_id=em2.employee_id;