从零开始学Oracle--自学笔记

1. 啥是数据库

其实Oracle是一个包括数据库软件和存储硬盘的概念。
一般我们画数据库都是画成下面这样,这个其实是个硬盘的重叠盘片的模样,就是来存储数据的意思。
在这里插入图片描述
Oracle提供的不只是装在电脑上的软件,还有服务器,以及装在服务器上的存储空间。
存储空间里保存所有Oracle的表,通过SQL和服务器交互,或许是删表,建表,建用户等等。
当然现在都是用Apex了,就是不管你这个Oracle装在哪个服务器上,也许在北京,也许在东京。我只买个云服务。那我通过Apex网页直接执行SQL语句。
https://apex.oracle.com/en/learn/getting-started
在这里插入图片描述

2. 单行操作, 字符串功能

select from where
<

=
!=
<>
<=

=

ORDER BY
ASC
DESC

upper()
lower()
sum()
concat()
length()

dual table
Initcap()
substr()
lpad(A,5,’%’)
rpad()
ltrim(A,‘L’)
rtrim(B,0)

3. 单行功能,数字和日期功能

round(100.234,2)= 100.23
round (100.237,2) = 100.24
round(100.8) = 101
round(100.55) = 101

select round(100.234,2) from dual

TRUNC(100.887,2) = 100.88
trunc(100.345) = 100 忽略小数位

select sysdate from dual
select sysdate from dual
select systimestamp from dual
select add_months('02/18/2022',12) from dual
select add_months(sysdate,-2) from dual
select round(months_between(sysdate,'12/09/2020') )from dual
select trunc(systimestamp) from dual

select trunc(systimestamp,'YEAR') from dual (给出当年的一月一日)
select trunc(hiredate,'month') from emp (给出每月1号)
select trunc(hiredate,'day') from emp (给出具体日期)
select trunc(hiredate,'day') from emp where trunc(hiredate,'YEAR') = '01/01/1982'  (注意这个日期的格式,不是只有YEAR,而是当前年的一月一日)

sysdate
systimestamp
add_months
months_between

TO_CHAR(sysdate,‘Month DD,YYYY’)
Feb 18, 2022

TO_CHAR(123,’$999.99’)
$123.00

把日期或数字转换成文本
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
TO_DATE(‘str’,‘fmt’)
在这里插入图片描述
在这里插入图片描述

LAST_DAY(d) 当前月的最后一天
在这里插入图片描述

NEXT_DAY(d, c) 从d开始的下一个星期c。
就算当前星期五,下一个星期五也只能是7天后。next要往下数,不会是像between一样的包含。
在这里插入图片描述
NVL(a,0)
No value: null
在这里插入图片描述
很多的公式的input的和output的格式要是一样的,比如那个DDth,ddth是和跟着日期的格式来的。如果前面大写那就是19TH,不管th是怎么写的。这个还是挺有意思的。
也就是很多时候,格式默认是跟着输入值来的。默认输入值已经给你定义好了格式了。

在这里插入图片描述
在这里插入图片描述

4. 多行功能,group

在这里插入图片描述
多行输入,只有一行输出。
就是基于多行输入.
但是如果先给按group做分组,那么就会像where一样的限制条件。先限制,再计算。
在这里插入图片描述
在这里插入图片描述
懂得group 是个很重要的事情。
在这里插入图片描述
where里面的条件先行,到group里面是group的条件先行,但是有一点就是在group里面不能把function用在where条件里。
就是说一些count,max,min,sum ,avg的功能不能和group里的where一起用。

那么这里就要记住了:
是Having来用了,这个看似和where是一个意思,都是用来过滤。
在这里插入图片描述
比如这种在where条件里用min就不行。
在这里插入图片描述
只能用单行的功能。
而且由于是group by…having的语句。你select出来的也只能是group的一些功能,或者是你group by的列。考虑到这个功能是先按照group by的列来分组,所以其他的列在select里面就不好展示了,当然按照分好的组进行的组计算还是可以的。但是都是基于数字进行计算。如果要展示属性列,还是有些困难的。group无法实现啊。
在这里插入图片描述
当然having是必须得在group之后的。只有做了分组之后,才能再在组里进行再过滤。
在此结构之下,最后一个是order by

