12Oracle Database SQL程序
Oracle Databse SQL 程序
程序块
在这之前,我们所有的sql语句都是一句一句执行的,如果我们把很多事情看作一个整体提交执行的话,必须使用程序块。
声明部分:声名变量及初始化
关键字:declare
执行部分:存放所有可执行的代码,这些代码包含在begin/end中
关键字:begin end
每个指令结束用;表示,--表示注释
--这是一个示例
declare
i number:=5; y number:=6;
begin
i:=i+y;
dbms_output.put_line(i);
end;
/
流程控制
--条件if......then...elseif.. .end if;
declare
i number:=50;
begin
if i=50
then dbms_output.put_line(i);
elsif i<50
then dbms_output.put_line(0);
end if;
end;
/
-----使用loop循环(exit when 退出条件)
declare
i number;
begin
i:=0;
loop
exit when i=10;
dbms_output.put_line(i);
i:=i+1;
end loop;
end;
-----使用while-loop循环
declare
i number;
begin
i:=0;
while i<10
loop
dbms_output.put_line(i);
i:=i+1;
end loop;
end;
/
-----使用for-loop循环
begin
for i in 1..10
loop
dbms_output.put_line(i);
end loop;
end;
/
-----使用for-loop反序循环
begin
for i in REVERSE 1..10
loop
dbms_output.put_line(i);
end loop;
end;
字符串函数
函数名: ASCII(char)
含义: 返回与指定的字符对应的十进制数
示例: select ascii('孟') from dual;
结果: 50127
函数名: CHR(int)
含义: 给出整数,返回对应的字符
示例: select chr(50127) from dual;
结果: 孟
函数名: CONCAT(string,string)
含义: 连接两个字符串
示例: select concat('我是','孟庆晨') from dual;
结果: 我是孟庆晨
函数名: INITCAP(string)
含义: 返回字符串并将字符串的第一个字母变为大写
示例: select INITCAP('aaa') from dual;
结果: Aaa
函数名: INSTR(被搜索字符串,搜索的字符串,搜索的开始位置默认为1,第几次出现默认为1)
含义: 在一个字符串中搜索指定的字符,返回发现指定的字符的位置
示例: select INSTR('我是孟庆晨','孟',1,1) from dual;
结果: 3
函数名: LENGTH(string)
含义: 返回字符串的长度
示例: select length(‘孟庆晨’) from dual ;
结果: 3
函数名: LOWER(string)
含义: 小写形式
示例: select lower(‘AAA’) from dual
结果: aaa
函数名: UPPER
含义: 大写形式
示例: select upper(‘aaa’) from dual ;
结果: AAA
函数名: RPAD & LPAD
含义: 黏贴字符串到目标字符串左右
示例: select lpad(‘a’,10,’*’) from dual ;
结果: *********a
函数名: ltrim & rtrim
含义: 删除左边(右边)的字符串
示例: select ltrim(‘abc’,’a’) from dual ;
结果: bc
函数名: substr
含义: 取字符串(原字符串,第几个开始,取几个)
示例: select substring(‘abcdefg’,3,4) from dual
结果: cdef
函数名: REPLACE(string,string,string)
含义: 替换字符串
示例: select replace(‘abcde’ , ‘abc’ , ‘aaa’ ) from dual ;
结果: aaade
数学函数
函数名: abs
含义: 返回指定值的绝对值
示例: select abs(-10) from dual
结果: 10
异常处理
自定义异常处理 1. 定义异常处理 定义异常处理的语法如下: declare 异常名 exception;
begin 2. 触发异常处理 触发异常处理的语法如下: raise 异常名; 3. 处理异常 触发异常处理后,可以定义异常处理部分,语法如下: Exception When 异常名1 then 异常处理语句段1; When 异常名2 then 异常处理语句段2;
end;
小技巧
raise_application_error(错误代码,错误原因) 函数可以直接抛异常
其中错误代码为-20000到-20999之间,错误原因为2000个以内的字符
set linesize 800;
set linesize 可以一行的字符数,默认80
设置每行为800个字符,set linesize 800;
2.7.2、L(list)
此命令可以显示SQL缓冲区中的内容
相当于上下键来显示输入过的SQL语句
2.7.3、run / r
以上三个命令完成的功能是一样的,重新运行缓存区中的语句
2.7.4、save
Save命令可以将缓存区中的语句保存到文件
|
save c:\sql.sql; |
2.7.5、get
Get可将文件中的sql读取出来
|
get c:sql.sql |
2.7.6、ed
可以采用记事本编辑sql语句
|
ed |
2.7.7、如何直接运行文件中的sql语句
|
@c:\sql.sql |
2.10.1、lower
查询员工信息,将姓名转换成小写
|
select empno,lower(ename) from emp ; |
2.10.2、upper
|
select empno,upper(ename) from emp ; |
2.10.3、substr
l 查询员工,只显示员工姓名的前三个字符
|
select empno,substr(ename,1,3) from emp; |
2.10.4、length
l 查询员工,取得员工姓名的长度
|
select empno,length(ename) as 长度 from emp; |
2.10.5、trim
Trim会去除头尾空格,不会去除中间的空格
|
select empno,trim(ename) from emp ; |
2.10.6、to_date
l 查询入职日期大于1980年01月01日
|
select empno,ename from emp where HIREDATE > to_date('1980-01-01','YYYY-MM-DD'); |
To_date可以将字符串转换成日期,具体格式to_date(字符串,匹配格式)
日期格式的说明
|
控制符 |
说明 |
|
YYYY |
表示年 |
|
MM |
表示月 |
|
DD |
表示日 |
|
HH12,HH24 |
表示12小时制,表示24小时制 |
|
MI |
表示分 |
|
SS |
表示秒 |
2.10.7、to_char
l 查询所有员工,将入职日期格式成年月日时分秒方式
|
select empno,ename ,to_char(HIREDATE,'YYYY-MM-DD') as 雇佣日期 from emp; |
l 查询所有员工,小数保留两位,采用逗号分组
|
select empno,ename ,to_char(sal,'$999,999.00') from emp; |
将数字转换成字符串,格式
|
控制符 |
说明 |
|
9 |
表示一位数字 |
|
0 |
位数不够可以补零 |
|
$ |
美元符 |
|
L |
本地货币符号 |
|
. |
显示小数 |
|
, |
显示千分位 |
2.10.8、to_number
将字符串转换成数值
|
select * from emp where sal>to_number('1,000', '999,999'); |
2.10.9、nvl
l 取得员工的全部薪水,薪水+津贴
|
select empno,ename,sal+comm from emp ;---错误 |
以上结果不正确,主要原因是津贴(comm)字段为null,所以无法计算,所以正确的做法是将津贴先转换成0,再计算。可以使用Oracle提供的nvl,该函数的语法格式为:nvl(表达式1,表达式2),表达式1:指的是字段名称;表达式2:指的是将该字段的null转换成的值
l 采用nvl函数,取得员工的全部薪水,薪水+津贴
|
select empno,ename,sal+nvl(comm,0) as 全部薪水 from emp ; |
以上结果是正确的,在做表设计的时候,关于数值字段最好不允许为null,可以设置缺省值为0
2.10.10、case … when … then …end
l 如果job为MANAGER工资涨50%,如果是SALESMAN工资涨20%
|
select empno,ename , case job when 'MANAGER' then sal*1.5 when 'SALESMAN' then sal*1.2 end as newsal from emp ; |
具体用法case 字段 when 条件 then 。。。。when… then….. end
2.10.11、Decode
同case 。。 when … then ….end
|
select empno,ename ,decode(job,'MANAGER',sal*1.5,'SALESMAN',sal*1.2) as 薪水 from emp ; |
Decode语法:decode(字段,条件,执行的运算)
2.10.12、round
round主要可以完成四舍五入
|
select round(sal/100.0) from emp; |
注意:dual是Oracle提供的,主要为了方便因为使用select那么from后面需要跟上表
2.11、聚合函数
|
count |
取得记录数 |
|
sum |
求和 |
|
Avg |
取平均 |
|
Max |
取最大的数 |
|
min |
取最小的数 |
2.11.1、Count
l 取得所有的员工数
|
select count(*) from emp; |
采用count(*)会取的记录,忽略null
l 取得津贴不为null的员工数
|
select count(*) from emp where comm is not null; |
采用count(字段名称),该字段不会null的个数
l 取得工作岗位的个数
|
select count(job) from emp; |
Distinct可以过滤重复的记录
|
select count(distinct job) from emp; |
2.11.2、sum
Sum可以取得某一列的和,但忽略null的行,sum里可以放置表达式
l 取得薪水的合计数
|
select sum(sal) as sal_total from emp; |
l 取得薪水的合计数(薪水+津贴)
从计算结果来看,不正确,原因在于comm字段有null,所以无法计算,sum会忽略掉。正确的做法,是将comm字段先转换成0再sum,如下所示:
l 取得薪水的合计数(薪水+津贴)
|
select sum(sal+nvl(comm,0)) as sal_total from emp; |
正确
2.11.3、avg
取得某列或表达式的平均值
l 取得平均薪水
|
select avg(sal) from emp; |
2.11.4、max
Max取得指定列的最大值
l 取得最高的薪水
|
select max(sal) as 薪水 from emp; |
l 取得最晚入职的员工
|
select max(to_char(hiredate,'YYYY-MM-DD')) from emp; |
2.11.5、min
取得指定列的最小值
l 取得最低薪水
|
select min(sal) from emp; |
2.11.6、组合聚合函数
可以在select组合使用聚合函数
l 取得员工数,工资合计,平均工资,最高工资,最低工资
|
select count(*) as 员工数,sum(sal) as 工资合计 ,avg(sal) as 平均工资 , max(sal) as 最高薪水,min(sal) as 最低薪水 from emp ; |
2.12、分组查询
分组主要涉及到两个子句:group by和having
2.12.1、group by
l 取得每个岗位的工资合计,要求显示出岗位名称和每个岗位的工资合计
|
select sum(sal) ,job from emp group by job; |
采用group by时,聚合函数前的所有字段必须参与分组
采用group by时,如果存在order by,那么order by必须放到group by后面
以上是不正确的
l 取得每个岗位的工资合计,要求显示出部门代码,岗位名称和每个岗位的工资合计
2.12.2、having
如果想按条件取得分组中的数据那么需要使用having
l 取得平均工资大于2000的岗位
|
select job,avg(sal) from emp group by job having avg(sal) >2000; |
分组函数的执行顺序:
a) 先根据条件查询数据
b) 对记录分组
c) 采用having进行过滤,选择出正确的数据
2.12.3、select语句总结
完整的select语句格式如下
|
Select *,列名 From 表名 Where ….. Group by …… Having ……. Order by …….. |
以上语句执行顺序
a) 首先执行where语句来过滤原始记录
b) 执行group by分组
c) 执行having过滤
d) 执行select选出数据
e) 最后执行order by排序
关键点:把子查询作为一张表来用
2.15、union、minus
2.15.1、Union可以合并结果集(加)
|
select deptno,dname from dept union select empno ,ename from emp; |
2.15.1、minus可移除结果集(减)
l 查询部门编号为10和20的员工,移除薪水小于2000的
|
select empno,ename from emp where deptno=10 or minus select empno,ename from emp where sal<2000; |
相当于:select empno, ename, sal from emp where deptno in(10, 20) and sal >=2000;
2.16、rownum的使用
Oracle提供了一个rownum隐含字段,每个表都有,rownum是每条记录的行号,从1开始顺序递增
2.16.1、隐含字段rownum
|
select rownum ,empno,ename from emp; |
2.16.2、显示出前五条数据
|
select empno ,ename from emp where rownum<=5; |
2.16.3、显示大于5行以后的数据
|
select empno ,ename from emp where rownum>=5; |
以上语句,无法查询到符合条件的数据,rownum只支持<=,不支持= 或>= 或>
只支持=1
select empno ,ename from emp where rownum=1;-这条可以
2.16.4、显示薪水最高的前5为员工
上面的结果不是预期的结果,因为rownum在数据集形成时已经确定,采用order by 排序不会给便rownum的值,采用如下方式可以取得前5名:
|
select rownum ,empno,ename from (select empno,ename from emp order by sal desc) e Where rownum<=5; |
2.16.5、采用rownum分页查询
分页查询主要为了提高效率,不是一次性查询出所有的数据,而是部分查询,如:每次查询5条
第一页:1~5
第二页:6~10
第三页:。。。。。。
因为rownum不支持>=,必须采用3层嵌套的sql来进行分页,嵌套的目的就是转换rownum,支持大于等于
|
select empno, ename, sal from (select rownum r, empno, ename, sal from (select rownum ,empno, ename, sal from emp order by sal desc ) where rownum <=10 ) where r>5; |
以上使用3层的select嵌套完成分页,嵌套的目的就是将rownum转换成一个字段r,r代表了一个字段,r不再是隐含字段,r作为普通字段,所以我们就可以对r进行任何操作
如果忽略了插入的字段,那么它会严格按照表中字段的顺序,包括类型必须符合,这中方式存在缺陷,如果表中位置发生改变,将会影响到insert语句。可以显示的设置某个值为null
l 指定字段插入
|
insert into emp (empno,ename) values(3000,'kyle'); |
建议使用以上insert方式,此种方式存在优点,当数据库表中的字段顺序发生改变,不会影响到我们的insert语句
l 表内容复制---记住
|
create table new_emp as select * from emp; |
以上语句可以自动建立一个表,将所有的数据拷贝到新表中
l 如何将查询出的数据插入到已经存在的表中(insert into 新表名 select * from 表名)
|
insert into new_emp select * from emp; ----要求表必须存在 |
本示例同create table new_emp as select ……的区别在于,本示例不会创建表,只向已经存在的表中复制数据,而前者会自动创建表。
2.17.2、update
Update可以更新数据,它可以更具条件更新
l 语法格式
|
Update 表名 set 字段名称=更新的值,……… where ……….. |
l 更新全部数据
将所有的工资全部改为1000
|
update new_emp set sal=1000 ; |
如果job为MANAGER,薪水上涨50%
|
update new_emp set sal=sal+(sal*0.5) where job='MANAGER'; |
可以更新多个字段,字段间用逗号隔开
|
update new_emp set sal=10000 ,comm=5000 where job='MANAGER' ; |
2.17.3、delete
Delete可以删除一个或多个数据
l 语法格式
|
Delete from 表名 where ……. |
l 删除部门数据
删除津贴为null的记录
|
delete from new_emp where empno=7782; delete from new_emp where comm is null; |
l 删除全部数据
|
delete from new_emp; |
2.18、事务概述
|
北京数据库 金额:10000 |
|
深圳数据库 金额: |
|
向深圳数据库转账8000,必须保障北京数据库减少8000,深圳数据库增加8000,这两项操作必须全部成功,如何保障?需要事务 |
事务可以保证多个操作原子性,要么全成功,要么全失败。对于数据库来说事务保证批量的sql要么全成功,要么全失败。事务具有四个特征ACID
a) 原子性
b) 一致性
c) 隔离性
d) 持续性
事务中存在一些概念:
a) 事务(Transaction):一批操作(一组sql)
b) 开启事务(Begin Transaction)
c) 回滚事务(rollback Transaction)--Oracle---rollback
d) 提交事务(commit transaction)----Oracle--commit
当执行DML语句是其实就是开启一个事务
关于事务的回滚需要注意:只能回滚insert、delete和update语句,不能回滚select(回滚select没有任何意义),对于create、drop、alter这些无法回滚
2.19、表
2.19.1、创建表
l 语法格式
|
Create table 表名( 列名称 类型, ……………., ……………. ) |
l Oracle常用数据类型
|
类型 |
描述 |
|
Char(长度) |
定长字符串,存储空间大小固定,适合作为主键或外间 |
|
Varchar2(长度) |
变长字符串,存储空间等于实际数据空间 |
|
Number(位数,小数位) |
数值型 |
|
Date |
日期型 |
l 建立学生信息表
组要涉及的字段:学号、姓名、性别、出生日期,email、班级标识
|
create table t_student ( student_id number(10) , student_name varchar2(20), sex char(2), birthday date, email varchar2(20), classes_id number(3), primary key(student_id) ) |
l 建立表加入默认值
性别加入默认值为“男“,出生日期加入默认值为当前时间
|
create table t_student ( student_id number(10), student_name varchar2(20), sex char(2) default '男', birthday date default sysdate, email varchar2(20), classes_id number(3) ) |
2.19.2、创建表加入约束
l 常见的约束
a) 非空约束,not null
b) 唯一约束,unique key
c) 主键约束,primary key
d) 外键约束,foreign key
e) 自定义检查约束,check
l 非空约束,not null
非空约束可以指定某个字段不为空,如:学生姓名不能为空
|
create table t_student ( student_id number(10), student_name varchar2(20) not null, sex char(2) default '男', birthday date default sysdate, email varchar2(20), classes_id number(3) ) |
以上,我们可以为约束起个名字,建表语句如下:
|
create table t_student ( student_id number(10), student_name varchar2(20) constraint stu_name_not_null not null, sex char(2) default '男', birthday date default sysdate, email varchar2(20), classes_id number(3) ) |
l 唯一约束,unique key
唯一约束,可以使某一个字段的值不能重复,如:email不能重复
|
create table t_student ( student_id number(10), student_name varchar2(20), sex char(2) default '男', birthday date default sysdate, email varchar2(20) unique, classes_id number(3) ) |
同样可以为唯一性约束起一个约束名称
|
create table t_student ( student_id number(10), student_name varchar2(20), sex char(2) default '男', birthday date default sysdate, email varchar2(20) constraint email_unique unique, classes_id number(3) ) |
以上约束是在字段后面,这种方式称为字段级约束,另外这种约束也可以加到字段定义的后面,此时称为表级约束
|
create table t_student ( student_id number(10), student_name varchar2(20), sex char(2) default '男', birthday date default sysdate, email varchar2(20), classes_id number(3), constraint email_uqinue unique(email) ) |
l 主键约束,primary key
每个表都应该具有主键,主键可以标识一条记录的唯一性,主键分为单一主键和复合主键
单一主键:一个字段构成主键
复合:多个字段构成主键,一般不建议使用
|
create table t_student ( student_id number(10) primary key, student_name varchar2(20), sex char(2), birthday date, email varchar2(20), classes_id number(3) ) |
以上也已采用表级约束
|
create table t_student ( student_id number(10), student_name varchar2(20), sex char(2), birthday date, email varchar2(20), classes_id number(3), constraint stu_pk_id primary key(student_id) ) |
复合主键示例
|
create table t_student ( student_id number(10), student_name varchar2(20), sex char(2), birthday date, email varchar2(20), classes_id number(3), constraint stu_pk_id primary key(student_id,student_name) ) |
l 外键约束,foreign key
外键通常建立在两个字段或两个表之间,主要为了保证参照完整性,如果一表中的某个字段为外键,那么这个字段的值全部来源于另一表的主键,例如:emp表中的deptno是一个外键,它的值全部来源于dept表的主键字段deptno
如果向emp表中加入一条数据,指定deptno为60,将会出现如下错误:
出现错误的原因就是,emp表中的deptno是外键,而60在dept表中不存在,所以无法参照60这个部门
如果emp表中的deptno没有设置为非空,虽然他是外键,但仍然可以插入null值,如果设置了外键,最好设置这个外键这段为非空
删除dept表中的记录,将会出现如下问题
出现问题的原因是:emp表中参照了部门编号10,如果想删除必须先将emp表中引用部门编号10的员工删除,再来删除dept表中的部门编号10
对t_student表中的classes_id如何创建外键约束:
首先加入t_classes表
|
Create table t_classes ( Id number(3), Name varchar2(2), Constraint t_classes_pk_id primary key(id) ) |
建立外键
|
create table t_student ( student_id number(10), student_name varchar2(20), sex char(2), birthday date, email varchar2(20), classes_id number(3) references t_classes(id), constraint stu_pk_id primary key(student_id,student_name) ) |
也可以采用表级约束
|
create table t_student ( student_id number(10), student_name varchar2(20), sex char(2), birthday date, email varchar2(20), classes_id number(3) not null, constraint stu_pk_id primary key(student_id,student_name), constraint stu_fk_classes_id foreign key(classes_id) references t_classes(id) ) |
外键一定要来源于主键
l 自定义检查约束,check
使用check可以检查表中的字段,是否复合某一个表达式,如:性别只能为“男”或“女”
|
create table t_student ( student_id number(10), student_name varchar2(20), sex char(2) , birthday date, email varchar2(20), classes_id number(3) not null, constraint stu_pk_id primary key(student_id,student_name), constraint stu_fk_classes_id foreign key(classes_id) references t_classes(id), constraint stu_check_sex check(sex in('男','女')) ) |
Check支持常见的表达式,但check很少使用,通常关于验证都在应用程序中做,而不再数据库中作
2.19.3、T_student完整示例
|
create table t_student ( student_id number(10), student_name varchar2(20) not null, sex char(2) not null, birthday date not null, email varchar2(20) unique, classes_id number(3) not null, constraint stu_pk_id primary key(student_id), constraint stu_fk_classes_id foreign key(classes_id) references t_classes(id), constraint stu_check_sex check(sex in('男','女')) ) |
2.19.4、增删改表结构
当一个表已经包含数据,如果表结构需要改变,那么我们不能删除后,再创建表,这样数据会丢失,采用alter table来修改表结构
l 添加字段
例如:向t_student表中加入联系电话字段
|
alter table t_student add (telphone varchar2(20)); |
l 修改字段
例如:修改t_student中的student_name为varchar2(30)
|
alter table t_student add (telphone varchar2(20)); |
l 删除字段
例如:删除t_student中contact_tel
|
alter table t_student drop(telphone); |
2.19.5、增删改约束
l 删除约束
将t_student表中的classes_id外键约束
|
alter table t_student drop constraint stu_fk_classes_id; |
l 添加约束
将t_student表中的classes_id加入外键约束
|
alter table t_student add constraint stu_fk_classes_id foreign key(classes_id) references t_classes(id); |
l 修改约束
修改t_student的student_name为null
|
alter table t_student modify(student_name varchar(30) null); |
2.19.6、删除表
|
Drop table 表名 |
如果存在外键关联,首先先删除子表,再删除父表
2.20、索引
索引的目的是加快查询速度,就像一本数据的目录一样。建立索引的原则:非常少的DML操作;经常出现在where语句中的字段
2.20.1、建立索引
l 对t_student中的birthday建立索引
|
create index idx_t_student_birthday on t_student(birthday); |
2.20.2、删除索引
|
drop index IDX_T_STUDENT_BIRTHDAY; |
2.21、视图
看如下示例:
|
select a.deptno, a.avg_sal, b.grade from (select deptno, avg(sal) as avg_sal from emp group by deptno) a, salgrade b where a.avg_sal between b.losal and b.hisal; |
如果频繁使用以上查询语句,那么会带来维护的成本,那么需要使用到视图技术
2.21.1、创建视图
|
create view v_dept_avg_sal as select a.deptno, a.avg_sal, b.grade from (select deptno, avg(sal) as avg_sal from emp group by deptno) a, salgrade b where a.avg_sal between b.losal and b.hisal; |
执行以上语句创建视图,会出现没有权限的错误,因为scott用户没有授予创建视图的权利,如何查看当前用户的权限:
|
select * from session_privs; |
切换用户
|
让scott以sysdba身份登录 Conn scott/tiger as sysdba Sqlplus/nolog Conn /as sysdba |
开始授权,授予创建视图的权限
|
grant create view to scott; 前提是以sysdba权限登录,然后grant resource, sysdba to scott; |
再次切换到scott
|
conn scott/tiger |
再次查看权限
|
select * from session_privs; |
成功授予了创建视图的权限
开始创建视图
视图创建成功
视图的使用表一样,可以和表或和视图关联,但是视图不能进行增删改,只能进行查询。
视图最好不要频繁创建,当表结构发生改变将会影响到视图,视图的主要的作用就是查询的方便性
2.21.2、删除视图
|
Drop view 视图名称 |
2.22、序列:sequence
序列是Oracle专有的,主要来产生一个自增的数字序列,如:t_student表中的学号,我们就可以采用自增的方式,序列主要用在主键的生成上
还有一种经常使用的生成策略:identity,如:MySQL, Ms SQLServer
2.22.1、创建序列
|
create sequence seq_student_id start with 1 increment by 1; |
2.22.2、使用序列
向t_student表中插入数据
|
insert into t_student(student_id, student_name, sex, birthday, classes_id) values(SEQ_STUDENT_ID.nextval, 'zhangsan','男',to_date('2009-06-06', 'yyyy-mm-dd'), 111); |
以上会看到,增加一个student,那么student_id会自增,如果出现错误,将会断号
2.22.3、删除序列
|
drop sequence SEQ_STUDENT_ID; |
2.23、存储过程、触发器和游标
2.23.1、存储过程
存储过程最直接的理解:就是保存了批量的sql(select,insert,if for),以后可以通过一个名字把这些批量的sql执行,使用存储过程在大批量数据查询或计算时会带来高性能,存储过程存在确定,编写和调试复杂,不同数据库产品存储过程差异非常大,很难实现平滑一致
l 建立存储过程
|
create or replace procedure proc_test(in_var number,out_var out sys_refcursor) as begin open out_var for select * from new_emp where deptno=in_var; end; |
l 执行存储过程
2.23.2、触发器
触发器是特殊的存储过程,它与数据库的insert、update和delete相关联,如定义完成触发器之后,会在insert、update或delete语句执行前或执行后自动执行触发器中的内容
触发器示例,向new_emp表中加入数据,采用触发器自动再向t_log表里加入一条数据
l 首先建立t_log表
|
create table t_log ( log_id number(10) primary key, log_time date ) |
l 为建立t_log的主键建立sequence
|
create sequence seq_log_id start with 1 increment by 1; |
l 建立触发器
|
create or replace trigger tri_test after/before insert/update/delete on new_emp begin insert into t_log(log_id, log_time) values(seq_log_id.nextval, sysdate); end; |
l 向new_emp表中加入数据
|
insert into new_emp(empno, deptno) values(7777, 10); |
在new_emp中多了一条数据empno为7777,在t_log中自动加入了一条数据,这就是触发器的作用。
2.24、游标
我们有时采用select会返回一个结果集,使用简单的select无法得到上一行,下一行,后5行,后10行,如果想做到这一点必须使用游标,游标是存储在数据库服务器上的一个数据库查询,它不是一条select语句,他是一个结果集,有了游标就可以根据需要滚动浏览数据了
下面通过一个示例,根据岗位加工资,如果是MANAGER增加20%的工资,如果是SALESMAN增加10%的工资,其他的增加5%的工资 ---delphi
|
create or replace procedure proc_sal is cursor c is select * from new_emp for update; begin for v_emp in c loop if (v_emp.job = 'MANAGER') then update new_emp set sal = sal + sal*0.2 where current of c; elsif (v_emp.job = 'SALESMAN') then update new_emp set sal = sal + sal*0.1 where current of c; else update new_emp set sal = sal + sal*0.05 where current of c; end if; end loop; commit;//事物的提交 end; |
执行存储过程
|
exec proc_sal; |
2.25、常用的DBA操作
2.25.1、查询用户拥有的数据库对象
|
select object_name from user_objects; |
2.25.2、查询约束信息
|
select constraint_name from user_constraints; |
2.25.3、查询用户拥有的表
|
select * from tab; 或 select table_name from user_tables; |
2.25.4、查询用户拥有的视图
|
select view_name from user_views; |
2.25.5、查询用户拥有的触发器
|
select trigger_name from user_triggers; |
2.25.6、查询用户拥有的序列
|
select sequence_name from user_sequences; |
2.25.7、查询用户拥有的存储过程
|
select object_name from user_procedures; |
2.25.8、查询用户拥有的索引
|
select index_name from user_indexes; |
2.25.9、显示当前用户
|
show user; |
2.25.10、切换用户
|
conn cms/cms |
2.25.11、以某种角色来登录
|
conn scott/tiger as sysdba; |
2.25.12、查看用户拥有的权限
|
select * from session_privs; |
常用权限
|
CREATE SESSION |
连接数据库 |
|
CREATE TABLE |
创建表 |
|
CREATE VIEW |
创建视图 |
|
CREATE SEQUENCE |
创建序列 |
|
CREATE PROCEDURE |
创建存储过程 |
|
CREATE TRIGGER |
创建触发器 |
|
CREATE INDEXTYPE |
创建索引 |
|
UNLIMITED TABLESPACE |
对表空间的使用 |
|
Grant resource ,sysdba to scott |
把以上所有资源都分配 |
2.25.13给用户加锁
|
alter user scott account lock; |
2.25.14给用户解
|
alter user scott account unlock; |
2.25.15、改用户的密码
|
alter user scott identified by tiger; |
2.25.16建立用户
|
create user test1(username) identified by test1(password); |
2.25.17删除用户
可以级联删除
|
drop user test1 cascade; |
2.25.18、给用户授权
|
grant create session,create table to test1; |
2.25.19、授予表空间users给用户
|
alter user test1 default tablespace users; |
2.25.20、给用户 授权表空间
|
grant UNLIMITED TABLESPACE to test1; |
2.25.21一个完整的过程,从创建用户、创建表空间、授权、建表
l 创建用户
create user test123 identified by test123;
l 创建表空间
create tablespace data001 datafile 'd:\data001.dbf' size 100m;
l 分配表空间给用户
alter user test123 default tablespace data001;
l 给用户授权
grant create session,create table, UNLIMITED TABLESPACE to test123;
l 以test123登录
conn test123/test123;
l 创建表。。。。
2.25.22、导入和导出命令imp(import)、exp(export)
EXPDAT.DMP
数据库的格式:dmp文件:备份数据库
2.26、数据库设计的三范式
2.26.1、第一范式
数据库表中不能出现重复记录,每个字段是原子性的不能再分
不符合第一范式的示例
|
学生编号 |
学生姓名 |
联系方式 |
|
1001 |
张三 |
zs@gmail.com,1369999999 |
|
1002 |
李四 |
ls@gmail.com,13999888777 |
|
1001 |
王五 |
ww@163.net, 13455566677 |
存在问题:
n 最后一条记录和第一条重复(不唯一,没有主键)
n 联系方式字段可以再分,不是原子性的
|
学生编号(pk |
学生姓名 |
|
联系电话 |
|
1001 |
张三 |
zs@gmail.com |
1369999999 |
|
1002 |
李四 |
ls@gmail.com |
13999888777 |
|
1003 |
王五 |
ww@163.net |
13455566677 |
关于第一范式,每一行必须唯一,也就是每个表必须有主键,这是我们数据库设计的最基本要求,主要通常采用数值型或定长字符串表示,关于列不可再分,应该根据具体的情况来决定。如联系方式,为了开发上的便利行可能就采用一个字段了。
2.26.2、第二范式
第二范式是建立在第一范式基础上的,另外要求所有非主键字段完全依赖主键,不能产生部分依赖
示例:
|
学生编号 |
学生姓名 |
教师编号 |
教师姓名 |
|
1001 |
张三 |
001 |
王老师 |
|
1002 |
李四 |
002 |
赵老师 |
|
1003 |
王五 |
001 |
王老师 |
|
1001 |
张三 |
002 |
赵老师 |
确定主键:
|
学生编号(PK) |
教师编号(PK) |
学生姓名 |
教师姓名 |
|
1001 |
001 |
张三 |
王老师 |
|
1002 |
002 |
李四 |
赵老师 |
|
1003 |
001 |
王五 |
王老师 |
|
1001 |
002 |
张三 |
赵老师 |
以上虽然确定了主键,但此表会出现大量的冗余,主要涉及到的冗余字段为“学生姓名”和“教师姓名”,出现冗余的原因在于,学生姓名部分依赖了主键的一个字段学生编号,而没有依赖教师编号,而教师姓名部门依赖了主键的一个字段教师编号,这就是第二范式部分依赖。
解决方案如下:
学生信息表
|
学生编号(PK) |
学生姓名 |
|
1001 |
张三 |
|
1002 |
李四 |
|
1003 |
王五 |
教师信息表
|
教师编号(PK) |
教师姓名 |
|
001 |
王老师 |
|
002 |
赵老师 |
教师和学生的关系表
|
学生编号(PK) |
教师编号(PK) |
|
1001 |
001 |
|
1002 |
002 |
|
1003 |
001 |
|
1001 |
002 |
如果一个表是单一主键,那么它就复合第二范式,部分依赖和主键有关系
2.26.3、第三范式
建立在第二范式基础上的,非主键字段不能传递依赖于主键字段。
|
学生编号(PK) |
学生姓名 |
班级编号 |
班级名称 |
|
1001 |
张三 |
01 |
一年一班 |
|
1002 |
李四 |
02 |
一年二班 |
|
1003 |
王五 |
03 |
一年三班 |
从上表可以看出,班级名称字段存在冗余,因为班级名称字段没有直接依赖于主键,班级名称字段依赖于班级编号,班级编号依赖于学生编号,那么这就是传递依赖,解决的办法是将冗余字段单独拿出来建立表,如:
学生信息表
|
学生编号(PK) |
学生姓名 |
班级编号 |
|
1001 |
张三 |
01 |
|
1002 |
李四 |
02 |
|
1003 |
王五 |
03 |
班级信息表
|
班级编号 |
班级名称 |
|
01 |
一年一班 |
|
02 |
一年二班 |
|
03 |
一年三班 |
2.26.3、三范式总结
第一范式:有主键,具有原子性,字段不可分割
第二范式:完全依赖,没有部分依赖
第三范式:没有传递依赖
数据库设计尽量遵循三范式,但是还是根据实际情况进行取舍,有时可能会那冗余换速度,最终用目的要满足客户需求。
3、练习
3.1、取得每个部门最高薪水的人员名称
1、取得每个部门的最高薪水
2、然后把结果当成一张表,再用emp和结果做关联
|
select a.ename, a.sal, a.deptno from emp a join (select deptno, max(sal) max_sal from emp group by deptno) b on (a.deptno=b.deptno and a.sal=b.max_sal) |
3.2、哪些人的薪水在部门的平均薪水之上
1、首先取得每个部门的平均薪水
2、然后把结果集当成一张表,再用emp和这张表做连接
|
select a.ename, a.sal from emp a join (select deptno, avg(sal) avg_sal from emp group by deptno) b on (a.deptno=b.deptno and a.sal > b.avg_sal); |
3.3、取得部门中(所有人的)平均的薪水等级,如下:
1、每个人的薪水等级
2、按部门分组取平均等级
|
select deptno, avg(grade) from (select a.ename, a.deptno, b.grade from emp a join salgrade b on (a.sal between b.losal and b.hisal)) group by deptno; |
3.4、不准用组函数(Max),取得最高薪水(给出两种解决方案)
第一种解决办法:
1、先把所有的薪水按降序排列
|
select sal from (select sal from emp order by sal desc) where rownum <=1; |
第二种解决办法:
1、 将emp作为两个表,进行比较,得出最大值以外的所有值
2、 然后采用not in
|
select sal from emp where sal not in( select distinct a.sal from emp a join emp b on (a.sal < b.sal) ) |
3.5、取得平均薪水最高的部门的部门编号(至少给出两种解决方案)
第一种解决办法:
1、 取得每个部门的平均薪水
2、 再取每个部门平均薪水的最大值
3、 然后平均薪水和平均薪水的最大值比较,得出部门编号
|
select deptno from (select deptno, avg(sal) avg_sal from emp group by deptno) where avg_sal =( select max(avg_sal) from (select deptno, avg(sal) avg_sal from emp group by deptno) ) |
第二种解决办法:
1、 取得平均薪水的最大值
2、 然后平均薪水和平均薪水的最大值比较,得出部门编号
|
select deptno from (select deptno, avg(sal) avg_sal from emp group by deptno) where avg_sal = ( select max(avg(sal)) from emp group by deptno ) |
第三种解决办法:
1、 先取得部门的平均薪水
a) select deptno, avg(sal) from emp group by deptno
2、 取得最高薪水
a) select max(avg(sal)) from emp group by deptno
3、 最后采用having子句做等值比较
|
select deptno, avg(sal) from emp group by deptno having avg(sal) = (select max(avg(sal)) from emp group by deptno) |
3.6、取得平均薪水最高的部门的部门名称
1、 取得部门平均最高薪水
a) select max(avg(sal)) from emp group by deptno)
2、 得到部门编号列表
a) select deptno from emp group by deptno
3、 采用having子句比较取得平均最高薪水的部门编号
|
(select deptno from emp group by deptno having avg(sal) = (select max(avg(sal)) from emp group by deptno) |
4、 得到部门名称
|
select dname from dept where deptno in (select deptno from emp group by deptno having avg(sal) = (select max(avg(sal)) from emp group by deptno)) |
3.7、求平均薪水的等级最低的部门的部门名称
1、 取得部门平均薪水等级
|
select deptno, avg_sal, grade from (select deptno, avg(sal) avg_sal from emp group by deptno) join salgrade on avg_sal between losal and hisal) |
2、 取得最低等级
|
select min(grade) from (select deptno, avg_sal, grade from (select deptno, avg(sal) avg_sal from emp group by deptno) join salgrade on avg_sal between losal and hisal) |
3、 在薪水等级集合中,取得最小薪水等级记录,与步骤二对比
4、 然后取得部门代码
5、 最后取得部门名称
|
select dname from dept where deptno in ( select deptno from ((select deptno, avg_sal, grade from (select deptno, avg(sal) avg_sal from emp group by deptno) join salgrade on avg_sal between losal and hisal) )where grade = (select min(grade) from (select deptno, avg_sal, grade from (select deptno, avg(sal) avg_sal from emp group by deptno) join salgrade on avg_sal between losal and hisal)) ) |
3.8、取得比普通员工的最高薪水还要高的经理人姓名
1、 先取得经理人
n select distinct mgr from emp where mgr is not null
2、 取得普通员工的坐高薪水
n (select max(sal) from emp where empno not in (select distinct mgr from emp where mgr is not null))
3、 取得经理人的薪水,与普通员工最高薪水对比
|
select ename, sal from emp where empno in (select distinct mgr from emp where mgr is not null) and sal >普通员工的最高薪水 |
|
select ename, sal from emp where empno in (select distinct mgr from emp where mgr is not null) and sal > (select max(sal) from emp where empno not in (select distinct mgr from emp where mgr is not null)) |
3.9、取得薪水最高的前五名员工
|
select rownum, ename,sal from (select ename, sal from emp order by sal desc) where rownum<=5; |
3.10、取得薪水最高的第六到第十名员工
|
select ename, sal from (select rownum r, ename,sal from (select ename,sal from emp order by sal desc) where rownum<=10) where r>=6; |
3.11、取得最后入职的5名员工
|
select ename,to_char(hiredate,'yyyy-mm-dd') from (select ename, hiredate from emp order by hiredate desc) where rownum <=5; |
3.12、取得每个薪水等级有多少员工
1、取得每个员工的薪水等级
2、更具薪水等级分组,取count
|
select grade, count(*) from (select ename,sal,grade from emp join salgrade on sal between losal and hisal) group by grade |
3.13、面试题
有3个表S,C,SC
S(SNO,SNAME)代表(学号,姓名)
C(CNO,CNAME,CTEACHER)代表(课号,课名,教师)
SC(SNO,CNO,SCGRADE)代表(学号,课号,成绩)
问题:
1,找出没选过“黎明”老师的所有学生姓名。
2,列出2门以上(含2门)不及格学生姓名及平均成绩。
3,即学过1号课程又学过2号课所有学生的姓名。
请用标准SQL语言写出答案,方言也行(请说明是使用什么方言)。
-----------------------------------------------------------------------------
CREATE TABLE SC
(
SNO VARCHAR2(200 BYTE),
CNO VARCHAR2(200 BYTE),
SCGRADE VARCHAR2(200 BYTE)
);
CREATE TABLE S
(
SNO VARCHAR2(200 BYTE),
SNAME VARCHAR2(200 BYTE)
);
CREATE TABLE C
(
CNO VARCHAR2(200 BYTE),
CNAME VARCHAR2(200 BYTE),
CTEACHER VARCHAR2(200 BYTE)
);
INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '1', '语文', '张');
INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '2', '政治', '王');
INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '3', '英语', '李');
INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '4', '数学', '赵');
INSERT INTO C ( CNO, CNAME, CTEACHER ) VALUES ( '5', '物理', '黎明');
commit;
INSERT INTO S ( SNO, SNAME ) VALUES ( '1', '学生1');
INSERT INTO S ( SNO, SNAME ) VALUES ( '2', '学生2');
INSERT INTO S ( SNO, SNAME ) VALUES ( '3', '学生3');
INSERT INTO S ( SNO, SNAME ) VALUES ( '4', '学生4');
commit;
INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '1', '1', '40');
INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '1', '2', '30');
INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '1', '3', '20');
INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '1', '4', '80');
INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '1', '5', '60');
INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '2', '1', '60');
INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '2', '2', '60');
INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '2', '3', '60');
INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '2', '4', '60');
INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '2', '5', '40');
INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '3', '1', '60');
INSERT INTO SC ( SNO, CNO, SCGRADE ) VALUES ( '3', '3', '80');
commit;
问题1.找出没选过“黎明”老师的所有学生姓名。
第一步:求黎明老师教的所有课的课号
select distinct cno from c where cteacher='黎明'
第二步:选了黎明老师的所有学生的编号
select sno from sc where cno in (
第一步的结果
)
第三步:没有选黎明老师的所有学生的姓名
select sname from s where sno not in (
第二步的结果
)
即:
|
select sname from s where sno not in ( select sno from sc where cno in ( select distinct cno from c where cteacher='黎明' ) ) |
问题2:列出2门以上(含2门)不及格学生姓名及平均成绩。
第一步:2门以上不及格的学生的学号
select sno from sc where scgrade < 60 group by sno having count(*) >= 2
第二步:每个学生平均分
select sno, avg(scgrade) as avg_grade from sc group by sno
第三步:第一步中得到的学号对应的学生姓名以及平均分
select s.sname ,avg_grade from s
join
第一步的结果
on s.sno = t.sno
join
第二步的结果
on s.sno = t1.sno
即:
select s.sname ,avg_grade from s
join
(select sno, count(*) from sc where scgrade < 60 group by sno having count(*) >= 2)t
on s.sno = t.sno
join
(select sno, avg(scgrade) as avg_grade from sc group by sno )t1
on s.sno = t1.sno
问题3:即学过1号课程又学过2号课所有学生的姓名。
第一步:学过1号课程的学号
select sno from sc where cno = 1
第二步:学过2号课程的学号
select sno from sc where cno = 2
第三步:即学过1号课程又学过2号课的学号
select sno from sc where cno =1 and sno in (select sno from sc where cno = 2)
第四步:得到姓名
select sname from s where sno in (
select sno from sc where cno = 1 and sno in (select sno from sc where cno = 2)
)
或者:
select sname from s where
sno in (select sno from sc where cno = 1)
and
sno in (select sno from sc where cno = 2)
PL/SQL工具的使用
- 连接方式:
2.打开左侧的下拉框:选择:My objects
- 右键的功能
- 导出:
文件的格式:.dmp和.sql
Dmp;
|
导出.sql文件 |
|
导出.dmp文件 |
导入:@ 文件路径
例如:@c:\cms.sql :导入sql中的数据
5.
SQL WINDOW菜单,主要是写sql语句或执行sql语句
6.导入:
Cd oracle的bin目录下:例如我的oracle安装路径:F:\oracle\product\10.1.0\db_1\BIN
Cd F:\oracle\product\10.1.0\db_1\BIN
导入dmp文件
imp cms/cms file=c:\cms.dmp full=y;
如果上面不可用,可用下面方式from表示来自哪个用户,to是要到哪个用户。
imp cms/cms file=c:\cms.dmp from scott to cms ;
|
Client |
|
Server |
导出dmp文件:
exp cms/cms file=d:\cms.dmp ;
7.本机oracle客户端如何连接服务器?
如果连不上的问题:关闭代理软件
1)打开oracle------------------》configuration and Migration Tools---------》
--------------》NET manager
修改服务命名标签中的:
主机名:写服务器的ip地址
监听程序:主机:写ip地址
点击文件中的save。
然后,PL/SQL工具来连接服务器数据库。
如果连接不上,重启服务器
1.打开方式如下:在运行中打入以下命令
services.msc
然后重启:oracle的service和LISTENER
2.修改一下服务名为服务器的sid名即可。
任务:
- 创建用户sinojava密码为:sinojava
- 授权给sinojava权限
- 拷贝scott用户中的数据表emp到sinojava用户下。
- 在sinojava用户下面,把表emp复制一份并命名为:new_emp
- 往new_emp表中插入1条数据。
- 导出此用户下的数据库及表的sql文件
SQLServer2005
Sever name:ip地址
Login:用户名
Pawword:密码
选择语句:shift+home或end
快捷键:F5执行sql键
创建数据库:create database cms;//create database 数据库名
打开数据库:use cms;或可用的所有的数据库下拉框选择
创建表
create table t_user (
id int not null primary key,
name varchar(20) not null,
sex char(2) not null,
mobile varchar(11)
);
Data types:
Int
Bigint:长整型
Char
Datetime
Decimal:十进制
Float
Money
Numeric
Samllint:短整型
Varchar:字符型的都可以使用
插入表:
insert into t_user
values(1,'tom','男','13439485642');
(1 row(s) affected)
删除表
delete from t_user where id=1;
修改表
update t_user set name='lucy' where id =2;
查询表
select * from t_user;
select id,name,sex,mobile from t_user;
配置sqlserver2005 服务
1, 开始>>程序>>Microsoft SQLServer2005 >>配置工具>>SQL Server Configurationo Manager
1..1启动图上服务
1.2 启动图上前三项
1.3 启动图上前三项
12Oracle Database SQL程序的更多相关文章
- go标准库的学习-database/sql
参考:https://studygolang.com/pkgdoc 导入方式: import "database/sql" sql包提供了保证SQL或类SQL数据库的泛用接口. 使 ...
- Go组件学习——database/sql数据库连接池你用对了吗
1.案例 case1: maxOpenConns > 1 func fewConns() { db, _ := db.Open("mysql", "root:roo ...
- 在Golang中如何正确地使用database/sql包访问数据库
本文记录了我在实际工作中关于数据库操作上一些小经验,也是新手入门golang时我认为一定会碰到问题,没有什么高大上的东西,所以希望能抛砖引玉,也算是对这个问题的一次总结. 其实我也是一个新手,机缘巧合 ...
- go database/sql sql-driver/mysql 操作
这里使用的是github.com/Go-SQL-Driver/MySQL, 所以需要下载一个github.com/Go-SQL-Driver/MySQL 引入 database/sql 和 githu ...
- Change the Target Recovery Time of a Database (SQL Server) 间接-checkpoints flushcache flushcache-message
Change the Target Recovery Time of a Database (SQL Server) 间接checkpoints flushcache flushcache-mes ...
- Oracle数据库之PL/SQL程序设计基础
PL/SQL程序设计基础 一.PL/SQL块结构 前边我们已经介绍了PL/SQL块的结构,再来回顾一下: DECLARE /* * 声明部分——定义常量.变量.复杂数据类型.游标.用户自定义异常 */ ...
- Database SQL script automation management tools investigation
Recently researched about database SQL scripts auto management tools, recorded the results here. Res ...
- go-mysql: database/sql 接口适配
go-mysql已经支持golang database/sql接口,并通过https://github.com/bradfitz/go-sql-test测试用例. 现在go-mysql可以直接通过go ...
- 【原创 Hadoop&Spark 动手实践 10】Spark SQL 程序设计基础与动手实践(下)
[原创 Hadoop&Spark 动手实践 10]Spark SQL 程序设计基础与动手实践(下) 目标: 1. 深入理解Spark SQL 程序设计的原理 2. 通过简单的命令来验证Spar ...
随机推荐
- Grails边做边学入门篇[1]--------大家一起来动手建立project和Domain
近期工作比較忙,没空写博客了.我发现每周五的下午都是我最放松的时候,可能是迟延症的缘故吧...总是寄希望于周末,慢慢的.我的周末就被工作占领了. 希望大家不要有这种坏毛病.今日事,今日毕.当然我们程序 ...
- 第一次PHP面试题
1.标记符title是放在标记符什么之间:head 2.级联样式表文件的扩展名:CSS 3.html中<pre>的作用:pre 元素可定义预格式化的文本 4.mysql_affected_ ...
- c# Java 微信红包算法
int total_money_cent = 1000; // 红包总金额 单位:分 int total_people = 8; // 抢红包总人数 int[] array = new int[tot ...
- JTabbedPane的LookAndFeel--TabbedPaneUI
在定制JTabbedPane的时候是需要使用到LookAndFeel的,而使用LookAndFeel定制的时候,其实主要是继承BasicTabbedPaneUI. to be continue...
- POJ 3100:Root of the Problem
Root of the Problem Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12060 Accepted: 6 ...
- sql加一个%号是什么意思
sql%notfound 是异常SQL%ROWCOUNT SQL语句执行影响的行数SQL%FOUND SQL语句是否成功执行SQL%NOTFOUND SQL语句是否成功执行SQL%ISOPEN 游标是 ...
- 一位ACMer过来人的心得(转)
刻苦的训练我打算最后稍微提一下.主要说后者:什么是有效地训练? 我想说下我的理解.很多ACMer入门的时候,都被告知:要多做题,做个500多道就变牛了.其实,这既不是充分条件.也不会是必要条件. 我觉 ...
- bzoj3262 陌上花开——CDQ分治
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3262 第一道CDQ分治题! 看博客:https://www.cnblogs.com/Narh ...
- IDEA hadoop MapReduce 环境配置
1.下载,安装,配置好Hadoop 2.在IDEA中执行MapReduc 配置: 这里将JAR包加入: JAR包是:/usr/local2/hadoop/share/hadoop 目录下:直接右边+以 ...
- Ruby实例方法和类方法的简写
创建: 2017/12/12 类方法 Sample.func 实例方法 Sample#func