版权声明:著作权归作者所有,未经作者同意不得转载。 https://blog.csdn.net/qq_33417321/article/details/82664164
一、sql基础
- 查询city字段以A或L或N开头的数据
SELECT * FROM Persons WHERE City LIKE '[ALN]%'
- 查询city字段不以A或L或N开头的数据
SELECT * FROM Persons WHERE City LIKE '[!ALN]%'
- 连接符
select concat(id,’的学号’,cardno,’的卡号’); #Mysql语法
select 'hello'||'oracle' test from dual; #Oracle语法(oracle也可以用上边的concat)
- 字符串
select substr('hello',0,3) from dual --下标1与0效果一样 结果:hel
select length('hello') from dual --结果:5
select replace('hello','l','x') from dual --结果:hexxo
- 数值
select round(45.926,2) from dual --45.93 四舍五入
select trunc(45.926,2) from dual --45.92 截断
select mod(1600,300) from dual --100
- 日期
select ename,round((sysdate-hiredate)/7) from emp –入职周数
select ename,round(months_between(sysdate,hiredate)) from emp --入职月数
select add_months(sysdate,3) from dual --3个月后的日期 2018/3/26 21:29:19
- to_char函数
select ename,to_char(hiredate,'yyyy-mm-dd') from emp --1981--02—20
select ename,to_char(hiredate,'fmyyyy-mm-dd') from emp --1981-2-20
select to_char(sysdate,'yyyy-mm-dd hh :mi:ss') from dual—分钟是mi
- to_number函数
select to_number('10')+to_number('12') from dual --将字符串转换为数字
--查询1980和1985年入职的员工
select * from emp where to_char(hiredate,'yyyy')=1980 or to_char(hiredate,'yyyy')=1985
- to_date函数
select * from emp where hiredate between '1890-01-01' and '1982-12-31' #mysql语法
#oracle不能像上边那样写,因为hiredate是日期类型,与字符串类型匹配不上
select * from emp where hiredate between to_date('1980-01-01','yyyy-mm-dd') and to_date('1980-12-31','yyyy-mm-dd') #oracle语法
- decode函数(只有oracle有该函数)
select job, decode(job,
'CLERK', '业务员',
'SALESMAN','销售员',
'其他'
) from emp;
#以下语法(case/when)可以替换是那个边的表达
select job,
case job
when 'CLERK' then '业务员'
when 'SALESMAN' then '销售员'
else '其他'
end
from emp;
- 约束
create table person(
pid number(5),
pname varchar2(30) not null,
gender number(1),
tele varchar2(11) ,
constraint pk_pid primary key(pid),-- constraint后是起的名字
constraint check_gender check(gender in(0,1)),--性别只能是1或2
constraint unique_key unique(tele)
)
- 外键
create table orders( --订单
oid number(5) primary key,
totalprice number(8,2)
)
create table orderdetail( --订单项 键盘,鼠标是两个订单项,属于同一订单
oidid number primary key,
price number(8,2),
name varchar2(30),
oid number(5),--外键
constraint fk_orderdetail_orders foreign key(oid) references orders(oid)
);
- 聚合函数不能写在where之后
SELECT city FROM weather WHERE temp_lo = max(temp_lo); #语法错误,修改为如下写法是正确的
SELECT city FROM weather WHERE temp_lo = (SELECT max(temp_lo) FROM weather); #语法正确
- where与having的区别
WHERE在分组和聚合计算之前选取输入行(它控制哪些行进入聚合计算);而HAVING在分组和聚合之后选取输出行。
因此,WHERE 子句不能包含聚合函数;因为试图用聚合函数判断那些行将要输入给
聚合运算是没有意义的。 相反,HAVING子句总是包含聚合函数。当然,你可以写不使用聚合的HAVING 子句,但这样做没什么好处,因为同样的条件用在WHERE阶段会更有效。
二、数据类型
- 浮点型
float(m,d); #单精度浮点型 8位精度(4字节) m总个数,d小数位
double(m,d); #双精度浮点型 16位精度(8字节) m总个数,d小数位
- char与varchar
char:
固定长度;例如某字段定义为10个长度,该字段存了一个汉字”是”,这个汉字占两个字符,剩下八个字符会自动填满;最大长度255,长度没有默认长度,必须显式指定长度
varchar2:
长度不固定,同上,剩下八个用不到的字符空间会释放出去。Varchar2与mysql里的varchar一样;最大长度3999(即可以放2000个中文或3999个英文),没有默认长度,必须指定长度;
- number
number:默认长度是8
number(3):存的最大数是999
number(3,2):存的最大数是9.99
- date:
相当于mysql里的datetype,mysql里的date只有年月日,datetype还包括时分秒
- timestamp:
也是日期类型,相对于date来说,精度高,最多可以保留到秒后9位小数
- long
相当于mysql里的longtext,即大文本,可以支持两个G
- clob:
可以放四个G内容
- blob:
可以放四个G内容,存放电影,图片等;
- 定点数
#浮点型在数据库中存放的是近似值,而定点类型在数据库中存放的是精确值。
decimal(m,d) 参数m<65,指的是总个数;d<30且 d<m,指的是小数位个数。
三 、注意点
- union与union all
UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。
- 删除数据——delete与truncate
delete from person where name=’tom’;# delete from person删除全部数据;
truncate person; # 删除全部数据
delete:可以回滚,也可以闪回;
delete删除会产生磁盘碎片,且不释放空间;truncate不会产生磁盘碎片;
truncate先摧毁表结构,再重构表结构;delete只删除数据而已;
- savepoint事物保存点
insert into person(pid,pname,gender,tele) values('1','tom','1','13222229090');
savepoint a;
update person set tele='1111111111' where pid='1';
savepoint b;
select * from person;
rollback to a; #回滚到事物保存点a之前
- 视图 view
视图可以理解为一个虚表,封装了一条复杂的查询语句,视图可以隐藏敏感列;
语法:create view 视图名 as sql查询语句(最后是复杂的sql查询语句,可以用括号括起来)
先登录管理员用户,为当前用户(scott)提供创建视图的权限:grant create any view to scott;
create view person_view as (select pname from person where pid='1');#创建视图
select * from person_view;--查出来的是姓名
#优点:隐藏敏感列:比如隐藏工资与奖金列
create view view_emp as(select empno,ename,job,mgr,hiredate,deptno from emp)
select * from view_emp;
修改(update)视图的话,会将视图里涉及到的表数据修改,所以一般创建视图时将视图设计成只读:
create or replace view person_view as (select pname from person where pid='1') with read only; #此时该视图就不能update了
- 序列——sequence
auto increment语法只有mysql有,oracle没有;序列主要是做主键自增的,是独立于表之外的对象;
create sequence seq_person; --创建序列,没有与任何表产生关系,独立于表之外
select seq_person.nextval from dual --1 每执行一次,得到的结果依次加1
select seq_person.currval from dual --查看当前的值
insert into person(pid,pname) values (seq_person.nextval,'tom');
# 序列一般单表单用,有几个表就创建几个序列,如果多个表操作同一张表的序列,容易出现断层;
创建序列的复杂语法如下:
create sequence test
minvalue 3 --最小值,默认是1
increment by 2 --步增值,默认1
start with 5 --起始值,默认1
maxvalue 20 --最大值,默认值是18个9。不做循环的话,超过最大值会报错
cycle --循环 默认是nocycle
cache 5 --缓存,默认缓存的数是20(缓存在内存里),这里的值必须小于每次循环出来的数的个数
select test.nextval from dual;上边的复杂语法不能做主键自增,主键会冲突;即序列主要是做主键自增,也可以做其他事;
- 索引——index
也是独立于表之外的对象;作用是提高查询效率(相当于书的目录);
使用索引规则:
1、表里的数据经常被修改的话,不适合建索引;
2、数据量小时不用建立索引;
3、某些字段不会被当成条件做查询时,没有必要建立索引
语法:create index 索引名 on 表名(字段名);
eg: create index index_emp_ename on emp(ename);
select * from emp where ename='SMITH'; --建索引前后查询所花的时间:0.031 0.016
数据少的话效果不明显,下边创建500万条数据
create table t_test(
tid number,
tname varchar2(30)
)
begin
for i in 1..5000000
loop
insert into t_test values(i,'测试数据'||i);
end loop;
end;
create index test_index on t_test(tname);
select * from t_test where tname='测试数据4565558';#这样数据量大的话效果会很明显;
复合索引:对表里多个字段做索引
create index index_emp on emp(ename,job);# 注意,此时只有将ename,job同时作为查询条件时才会用到索引,不然不会用到索引的,比如select * from emp where job='' and hiredate=''是不会用到索引的;
- 同义词
给用户分配创建同义词的权限:grant create synonym to scott;
同义词相当于别名;
使用场景:一个用户下想访问另一个用户下的某张表,可以这样写:
select * from scott.emp;
此时为了访问方便,可以建立同义词:create public synonym emp for scott.emp --public 可以不写
以后查询时:select * from emp;
删除同义词:drop public synonym emp --如果上边加了public,这里也要加上
- 数据导入导出
用于数据备份;
1、 exp system/root full=y; # 整库导出,基本不用;
2、按用户导入导出:把scott用户下的数据导入maltose01用户下:
注意:使用exp与imp这两个命令的话,电脑上必须安装oracle软件,所以下边的命令需要在虚拟机里执行
--先导出
exp scott/[email protected]:1521/orcl file='c:\scott.dmp'
--再将上边的数据导入到另一个用户
imp maltose01/[email protected]:1521/orcl file='c:\scott.dmp' full=y
3、按表导入导出(plSql工具右键表就能导出该表)
--先导出
exp scott/[email protected]:1521/orcl file='c:\scott.dmp' tables=emp,student,teacher
--再导入到另一个用户
imp maltose01/[email protected]:1521/orcl file='c:\scott.dmp' full=y tables=emp,student,teacher