order by从功能上来看,只是排版。所以它是最后一个功能,可选可不选。
从下面语句来看,group by的优先级最高,紧跟着是having。这些过滤完了之后,才是where。然后进行select的操作。
在这里插入图片描述
对group的更深层理解:
当你去group两个列,其实是把这两个列来组合分组,这时候,当两列的值组合起来能多行合并成一组就合并成一组,如果不能,那就是一行一组了。
在这里插入图片描述

总结起来,group by有自己特定的格式:

select col1,col2,col3,group_function(aggregate_expression)
from tables
[where conditions]
group by col1,col2,col3
[having conditions]
[order by conditions]

这里要注意的点就是,你select的列,必须是group by用到的,否则不给你展示。
当然不是所有group by的列都得在select里面。

5. 内嵌select,子查询

在这里插入图片描述
可以内嵌在where语句里。
也可以内嵌在select语句里。
在这里插入图片描述
也就是说我可以select的结果集从一个已经被select过的地方出来。
或者我的条件是基于已经被选过的条件。
可以是一个from的table,也可以是一个where之后的。

下面这个就是把两个有关联的表的结果给整合起来了。
通过内嵌的select语句作为选择的条件。
当然select之后也可以嵌套。
总结起来就是括号内嵌套的语句的优先级最高。
在这里插入图片描述
但是你要搞清楚内嵌的select语句返回的结果集是什么,是单条语句还是很多条。
那么你的where语句就得相应的更改成适用于单条的还是多条的。
在这里插入图片描述
要注意的是你select的时候,都是一行一行的展示,如果你包入一个结果集,那就是不行的了。只能你select里面的是一个单值。
那么这样的话,每一条你的select出来的都是这个相同的单值。
在这里插入图片描述

6. 多表查询和join

使用关联字段。
在这里插入图片描述
在这里插入图片描述
需要注意的是,如果有表字段是同时在两个表中的。那么要指明你要select展示的是谁的表。要不然人家不知道。
而且如果你给了别名,那么就要把别名用上。
在这里插入图片描述
比如下面这样选出来的结果集有两个deptno的。那就不知道到底是哪个。
在这里插入图片描述
这些简单的技能,当能够整合起来,就是一个能解决复杂问题的技能了。所以,大神来源于简单技能的叠加。
下面这个可以把结果集当成from的一部分,并且分配一个别名。
在这里插入图片描述
以下的两个功能就是一样的,也就是把过滤值放到from的结果集里,先给它选出来。所以有时候,优先级一样的功能可以在不同的地方实现。
在这里插入图片描述
在这里插入图片描述

7.内连和外连

关于表的连接实际上下面两种都一样。
但是为了清楚的挂钩外连接,所以用inner join…on 更能接轨。
也就是说实现一种功能的方法有多重多样。咱可以选择一个更标准的常用的写法。
在这里插入图片描述
那么接下来,如果我们用右连接:
结果集就会把右表的所有行都展示出来了。
当然这些展示行,取决于你表的位置。放在左还是右。
在这里插入图片描述
比如这个和上面一样的意思,结果是一样的,就是把左表换了。左连接,把左表的所有行展示出来。右连接把右表的所有行展示出来。然后关联展示左表能匹配上的行。
在这里插入图片描述
所以也就是说左连接,右连接其实没什么相关的。
它主要还是和表的位置有关。

除此以外,还有outer join。那么outer join 其实是加在left join 或 right join的中间。
但意思是一样的。左连接,右连接都是外连接。是区别于inner join的。不管你加不加outer,反正都不是inner join.
在这里插入图片描述
那么在Oracle里面其实还有一种格式:
以下其实是用where限定的内连接。但是如果要把这种格式的内连接改为外连接,那么就用下面的方式:
在这里插入图片描述
在左表后面加(+)就是说我要在emp右面关联dept表。
但是这个比较少用了。只适用于Oracle。
在这里插入图片描述

除了左外连接,右外连接,还有个全连接,就是你左右有啥,我都给你拉过来。如果右表没有的列,我给成null,左表没有的列,我也给成null。
在这里插入图片描述
在连接里面也是可以用嵌套select的。
在这里插入图片描述
当然还可以这样:
在这里插入图片描述

8. exist(可以和子查询结合)

exist是在subquery里面使用的。
但是这种方式特别不高效。
因为这个循环嵌套,每一行外面的query都要去跑一遍subquery。
在这里插入图片描述
简言之,exists就是为subquery而设计的。
对于where后的限制条件,外部的每一行都要满足。所以,就是要对每一行做限定要满足where的条件。所以很低效。

