查询IP地址:win+R,调出窗口,输入cmd,接着输入ipconfig
connect:基本角色;resource:开发者角色;dba:超级管理员角色。
session-----------log off,log on
varchar2是可变长度,char是定长
目前没有区别,但官方文档不支持使用varchar,强烈建议使用varchar2。
varchar2是oracle提供的独特的数据类型,oracle保证在任何版本中该数据类型向上和向下兼容。但不保证varchar,这是因为varchar是标准sql提供的数据类型,有可能随着sql标准的变化而改变。如果数据库不移植的话,就没有区别。如果数据要移植到别的数据库,可能用varchar比较好。varchar2很多数据库不支持。varchar2把所有字符都占两字节处理(一般情况下),varchar只对汉字和全角等字符占两字节,数字,英文字符等都是一个字节。varchar2把空串等同于null处理,而varchar仍按照空串处理。varchar2字符要用几个字节存储,要看数据库使用使用的字符集,比如GBK,汉字就会占两个字节,英文1个,如果是UTF-8,汉字一般占3个字节,英文还是1个。可以直接在创建语句后面追加“tablespace name”进行表空间指定。
sql: create table tablename(id int) tablespace tablespacename;
解释:在表空间“tablespacename”上创建表“tablename”。以上语句就实现了为表指定表空间。
注意:()里面可以写很多列,用“,”隔开。
修改列类型 alter table person modify gender char(1); 修改列名称 alter table person rename column gender to sex; 删除一列 alter table person drop column sex;注意1:如果添加的数据占据了所有列,那person后面的()中可以不写内容。
注意2:增删改一定要写commit提交事务;查询不涉及事务。
修改一条记录 update person set pname='小马' where pid = 1; commit;注意1:在数据量大的情况下,尤其是在表中带有索引的情况下,第三种删除方式操作效率高;因为它是先删除索引。
注意2:索引会提高查询效率,但是会影响增删改效率;
对着表格右击view,column
序列不真的属于任何一张表,但是可以逻辑和表做绑定。
序列的使用:默认从1开始,依次递增,主要用来给主键赋值使用。
dual:虚表,只是为了补全语法,没有任何意义(因为oracle查询必须要打上from)
create sequence s_person; select s_person.nextval from dual; insert into person (pid,pname) values (s_person.nextval,'小明'); commit;注意:用s_person.currval容易报错,因为第一次使用时,没有当前序列。
1、Scott用户,密码tiger
2、解锁Scott用户,解锁密码(也可以用来重置密码)
alter user scott account unlock; alter user scott identified by tiger;注意:此句可以用来重置密码。
EMP:EMPNO(员工编号),ENAME(员工姓名),JOB(员工工作),MGR(员工直属领导编号),HIRDATE(入职日期),SAL(工资),COMM(一年奖金),DEPTNO(部门编号)
DEPT:DEPTNO(部门编号),DNAME(部门名称),LOC(部门地址)
SALGRADE:GRADE(工资等级),LOSAL(最低工资),HISAL(最高工资)
注意1:DEPTNO在EMP中是外键,主键在DEPT中
注意2:右击bonus表,点击query data,表中是没有数据的
作用于一行,返回一个值
截取的时候需要注意:要从哪里开始截取,之后取多长的长度。
select substr('hello',1,2) from dual; select substr('hello',-3,2) from dual; 倒数第三个开始取两位; 检索姓名最后一个字母为N的雇员: SELECT * FROM emp WHERE substr(ename,-1,1)='N'; 检索职务为“SALE”的全部员工信息 SELECT * FROM emp WHERE substr(job,1,4)='SALE';注意:其中length()函数获取的是字符串的字符数,lengthb()获取的是字符串的字节数。但是需要注意的是如果你的数据库中的字段是clob,使用lengthb()会报错。
在oracle 中
select lengthb(‘你好’) from dual; 返回的值是 4
select length(‘你好’) from dual; 返回的值是2
如果有此字符串,则返回位置;如果没有,则返回0。
select instr('hello','o') from dual; SELECT instr('hello','x') FROM dual ;取得当前的日期;
SELECT sysdate FROM dual ;注意:日期-数字=日期;日期+数字=日期;日期-日期=数字(多少天) (日期可以直接加减,最终的单位是天)
查询emp表中所有员工入职距离现在几天: select sysdate-e.hiredate from emp e; 算出明天此刻: select sysdate+1 from dual; 此时出现的结果是一个日期。 计算员工进入公司的周数: SELECT ename,round((sysdate-hiredate)/7) from emp ; 当前日期-雇佣日期(hiredate) = 天数,天数/7为周数。给出指定日期范围的月数;
注意:只有月有months_between。
查询emp表中所有员工入职距离现在几月: select months_between(sysdate,e.hiredate) from emp e; SELECT ename,round(MONTHS_BETWEEN(sysdate,hiredate)) from emp ; 查询emp表中所有员工入职距离现在几年: select months_between(sysdate,e.hiredate)/12 from emp e; 因为一年一定有12个月;在指定的日期上加上指定的月数,求出之后的日期。
求出三个月之后的日期是哪一天: select add_months(sysdate,3) from dual;表示下一个今天(星期几)。
SELECT NEXT_DAY(sysdate,'星期一') FROM dual ; 表示下一个星期一是多少号。 select next_day(sysdate,'Monday') from dual; 注意:可能是由于字符集的原因,这里只能输入Monday,输入‘星期一’一直在报错。。。求出当前日期所在月的最后一天。
SELECT LAST_DAY(sysdate) FROM dual ; 表示本月的最后一天的日期。修改货币字符集的参考网址:
https://www.cnblogs.com/huak/p/3448928.html
oracle中的trunc函数:
https://www.cnblogs.com/williamwsj/p/7001067.html
oracle中的to_char函数:
https://www.cnblogs.com/aipan/p/7941917.html
注意1:只要case后面不加“,”,就一直在一列之中;
注意2:When then可以不限数量写很多个,else可以省略
注意3:注释一行语句用“——”
如果高于3000显示高收入,高于1500低于3000显示中等收入,其余显示低收入
select e.sal, case when e.sal>3000 then '高收入' when e.sal>1500 then '中等收入' else '低收入' end from emp e;总结:oracle中除了起别名,都加单引号。(起别名可以加双引号或者不加引号)
(即聚合函数:作用于多行,返回一个值)
注意:写count(*)也行,但最好写count(1),相当于count(empno),即count主键这一列。
注意:分号是一次查询的结束。
分组查询不要一次性全部写完:select。。。from。。。group by。。。
注意:分组查询中,出现在group by后面的原始列,才能出现在select后面; 没有出现在group by后面的列,想在select后面出现,必须加上聚合函数。
比如:
select e.deptno,avg(e.sal),ename from emp e group by e.deptno;就会出现报错;主要是因为用了分组查询,表结构就会发生改变,由14行变成了3行,但是每个部门肯定不止一个人;
聚合函数有一个特性,可以将多行记录变成一个值;
注意:where是过滤分组前的数据,having是过滤分组后的数据
表现形式:where必须在group by之前,having在group by之后
emp表中14条记录,dept表中4条记录,一共14*4条。
注意:笛卡尔积中大部分数据都是没有用的
效果和等值连接一样。
其实就是站在不同的角度将一张表看成多张表
1)查询出员工姓名,员工领导姓名 select e1.ename,e2.ename from emp e1, emp e2 where e1.mgr=e2.empno;--e1表是员工表,e2表是领导表 一共有13条,因为有一个员工没有领导 2)查询出员工姓名,员工部门名称,员工领导姓名,员工领导部门名称 select e1.ename,d.dname,e2.ename,d.dname from emp e1, emp e2, dept d where e1.mgr=e2.empno and e1.deptno=d.deptno and e2.deptno=d.deptno 此时语法没问题,但是只有11条记录,因为加的过滤条件是:员工和领导在同一个部门。。。 所以正确写法: select e1.ename,d1.dname,e2.ename,d2.dname from emp e1, emp e2, dept d1, dept d2 where e1.mgr=e2.empno and e1.deptno=d1.deptno and e2.deptno=d2.deptno 3)查询出每个员工编号,姓名,部门名称,工资等级和他的上级领导姓名,工资等级 select e.empno, e.ename, e.sal, decode (s.grade,1,'一级',2,'二级',3,'三级',4,'四级',5,'五级') e_grade, d.dname, e1.empno, e1.ename, e1.sal, decode (s1.grade,1,'一级',2,'二级',3,'三级',4,'四级',5,'五级') e1_grade from emp e, emp e1, dept d, salgrade s, salgrade s1 where (e.mgr = e1.empno) and (e.deptno = d.deptno) and (e.sal between s.losal and s.hisal) and (e1.sal between s1.losal and s1.hisal);注意1:SCOTT必须写大写,不可以写小写
注意2:select * from emp where sal =
(select sal from emp where ename = ‘SCOTT’);
这里的等于最好写in,因为此时ename并不是主键,所以可能会有很多SCOTT,但是如果ename是主键,可以写“=”。
注:子查询永远先执行里面,所以这里可以使用别名
当我们做select操作的时候,每查询出一行记录,就会在该行上加上一个行号,行号从1开始,依次递增,不能跳着走。
排序操作会影响rownum的顺序 select rownum,e.* from emp e order by e.sal desc注1:rownum前面不能加表的别名
注2:rownum只能放在select后面
注3::此时,rownum的顺序是乱的,因为必须把所有数据查询了之后,才能排序;
先执行select,此时rownum顺序是正确的, 加上order by之后,就成了乱序;
如果涉及到排序,但还要使用rownum的话,我们可以再次嵌套查询 select rownum, t.* from( select rownum,e.* from emp e order by e.sal desc) t emp表工资倒叙排列后,每页五条记录,查询第二页: 错误代码: select rownum, e.* from(select * from emp order by sal desc) e where rownum<11 and rownum>5此时一条记录都没有了,因为行号是从1开始,不能跳着走
并且,是先where,后select,1肯定小于5,所以永远无法满足大于5的条件,所以没有办法select;
结论:条件中rownum行号不可以写大于一个正数(>0是可以的)
正确代码: select * from(select rownum rn, e.* from(select * from emp order by sal desc) e where rownum<11) where rn>5; 此时,将rownum变成普通的一列 还有一种写法: select * from (select rownum r, e.* from emp e) b where b.r>5 and b.r<11; 但是这种写法不可以order by 操作视图就是提供一个查询的窗口,所有数据来自于原表。
注:视图需要起名字。
注意:此时原表的数据也改变了,视图中根本没有存放数据,改的是表的数据。
1)视图可以屏蔽掉一些敏感字段
2)保证总部和分部数据及时统一
索引就是在表的列上构建一个二叉树,达到大幅度提高查询效率的目的,但是索引会影响增删改的效率
(单行函数,模糊查询,都会影响索引的触发)
select * from emp where ename='SCOTT';复合索引中第一列为优先检索列;
如果要触发复合索引,必须包含有优先检索列中的原始值。
a)select * from emp where ename='SCOTT'; 注:这一列既包含在单列索引中,又包含在复合索引中,此时触发的是单列索引; b)select * from emp where ename='SCOTT' and job='xx'; 此时触发的是复合索引; c)select * from emp where ename='SCOTT' or job='xx'; 此时不触发索引; 因为写了or,就相当于写了两个查询语句,一个触发,一个不触发,最终的结果就是不触发。pl/sql编程语言是对sql语言的扩展,使得sql语言具有过程化编程的特性。
pl/sql编程语言比一般的过程化编程语言,更加灵活高效。
pl/sql编程语言主要用来编写存储过程和存储函数等。
a)
declare i number(2) := 10; s varchar2(10) := '小明'; begin dbms_output.put_line(i); dbms_output.put_line(s); end;i定义一个变量,number表示长度;
一般都用number,因为防止i是一个小数。
b)
declare ena emp.ename%type;--------引用型变量(变量类型为emp表中ename的类型) empow emp%rowtype;---------记录型变量(即存一行记录,一个对象) begin select ename into ena from emp where empno=7788; dbms_output.put_line(ena); select * into empow from emp where empno=7788; dbms_output.put_line(empow.ename || '的工作为:' || empow.job); end;注意:赋值操作可以使用“:=”,也可以使用into查询语句赋值;oracle中的连接符号为“||”。
(三种循环中用的比较多的是exit循环)
e.g:用三种方式输出1到10十个数字:
注意:写的时候一定要严格注意分号。
可以存放多个对象,多行记录
1、输出emp表中所有员工的姓名 declare cursor c1 is select * from emp; emprow emp%rowtype; begin open c1; loop fetch c1 into emprow; exit when c1%notfound; dbms_output.put_line(emprow.ename); end loop; close c1; end; 2、给指定部门员工涨工资 declare cursor c2(eno emp.deptno%type)-------带参数的游标 is select empno from emp where deptno = eno; en emp.empno%type; begin open c2(10);----给10号员工涨工资 loop fetch c2 into en; exit when c2%notfound; update emp set sal=sal+100 where empno=en; commit; end loop; close c2; end; 查询10号部门员工工资 select * from emp where deptno=10;就是提前已经编译好的一段pl/sql语言,放置在数据库端,可以直接被调用。
这一段pl/sql一般都是固定步骤的业务。
[or replace]可写可不写;是直接修改的意思,一般最好加上,尤其是业务复杂的时候
PROCEDURE是关键字,必须要带上
默认不写的类型是in类型
AS也可以写IS
给指定员工涨100块钱工资:
create or replace procedure p1(eno emp.empno%type)---不写,则默认in类型 is begin update emp set sal=sal+100 where empno = eno; commit; end;测试p1:
declare begin p1(7788); end; select * from emp where empno = 7788;一般来讲,过程和函数的区别在于,函数可以有一个返回值,而过程没有返回值;
但过程和函数都可以通过out指定一个或多个输出函数。我们可以利用out参数,在过程和函数中实现返回多个值。
注意:存储过程和存储函数的参数都不能带长度;存储函数的返回值类型不能带长度;
通过存储函数实现计算指定员工的年薪:
create or replace function f_yearsal(eno emp.empno%type) return number------返回值类型后面不可以加长度(引用型变量在不需要长度的时候会自己去掉长度) is s number(10);-----这里是自己定义的变量 begin select sal*12+nvl(comm,0) into s from emp where empno = eno; return s; end;测试f_yearsal:
declare s number(10); begin s := f_yearsal(7788); dbms_output.put_line(s); end;注意:存储函数在调用的时候,返回值需要接收
1)使用存储过程来算年薪
create or replace procedure p_yearsal(eno emp.empno%type,yearsal out number) is s number(10); c emp.comm%type; begin select sal*12, nvl(comm,0) into s, c from emp where empno = eno; yearsal := s+c; end;测试p_yearsal:
declare yearsal number(10); begin p_yearsal(7788, yearsal); dbms_output.put_line(yearsal); end;2)in和out类型参数的区别是什么?
凡是涉及到into查询语句赋值或者:=赋值操作的参数,都必须使用out来修饰;否则其余的都用in。
关键字不一样,一个是procedure,一个是function
存储函数比存储过程多了两个return。
本质区别:存储函数有返回值,而存储过程没有返回值;
如果存储过程想实现有返回值的业务,我们就必须使用out类型的参数;
即便是存储过程使用了out类型的参数,其本质也不是真的有了返回值,而是在存储过程内部给out类型参数赋值,在执行完毕之后,我们直接拿到输出类型参数的值。
我们可以使用存储函数有返回值的特性,来自定义函数。而存储过程不能用来自定义函数。
查询出员工姓名,员工所在部门名称。
1)案例准备工作: 把SCOTT用户下的dept表复制到当前用户下 create table dept as select * from scott.dept; 2)使用传统方式来实现案例需求: select e.ename,d.dname from emp e,dept d where e.deptno=d.deptno; 3)使用存储函数来实现提供一个部门编号,输出一个部门名称 create or replace function fdna(dno dept.deptno%type) return dept.dname%type is dna dept.dname%type; begin select dname into dna from dept where deptno = dno; return dna; end; 4)使用fdna存储函数来实现案例需求:查询出员工姓名,员工所在部门名称 select e.ename, fdna(e.deptno) from emp e;注意:只有存储函数可以这样做,因为有返回值。
就是制定一个规则,在我们做增删改操作的时候,只要满足该规则,自动触发,无需调用。
语句级触发器:不包含有for each row的触发器
行级触发器:包含有for each row的就是行级触发器
加for each row是为了使用:old或者:new对象或者一行记录。
插入一条记录,输出一个新员工入职
1)create or replace trigger t1 -----操作后触发 after insert on person declare begin dbms_output.put_line('一个新员工入职');-----双引号只在起别名的时候使用 end; 2)触发t1 insert into person values (1, '小红'); commit; select * from person;不能给员工降薪:
1)create or replace trigger t2 -----降工资前触发,拦截降工资这件事情 before update on emp for each row declare begin if :old.sal>:new.sal then raise_application_error(-20001,'不能给员工降薪');---抛异常 end if; end; 注意:raise_application_error(-20001~-20999之间,不能重复,'错误提示信息');---抛异常 3)触发t2 update emp set sal=sal-1 where empno = 7788; commit; select * from emp where empno=7788;分析:在用户做插入操作的之前,拿到即将插入的数据,给该数据中的主键列赋值。
1) create or replace trigger auid before insert on person for each row declare begin select s_person.nextval into :new.pid from dual; end; 2)查询person表数据 select * from person; 3)使用auid实现主键自增 insert into person (pname) values ('a'); commit; 或者: insert into person values (1,'b'); commit;oracle 10g -------ojdbc14.jar
oracle 11g -------ojdbc6.jar
补充:
身份证号码15位升18位的计算方法:
1、第一步在原15位身份证的第六位后面插入19
这样身份证号码为17位
2、每一位与其对应的系数相乘
系数表:
位数1234567891011121314151617乘数7910584216379105842乘数的由来:mod(power(2,i-1),11) i从18开始
把相乘之后的结果相加,然后对11取余
得到一个0-10的数字尾数
尾数对应表:
01234567891010X98765432这样就得出你的18位身份证号
例如,原15位身份证号码为:310112850409522
1)310112850409522 --> 310112 + 19 + 850409522 --> 31011219850409522
2)3*7+1*9+0*10+1*5+1*8+2*4+1*2+9*1+8*6+5*3+0*7+4*9+0*10+9*5+5*8+2*4+2*2 = 258
3)258 Mod 11 = 5
4)5 --> 7
5)31011219850409522 + 7 --> 310112198504095227
故升级后,新18位身份证号码为:310112198504095227