那么它适用的场景为关联子查询。其实就是把外部的表关联用在子查询里面。那么对于外部的每一行查询启动时,也会相应的启动内部子查询针对于外部该行的查询。所以不会低效。
在这里插入图片描述

这里有个扩展的例子没有用到exist,但是是子查询:
理解起来就是,子查询可以用到外部查询,但是外部查询无法干预到子查询。
当我的嵌套子查询有条件约束,我可以去拿外面的表的列作为条件。

其实再理解起来,这个嵌套子查询,也就有点像自关联啊。
在这里插入图片描述
在这里插入图片描述

9. 自连接(要多看)

一个自连接差点把我给绕晕,我觉得是由于我不经常接触这些的。头脑链路还没通。念头还没通达。
在这里插入图片描述
自连接是为了获取自己表中的层级数据或者去比较表内数据。自己的表里有两列值是相关联的。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果我想找雇佣日期相同的员工:
这时候要知道,我去关联自己。那么都是按照行去关联的。但是雇佣日期是在列上。
我如果想取雇佣日期相同。直接关联两个表,是只能取出完全相同的自己的行。我其实需要的是把行错开,也就是比较不同的雇员的雇佣日期。
在这里插入图片描述
实际上我们一定要把行错开。这里选empno > 也是有一点道理的。选<>性能要差点。
在这里插入图片描述
选<>会执行两遍啊。
在这里插入图片描述
如果不执行任何的join,那么数据库会直接把A表的每一行和所有B表的每一行强硬关联:没有任何道理的进行重复M*N条出来。
在这里插入图片描述
这种在Oracle里也叫cross join:
在这里插入图片描述
natural join:A表外键和B表主键列名一样的。就这列。那么我可以指明用inner join,或者反正你就这列一样。我知道了,你就用natural join。交给Oracle吧。
在这里插入图片描述
如果列名不一样,用一个using(col1, col2)
在这里插入图片描述

10. EQUI join&NON-EQUI join

equijoin啥意思呢?就是它这个有个=号。
实际上就是下面这个内连接,同时因为用了= 所以它也是EQUIJOIN。
在这里插入图片描述这个就是不等连接。join的条件是non equijoin。不等连接。
在这里插入图片描述

11. CASE

在这里插入图片描述
case 的几种写法:

SELECT table_name,
CASE owner
  WHEN 'SYS' THEN 'The owner is SYS'
  WHEN 'SYSTEM' THEN 'The owner is SYSTEM'
  ELSE 'The owner is another value'
END
FROM all_tables;
SELECT table_name,
CASE
  WHEN owner='SYS' THEN 'The owner is SYS'
  WHEN owner='SYSTEM' THEN 'The owner is SYSTEM'
  ELSE 'The owner is another value'
END
FROM all_tables;

当然,实际上case when end就是一个If elsif else endif.

IF owner = 'SYS' THEN
   result := 'The owner is SYS';

ELSIF owner = 'SYSTEM' THEN
   result := 'The owner is SYSTEM'';

ELSE
   result := 'The owner is another value';

END IF;
SELECT
CASE
  WHEN a < b THEN 'hello'
  WHEN d < e THEN 'goodbye'
END
FROM suppliers;

可以在case里面多重选择。

SELECT supplier_id,
CASE
  WHEN supplier_name = 'IBM' and supplier_type = 'Hardware' THEN 'North office'
  WHEN supplier_name = 'IBM' and supplier_type = 'Software' THEN 'South office'
END
FROM suppliers;

在这里插入图片描述

12. 分析

在这里插入图片描述
在这里插入图片描述

12.1 over/ partition by

这个语法的用处是:
开启一个窗,over()窗给谁开?
其实就是跟上面的一样,省了一个子查询。用了partition这个关键字。
分区,也就是分组的意思。当你自己去写的时候。就能感觉到,其实意思就是按照表的哪个字段来分组计算。

这个语法就是比上面的子查询要简单,不用写那么长了。

在这里插入图片描述
在这里插入图片描述
不止局限于一行。多看看怎么用。这样就不用用很多子查询。
在这里插入图片描述
以下这个功能还是很有意思的。用brick_id来做排序。那么显然,会一个一个排下去。
按颜色分组。那么就会实现下面这种按颜色每个brick_id按行叠加的效果。也就是下一行的总计值是它本行和上行基于分区的叠加值。
在这里插入图片描述
实际上这条语句在执行的过程中,顺序是先partition分组。按什么分组,然后再基于brick_id来排序。默认是倒序。
最后在去按颜色的分组和ID的排序去计算sum。
那么这个sum计算的是当前行和接下来行的总和。

这个在用来计算分组按行依次累加还是很有用的。

这是个固定的语法。
如果你在over里面用group by就不对了。
人家只认partition by:
在这里插入图片描述
再回顾理解:
partition只是一个分区,将区的sum起来。
在这里插入图片描述
当我在区后来加了一个order by。也就是这个表内的分区,它虽然还是一个整的,但在整的内部,我又把它划分为不同的有关系区。
但是我基于partition by的分区的sum计算是不会变的。
当我order by brick_id,因为brick_id是完全不同的,所以,partition的大分区会继续划分为不同的小分区。但总值计算是不同的。只不过,累加值是按行号来的,就比较好理解。

在这里插入图片描述
当我把分区之后的order by换成colour。
那么总值还是一样的。还是按照shape来分区的总值,但是按行累加值,就变成基于colour来计算了。
这里因为colour的第二行red和第三行red是一样的。所以它在order by colour这里没办法区分我弄哪个colour。索性把所有的red都给先sum起来了,结果就是第二行和第三行的累加值,实际上是并列的了,没办法按照order by来排序累加的。那么就直接给累加的总值。咱俩都累加起来。

在这里插入图片描述
在这里插入图片描述

12.2 over/ order by

这里再去理解一下order by。
从上面的例子能看出,order by就是为了向上叠加。
在这里插入图片描述
为什么会是这样呢?
这个over后面的order by怎么就变成了这个功能呢?
要完全理解这个over后面的order by你就得知道:

首先它是按order by后面来排序的。然后这个over 的sum计算,计算的是brick_id小于或等于当前行的sum(weight).
下面这个例子则是计算了按行的平均weight值。
在这里插入图片描述
如果我按照colour来,那怎么理解呢?
前两个colour是一样的。我会一起计算。
第三个colour那就是总值(2+1+1)/3
第四到第六个又是一样的。那就是总值(2+1+1+3+2+1)/6
在这里插入图片描述
至此再来理解,其实上Oracle的这个语法,默认省略了一段:
range between unbounded preceding and current row
意思是去执行order by排序的前面公式count(*)或者sum(weight)的时候,默认执行的是,你order by的对象值的当前列和所有小于当前列的前面列的总值。

下面例子,改掉了默认的range between 为rows between:第一个执行的是count(*)是基于weight先来排序。那就是1在前,2在后。在weight的基础上再按照brick_id来排。所以brick_id排成了1,3,6,2,4,5.
当我计算count的时候,都是1,不管你weight值多少。我计算的这列。
当我去计算sum(weight)的时候。那就是按weight来排序算了。第一行是计算第一个weight第一个brick_id的是1, 第二行是1+1,第三行是1+1+1.
第四行是1+1+1+2 依次类推。
在这里插入图片描述
那么再来理解一下:
因为上面同时按照了brick_id来默认计算的。它是可以有个从上到下的范围顺序的。可以取到当前行和所有小于它的行的总值。
因为brick_id是有个顺序值的。但是一旦order by 的没有个顺序值,有了相同值。就像之前的列子:

当无法判别相同weight值的先后顺序的时候。我就会把它归为一起计算。也就是我不能按照行来累加计算了。实际上这等于是个按weight的值的分组了。我把相同weight值的都看做一行了。
在这里插入图片描述
为了避免,可以加上rows between.(默认是range between,但是这个是可以更改的)
加上rows between就相当于加了每行的索引。
这个不是默认的,要加的话得自己加,结果就是像order by一个有顺序的列值一样。
你要是用默认的,就像上面那个是个range between,那这个范围,它就默认值相同的是一个范围。那就会把值都归为一行。
在这里插入图片描述
这个unbounded的意思是不受约束的。
rows between unbounded preceding and current row.
那么其实这个unbounded可以被更改。可以只是统计当前行和之前的一行。
在这里插入图片描述
不仅能是之前,还能是之后。还是挺有意思的。
在这里插入图片描述

12.3 over 的过滤

看了这么多,over都是对于聚集计算有用的,比如说max() min() count() sum() average()

那么假设我要对over的结果集做过滤值呢?
over里面的partition实际上是和分组差不多的意思。
我们一般对分组进行过滤,都是用的having,不能用where count(*)之类的。
在这里插入图片描述
这里有个致命点就是,你用了group by。 你就只能看到这个group by的字段了,还有计算值。其他的字段你是看不到了的。

对分组的一个延伸,就是可以用分区。
这样我也可以看到聚集计算值。
在这里插入图片描述
因为having是跟着group by的。那我现在这个要过滤估计用不了having。
where应该可以用:
如果这样用,就回到了原始的话题,聚集的公式不能用在where里。为啥呢?因为数据库的处理逻辑一直是:先处理where的条件,然后再执行其他的。
显然如果我先处理了where的,那group或者partition的先决条件就完全没有考虑,等于是白处理了,所以这样的语句会报错。
在这里插入图片描述
那如果这样呢?还是报一样的错。where后面就不能用聚集公式。那咋办?
在这里插入图片描述
既然已经有了count(*)的值了,就用嵌套来对数据进行过滤吧:
在这里插入图片描述
在这里插入图片描述

12.4 row()/前,后值,开始,结束值。

在这里插入图片描述
在这里插入图片描述
由于last_value() 这个会停止于当前行,所以得加一句 range between current row and unbounded following
在这里插入图片描述
在这里插入图片描述

13. 创建,选择,更新表

先说下表的主键和外键。
主键必须唯一且不为空,能够独一无二表明一行。
主键可以是一列或者多列组合。

创建主键

My SQL:

create table persons(
  ID int not null,
  lastname varchar(255) not null,
  firstname varchar(255),
  age int,
  primary key(ID)
  );

SQL Server/Oracle/MS Access:

create table persons(
  ID int not null primary key,
  lastname varchar(255) not null,
  firstname varchar(255),
  age int,
  );

MySQL / SQL Server / Oracle / MS Access:定义主键限制(两列作为主键):

CREATE TABLE Persons (
    ID int NOT NULL,
    LastName varchar(255) NOT NULL,
    FirstName varchar(255),
    Age int,
    constraint pk_person primary key (id,lastname)
    );

在这里插入图片描述

添加主键

MySQL / SQL Server / Oracle / MS Access:
前提条件:创建表的时候已经指定该列为not null.

alter table persons
add primary key(id);
alter table persons
add constraint pk_person primary key(id,lastname);
删除主键

MySQL

alter table persons
drop primary key;

SQL Server/Oracle/MS Access:

alter table persons
drop constraint pk_person;
创建外键

表与表之间有个相同的列,那这两个表可以关联起来。外键限制可以防止这个关联被破坏。
一个表的外键,是另外一个表的主键。
那么这个有外键的表叫子表,有主键的表叫父表。
在这里插入图片描述
personID是person表的主键,是orders表的外键。
外键限制就是像参照完整性。如果你要在orders里插入personID的值,为了防止你乱写,我给一个外键限制,那么你这边插入的值必须是在我person表里有的personID值。也就是说你这个儿子要写什么,必须从我父亲那边已经有的来写。不能乱写。

创建外键

MySQL

CREATE TABLE Orders (
    OrderID int NOT NULL,
    OrderNumber int NOT NULL,
    PersonID int,
    PRIMARY KEY (OrderID),
    FOREIGN KEY (PersonID) REFERENCES Persons(PersonID)
);

SQL Server / Oracle / MS Access:

create table orders(
orderid int not null primary key,
ordernumber int not null,
personid int foreign key references persons(personid)
);

MySQL / SQL Server / Oracle / MS Access:

CREATE TABLE Orders (
    OrderID int NOT NULL,
    OrderNumber int NOT NULL,
    PersonID int,
    PRIMARY KEY (OrderID),
    CONSTRAINT FK_PersonOrder FOREIGN KEY (PersonID)
    REFERENCES Persons(PersonID)
)

MySQL / SQL Server / Oracle / MS Access:

ALTER TABLE Orders
ADD CONSTRAINT FK_PersonOrder
FOREIGN KEY (PersonID) REFERENCES Persons(PersonID);

MySQL:

ALTER TABLE Orders
DROP FOREIGN KEY FK_PersonOrder;

SQL Server / Oracle / MS Access:

ALTER TABLE Orders
DROP CONSTRAINT FK_PersonOrder;

13.1 create table, insert into … values

在这里插入图片描述

13.2 insert all into… values…select * from dual

这样直接插入多条不行。要加个select语句。
在这里插入图片描述
加个select是Oracle的特色。
在这里插入图片描述

13.3 constraint … primary key

直接插入的话,因为没建主键,是不行的。得再建主键。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
insert all语句可以向不同的表里插入数据,还可以从现有的其他表插入。
但是插入的是现有表的数据的时候,你得告诉数据库这数据从哪里来的。你得有个select。
在这里插入图片描述
这里插入的是把emp的所有行都插入表里面。INSERT ALL INTO

VALUES在这里插入图片描述
还可以插入条件的:
在这里插入图片描述

13.4 alter table … modify …/rename column … to …

修改表的字段类型。完了之后可以describe看表列类型。
在这里插入图片描述

13.5 delete from … where …

如果有表行不满足了,要先删除:
在这里插入图片描述
修改多行的数据类型也是可以的。
在这里插入图片描述
但是如果还要修改字段名,那么就要另起一行alter table了。
不能跟在前面一段下面。
在这里插入图片描述

13.6 create table … as select …from …

借用其他表的框架结构来。不用自己去建字段了。
在这里插入图片描述

13.7 alter table … add…

由上,当我们从别的表借框架和内容新建一个新表的时候,如果还要给这个新表加列。那么这列数据还要给设置成not null.
就加不上去。因为你说不能空,但是原表已经有很多行了,只要你加了这列,那这列必然为空。
在这里插入图片描述
只能不做限制给加上去。
在这里插入图片描述

13.8 insert/update

当我们insert的时候,是一行一行的去insert。
但是上面我新加了一列,怎么去填数?

UPDATE yourtable SET<column> = <value> WHERE <some criteria>

等用update 填充完了,就可以把刚才的列modify成not null了。
在这里插入图片描述

13.9 merge

这是一个很有意思的功能了。
因为如果我们create table基于select别的表。那么就是说把别人的都直接拿过来。
但是如果现在有两张表,需要合并怎么弄。别的表的字段我可能也有了,或者哪些字段基于条件我要,哪些我不要。

先来创建一张现有表,填充字段。由于用了BEGIN 和end,所以显示1 rows inserted. 系统认为是一条,实际上所有都 插入了。
在这里插入图片描述
再来创建一张表。
在这里插入图片描述
现在如果我想把new表合并进existing表。但是要注意新表有些已经重复在exist表里面了。这个功能只在Oracle里面有。
在这里插入图片描述
里面的条件可以更改。
在这里插入图片描述

13.10 sequence

在这里插入图片描述
在这里插入图片描述
一个sequence就是一个序列,你可以自己设定序列开始值,结束值,间隔值。
还可以给个cache就是运行的时候更快点但是没啥影响。
使用的话,就是你想在什么位置进行数据的修改:
在这里插入图片描述

13.11 delete,truncate,drop

当我完全删除一个表,它告诉我违反完整性限制。这是因为这个表有child record.
也就是说它的主键被它的child用作外键了,而且设置了参照限制。
在这里插入图片描述
这个外键名是EMP_DEPT_FK
那么去EMP的限制里面看,能看到这个EMP的外键限制是限制到了DEPT的DEPTNO这列。所以一旦DEPTNO的值被child表用到了,而你想要删除它,那就不行了,因为有这么个外键限制了。

在这里插入图片描述
在这里插入图片描述
那我们先来删除这个外键,再去删除表。删除了之后,那么在emp里面可以填入任何值了。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
delete只是删除表内容,和truncate一样,但是表结构,主外键还在的,但是如果drop了那就是整个表结构都没了。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

13.12 index

当你去翻字典,没有按ABCD划分的目录,是很难找到你要找的单词的。
当你的表是几十万行,那你没有索引,也是很难找到你要找的那行的。
索引至于数据库表,就是一个对象,像主键,外键,限制啥的。你表巨大的时候,要找一个列或者几列,就是表里经常被访问的对象作为索引,提升查询表的效率。
那么怎么建索引呢?
在这里插入图片描述
当我去查询表的时候,比如下面这个,那么where的条件是ename。这是Oracle去跑的时候说,哦,我有个index是建在ename上的啊,我不用去查整张表了,我只要去查ename这一列就好了,找到对应的ename然后再取出值来。因为我有了这个索引,所以会快很多。
在这里插入图片描述
当然还能是组合index,当我的查询条件是多个,那这样的效率会更高。因为不用一行一行的完全去遍历了。我已经建了一个index把这些的组合键拿出来了,我去这个index找,这个index很小的,会很快。然后再直接给你在数据库表的位置。
在这里插入图片描述
但是有一点,index是占空间的,不是越多越好的。选好index很重要。
在这里插入图片描述

13.13 row id/ 删除重复数据行

每个表都有这么一列,这是系统分配的存储地址。唯一的。
在这里插入图片描述
那么我们回过头来看这张表:
在这里插入图片描述
在一开始设计这张表的时候,并没有给主键。那也就是说这张表是可以有很多重复值的。
在这里插入图片描述
现在去填充一些重复的列,告诉我有索引限制。我都不记得我什么时候给加了索引,先去给删掉。在这里插入图片描述
在这里插入图片描述
然后再去插入数据,那么现在就会有重复的数值。有先输入进去的,也有后输入进去的。这在数据库表设计之初没有考虑到。但是如果说现在我要删除重复列了。咋办呢?
在这里插入图片描述
首先我来个分组:有两个ID是有两条数据的。
在这里插入图片描述
此时加上rowID就会看到所有的条目数,可是我要删除重复的行啊,咋整?
在这里插入图片描述
当我去按store_id分组,我知道有重复的会被归为一组,此时再去取rowID的改组内最小值,我就是可以把重复的值给去掉了。取决于我想看原始值(minrowid)还是后来值(maxrowid),那么如此我有了所有要保留的值,再来个反向删值就可以了。
在这里插入图片描述
这样就把后来的记录给删掉了。
在这里插入图片描述
那么现在我们把重复数据行删除了,就可以设置个主键了。然后再加个索引。
在这里插入图片描述

13.14 系统表

这个系统表呢all_tables里面能找到系统内所有表名,在table_name列你能看到表名,都是大写。
在这里插入图片描述
知道这个就可以找表了:
在这里插入图片描述
知道了表名,下一步就是去找表里的列名了,把rownum去掉就行了。
在这里插入图片描述
然后再去找找其他的,所有对象都在,你可以找TABLE,找INDEX就是where object_type = ‘TABLE’ 注意大写。
下面的synonym就是一个表的昵称,就像一个指针:
在这里插入图片描述
不能建public synonym 因为你不是数据库管理员。
在这里插入图片描述
在这里插入图片描述
去找system table就可以看到这些系统表都在干嘛了。
然后记住rowid这个隐藏行, rownum这个功能。

13.15 view/union/minus/replace

在这里插入图片描述
建完了去系统view能看到。
在这里插入图片描述
然后就可以按条件去找对象了。
在这里插入图片描述

在这里插入图片描述
现在假设我要看到store里面工资最高的人:
如果我按下面的写法,是错的:sal in 不是一个正确的思路,因为会有重复的相同sal在不同的store里面。这个根本没考虑到store id啊。如果不同的store id有相同的sal都是highest就错了。
简言之,where in 虽然也是一个join,但是它只能join一个条件,而inner join on 可以很多条件的啊。
所以inner join比较好用啊。
在这里插入图片描述
应该用inner join来写:
但是注意,当你去用inner join的时候是把select 的i作为一个新的表了,这个新的表里也有store_id和sal这个字段选出来的。这就会造成重复了哦。。那所以不要select * from employee e了。咋弄?
在这里插入图片描述
在这里插入图片描述
union的话得是结构相同才行,union的就没有重复行了。但是union all会给出所有重复行 。
在这里插入图片描述
在这里插入图片描述
Minus也是一样的用法,要结构相同才行。
在这里插入图片描述
replace view.
当一个view建好了,如果你再去执行就会报错,说已经有view了,但是你加一个 or replace就会覆盖上去。
在这里插入图片描述
drop view可以直接删掉view。
这里可以查看你自己的schema。在其他数据库就是个show user的命令。
在这里插入图片描述

13.16 revoke/grant

DCL :

grant select on products to User1;
grant select,update,delete on products to User2,User3;
revoke select on products from User1;

Create role role1;
grant select , update , delete to role1;

alter user user1 default role role1;
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaomici

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值