JSP(一)

MIME

<%@page contentType="text/html"; charset=uft-8 %>

import
<%@page import=”java.sql.*, java.io.*,java.util.*”%>

 

数据库连接

<!%
public static final String DBDRIVER=”oracle.jdbc.driver.OracleDriver”;
public static final String DBURL=”jdbc :o racle:thin@localhost:1521 :x xxx”;
public static final String BDUSER=””;
public static final String BDPW=””;
%>

<%

Connection conn=null;

PreparedStatement pstmt=null;

ResultSet rs=null;

%>

<%

Class.forName(DBDRIVER);

conn= DriverManager.getConnection(DBURL,DBUSER,DBPW);

String sql=””;

pstmt=conn.prepareStatement(sql);

rs=pstmt.executeQuery();

%>

 

 

<%

rs.close();

pstmt.close();

conn.close();

%>

 

include

<jsp:include /> 或者<%@include file=””%>

包含页面, @include是静态包含, 只包含内容.
<jsp:include />是动态包含, 如果是jsp文件,则显示结果.如果不是如@include.

<jsp:include page=”” />

或者给包含页面传递参数
<jsp: include page=””>
<jsp: param name=“” value=”” />

</jsp: include>

被包含的页面通过<%=request.getParameter(“”)%>获得参数.

forward 无条件跳转, 服务器端跳转, 客户端的URL不变. 当然可以传参. 参数<%=val %>

<jsp:forward page=””/>

或者带参数

<jsp:forward page=””>

<jsp:param name=”“ vlaue=”“/>

</jsp:forward>

 

登录程式

1. 数据库脚本

DROP TABLE testUser;

CREATE TABLE testUser(
uid     NUMMBER     PRIMARY KEY NOT NULL,
username   VARCHAR2(10)   NOT NULL,
password  VARCHAR2(10)  NOT NULL
);
INSERT INTO testUser(uid,username,password) VALUES (xxx,'xxx','xxx');
commit;

2. login.jsp
<%@page contentType=”text/html; charset=utf-8”%>
<head>
<script language=”javaScript”>

function validation(f){
if(!(/^\w(5,15)$/.test(f.username.value))){
alert('the length of username must be between 5 und 15 characters');
f.username.focus();
return false;
}

if(!(/^\w(5,15)$/.test(f.password.value))){
alert('the length of password must be between 5 und 15 characters');
f.username.focus();
return false;
}
return true;
}

</script>
</head>
<body>
<form action=”check.jsp” methode=”post”onSubmit=”validation(this);”>
<table border=”0”>
<tr>
<td colspan =”2”> Login Here<td/>
</tr>

<tr>
<td> USER &nbsp;ID: </td>
<td><input type=”text” name=”username”></td>

</tr>
<tr>
<td>PASSWORD:</td>
<td><input type=”password” name=”password”></td>
</tr>
<tr colspan=”2”>
<td><input type=”submit” value=”submit”></td>
<td><input type=”reset” value=”reset”></td>
</tr>
</table>
</body>
3. check.jsp
<%@page import=”java.sql.*”%>

<%!
public static final String DBDRIVER = “orcale.jdbc.driver.OrcaleDriver”;
public static final String DBURL=”jdbc :o rcale:thin:@localhost:1521:XE”;
public static final String DBUSER=””;
public static final String  DBPASS=””;
%>

<%
Connection conn=null;
preparedStatement ps=null;
ResaultSet rs=null;
boolean loginFlag=false;
%>

<%
String username = request.getParameter(“username”);

String password= request.getParameter(“password”);
try{
Class.forName(DBDRIVER);
conn=DriverManager.getConnection(DBURL,DBUSER,DBPASS);
String sql= “SELECT username, password FROM testUSER WHERE username=? AND password=?”;
ps=conn.prepareStatement(sql);
ps.setString(1,username); //把username给sql中的第一个问号
ps.setString(2,password);
rs=ps.executeQuery();

if(rs.next()){
loginFlag= true;
}
}catch(Exception e){
}finally{
try{
conn.close();
}catch(Exception e){}
}
%>

<%
if(loginFlag){
%>
<jsp:forward page=”success.jsp”/>

<%
}else{
%>
<jsp:forward page=”failure.jsp”/>
<%
}
%>
4. success.jsp
<%@page contentType=”text/html; charset=utf-8”%>
<h1>welcome</>
5. failure.jsp
<%@page contentType=”text/html;charset=utf-8”%>
<h1>failure, <a href=”login.jsp”>turn back</a></h1>

内置对象.

在使用内置对象时, 不需要通过构造方法实例化就能使用.

No. Objekt Type
1 pageContext javax.servlet.jsp.PageContext
2 request javax.servlet.http.HttpServletRequest
3 response javax.servlet.http.HttpServletResponse
4 session javax.servlet.http.HttpSession
5 application javax.servlet.ServletContext
6 config javax.servlet.ServletConfig

 

1. page

不能跳转

但在 pageContext.setAttribute(name, value, pageContext.REQUEST_SCOPE);

来改变属性的范围. pageContext.REQUEST_SCOPE; pageContext.SESSION_SCOPE;

pageContext.APPLICATION_SCOPE, 默认不写为pageContext.

 

 

2.request

可以forward, 但是不能通过link跳转. 在服务器端可以多次跳转.

request.setCharacterEncoding(“utf-8”);转码

如果是复选框传参, 需要使用public String[] getParameterValues(String name);
String.startsWith(String str, int offset) 布尔函数. 用于判断字符串开头匹配

String getRemoteAddr(); 取得客户端ip.

3.session

只针对一个用户, 无跳转限制

4. application

所有用户.

 

5. response 服务器端的回应.

No. Methods Desc
1 setHeader(String name, String value) 设置http头信息名字和内容
2 sendRedirect(String location) throws IOException 跳转页面
3 addCookie(Cookie cookie) 向客户端加入Cookie
4 setContentType(String type) 设置内容返回类型MIME

 

例子:取得头信息

<%@ page contentType=”text/html; charset=utf-8”%>

<%@ page import = “java.util.*”%>
<%
Enumeration enu= request.getHeaderNames();
while(enu.hasMoreElements()){
String name=(String)enu.nextElement();
%>
<%=name%> –> <%=request.getHeader(name)%>
<%
}
%>

应用: 定时刷新或者定时跳转, 使用”refresh”关键字

<%@ page contentType=”text/html; charset=utf-8”%>
<%
response.setHeader(“refresh”, “2;URL=xxx.jsp”);
%>
以上代码表示2秒跳转到xxx.jsp. 如果是

response.setHeader(“refresh”, “2”); 则表示定时刷新本页面.
不过如果是静态页,可以直接在页面头信息写入
<META HTTP-EQUIV=”refresh” CONTENT=”2;URL=xxx.jsp”>
以上两种方法等价, 后者更快. 都属于客户端跳转.

如果想要累加刷新. 那么 变量就要是静态变量. 比如用<%! %>声明

跳转指令(客户端跳转)
response.sendRedirect(“xxx.jsp”);

这种跳转会在页面内容执行后才会执行. 而forward属于无条件跳转, 只要执行到,就立即跳转. 所以使用jdbc时, conn.close()一定要在forward之前. 而对于sendRedirect则无所谓.

Cookie的使用

Cookie是指服务器存储在客户端的一些信息. 通过http头信息传递. 如要设置Cookie就要使用

<%@ page contentType=”text/html; charset=utf-8”%>
<%
Cookie c1 = new Cookie(“username”,”LDS”);
Cookie c2 = new Cookie(“password”,”LDS”);
response.addCookie(c1);
response.addCookie(c2);

c1.setMaxAge(20); //设置Cookie存活时间, 默认只存在浏览器打开时
c2.setMaxAge(50);
%>

如果要想取得Cookie, 则要使用request中的 public Cookie[] getCookies();

<%@ page contentType=”text/html; charset=utf-8”%>
<%
Cookie c[] = request.getCookies();
for(int i=0; i<c.length; i++){ 
%>
<%=c[i].getName()%>-----><%=c[i].getValue()%>
<%
}
%>

Posted in jsp, 编程学习 | Tagged | Leave a comment

修复磁盘

DOS下运行

chkdsk H: /X

Posted in 未分类 | Tagged , | Leave a comment

Oracle(10) 一般只有数据库工程师才会接触这部分

嵌套表nest

  1. 先定义类型

CREATE TYPE project_ty AS OBJECT(
            proid          NUMBER(10),
            proname        VARCHAR2(20),
            prodate        DATE
);
/

最后回车加”/”是必不可少的.

  2.  然后为上面的对象创建表名称

CREATE TYPE project_nt AS TABLE OF project_ty;

/

3. 定义创建嵌套表, 使用的是内表的名称, 而非类型

CREATE TABLE department (

deptno    NUMBER(2)       PRIMARY KEY NOT NULL,

dname     VARCHAR2(20)                      NOT NULL,

projects    project_nt

) NESTED TABLE projects STORE AS project_nt_table_temp;

 

4.插入数据.

INSERT INTO department (deptnom dname, projects) VALUES (1,'技术部',

project_nt(

project_ty(1001,'ERP', SYSDATE) ,

project_ty(1002,'CRM', SYSDATE),

project_ty(1002,'SAP', SYSDATE)

)

);                     

5.查询

  • 普通查询会将表当的全部数据查出
  • 只查内表:
    • SELECT * FROM TABLE( SELECT projects FROM department WHERE deptno=1);

6. 更新

UPDATE TABLE (SELECT projects FROM department WHERE deptno=1) pro SET  VALUE(pro)=project_ty('1001', 'TEST', to_date('1999-12-02','yyyy-mm-dd')) WHERE pro.proid=1001;

 

可变数组

嵌套表的升级版…

1.定义worker_info的类型

CREATE TYPE work_info(

);

/

2.定义worker_info的数组

CREATE TYPE worker_info_list AS VARRAY(10) OF work_info;

/

3.定义创建表.

4.插入测试数据

5.查询操作

 

数据库设计范式

实际开发中, 不会真的按照范式去做.

Posted in Oracle, 编程学习 | Tagged , | Leave a comment

Oracle(9)

用户管理(DBA)

创建用户语法: 首先使用管理员登录. 也就是system或者sys

CREATE USER 用户名 IDENTIFIED BY 密码;

  • create user test identified by test; 
  • --会提示 user TEST lacks CREATE SESSION privilege; logon denied
  • --所以必须授权grant…to

授权语法:

GRANT 权限名称|角色名称 TO 用户;

  • grant create session to test;

对于一个新的用户, 要分别授权其权限. 这样比较麻烦, 所以oracle中定义了若干组不同权限集合,也就是role角色.

  • grant connect, resource to test;

回收语法:

REVOKE 权限名称 FROM 用户名;

修改用户密码:

ALTER USER 用户名 IDENTIFIED BY 密码;

如果想用户第一次登陆时, 可以自己更改默认密码. 则使用:

ALTER USER 用户名 PASSWORD EXPIRE;

锁住或者解锁一个用户

ALTER USER 用户名 ACCOUNT LOCK|UNLOCK;

  • alter user test account lock;
  • alter user test account unlock;

授予和回收访问其他用户的操作的权限

GRANT SELECT, DELETE ON 用户名.表名 TO 用户名;

  • grant select, delete on scott.emp to test;

REVOKE SELECT, DELETE FROM 用户名.表名 FROM 用户名;

  • revoke select, delete from scott.emp from test;

数据库的备份和恢复

为了防止系统崩溃.  在Oracle安装完后可使用这两个命令.

  • 数据库备份(导出)> exp
  • 数据库导入> imp

例子: 在c盘建立一个文件夹 data, 然后进入cmd.  输入 exp, 然后按流程走. 就ok.

然后使用imp命令导入,恢复. 必须在备份文件所在文件夹.

Posted in Oracle, 编程学习 | Tagged | Leave a comment

Oracle(8)

视图 Sicht

就是封装了一个复杂的查询.

 

创建视图

CRAEATE VIEW 视图名 AS 子查询;

  • CREATE VIEW empv20 AS select empno, ename, job, hiredate from emp where deptno=20;
  • select * from empv20;

如果要修改视图的查询字段.. 因为视图无法重名. 所以要先删除原视图. 再重新建立

删除视图

DROP VIEW 视图名;

  • drop view empv20;

但如果这样做, 很繁琐. 所以在Oracle中提供了替换命令

建立视图(ORACLE)

CREATE OR REPLACE VIEW 视图名 AS 子查询

WITH CHECK OPTION / WITH READ ONLY ;

  • CREATE OR REPLACE VIEW empv20 AS select * from emp where deptno=30;

在系统开发中, 复杂的查询往往要建立视图, 来供用户查询操作. 以后直接查询视图, 就可以得到相同的结果.

 

在视图中是不包含真实数据的. 创建的视图是存在创建条件.

  • CREATE OR REPLACE VIEW empv20 AS select * from emp where deptno=20; 这个创建条件是deptno=20; 如果将视图中的一个记录修改其deptno.
  • UPDATE empv20 SET deptno=30 WHERE empno=7369; 此时视图中改变, 但实际的emp表中7369的部门编号也会被修改. 这就违反了创建条件. 相悖.
  • 所以在创建视图时, 在最后追加使用 WITH CHECK OPTION, 这样创建条件则不能被修改. 但其他条件可改.
  • 追加WITH READ ONLY 这样视图就不可被修改.

 

序列(SEQUENCE)

完成自动增长功能. 需要用户手工处理.

创建格式:

CREATE SEQUENCE sequencename

[INCREMENT BY n]  --每次增长幅度

[START WITH n] --序列开始位置

[MAXVALUE n | NOMAXVALUE]

[MINVALUE n | NOMINVALUE]

[CYCLE| NOCYCLE]

[CACHE n| NOCACHE];

删除格式:

DROP SEQUENCE sequencename ;

 

序列创建完后, 所有的自动增长应该由用户自己处理. 系统提供两种操作.

  1. nextVal 取得序列下一个内容;
  2. currVal 取得序列当前内容;
  • CREATE SEQUENCE myseq;--建序列
  • CREATE TABLE tesseq (next NUMBER, curr NUMBER);--建表
  • INSERT INTO tesseq (next,curr) VALUES (myseq.nextval,myseq.currval); --插入数据,手工设置序列
  • 执行插入数据5次.

 

  • CREATE SEQUENCE myseq1 INCREMENT BY 2 START WITH 10 MAXVALUE 10 CYCLE NOCACHE;

同义词 (synonyms):  ORCALE 特有.

  • select sysdate form DUAL;
  • DUAL是一张虚拟表.  此表在sys用户中. 但是其他用户也可以直接通过DUAL访问, 也就是直接通过表名称访问, 而不是用完整名称sys.DUAL. 这就是因为使用了synonyms

创建:

CREATE SYNONYM 同义词名称 FOR 用户名.表名称;

  • create synonym emp for scott.emp;

删除:

DROP SYNONYM 同义词名称;

  • drop synonym emp;
Posted in Oracle, 编程学习 | Tagged , | Leave a comment

Oracle(7)

综合练习:

题目: 学生运动会比赛信息

三张表如下

  • sporter(sportid, name, sex, department)
  • item(itemid,itemname,location)
  • grade(sportid,itemid,mark)

要求:

1. 建表

  • 定义各各表的约束, 运动员的姓名和系别不能为空.
  • 积分要么为空值,要么为6,4,2,0. 分别代表第一,二,三以及其他名次积分

脚本如下

DROP TABLE grade;

DROP TABLE sporter;

DROP TABLE item;

CREATE TABLE sporter (
    sporterid       NUMBER(4)   PRIMARY KEY       NOT NULL,
    name            VARCHAR2( 8)                            NOT NULL,
    sex               VARCHAR2(6) DEFAULT 'male'   NOT NULL,
    department  VARCHAR2( 8)                             NOT NULL,
    CONSTRAINT sporter_sex_ck CHECK(sex IN ('male','female'))
);

--测试数据

INSERT INTO sporter(sporterid,name,sex,department) VALUES (1001,'李晓友','male','INFO');

INSERT INTO sporter(sporterid,name,sex,department) VALUES (1002,'李云东','male','MATH');

INSERT INTO sporter(sporterid,name,sex,department) VALUES (1003,'王洋','male','PHY');

INSERT INTO sporter(sporterid,name,sex,department) VALUES (1004,'柳达深','male','INFO');

INSERT INTO sporter(sporterid,name,sex,department) VALUES (1005,'刘小曼','female','AUTO');

INSERT INTO sporter(sporterid,name,sex,department) VALUES (1006,'欧阳笑笑','female','LAN');

CREATE TABLE item (itemid VARCHAR2(4) NOT NULL , itemname VARCHAR2(10) NOT NULL, location VARCHAR2(10) NOT NULL, CONSTRAINT item_itemid_pk PRIMARY KEY(itemid), CONSTRAINT item_itemname_uk UNIQUE(itemname));

--测试数据

INSERT INTO item(itemid, itemname, location) VALUES('x001','男子五千米','一操场');

INSERT INTO item(itemid, itemname, location) VALUES('x002','男子标枪','一操场');

INSERT INTO item(itemid, itemname, location) VALUES('x003','男子跳远','二操场');

INSERT INTO item(itemid, itemname, location) VALUES('x004','女子跳高','二操场');

INSERT INTO item(itemid, itemname, location) VALUES('x005','女子三千米','三操场');

 

CREATE TABLE grade (sporterid NUMBER(4), itemid VARCHAR2(4), mark NUMBER(1), CONSTRAINT sporter_grade_sporterid_fk FOREIGN KEY(sporterid) REFERENCES sporter(sporterid) ON DELETE CASCADE, CONSTRAINT item_grade_itemid_fk FOREIGN KEY(itemid) REFERENCES item(itemid) ON DELETE CASCADE, CONSTRAINT grade_mark_ck CHECK (mark IN (6,4,2,0)));

INSERT INTO grade (sporterid,itemid,mark) VALUES (1001,'x001',6);

INSERT INTO grade (sporterid,itemid,mark) VALUES (1002,'x001',4);

INSERT INTO grade (sporterid,itemid,mark) VALUES (1003,'x001',2);

INSERT INTO grade (sporterid,itemid,mark) VALUES (1004,'x001',0);

INSERT INTO grade (sporterid,itemid,mark) VALUES (1001,'x003',4);

INSERT INTO grade (sporterid,itemid,mark) VALUES (1002,'x003',6);

INSERT INTO grade (sporterid,itemid,mark) VALUES (1004,'x003',2);

INSERT INTO grade (sporterid,itemid,mark) VALUES (1005,'x004',6);

INSERT INTO grade (sporterid,itemid,mark) VALUES (1006,'x004',4);

2. 查询:

  • 当前最高积分的系名以及其积分
  • select rownum, temp.* from (select s.department depart, SUM(g.mark) sum from sporter s, grade g where s.sporterid=g.sporterid group by s.department order by sum desc) temp where rownum=1; --利用rownum
  • 找出一操场项目的名称和每个项目的最高成绩,以及其人员名称
  • select * from (select i.location, i.itemname,s.name,g.mark  from item i, grade g, sporter s where i.location='一操场' AND i.itemid=g.itemid AND s.sporterid=g.sporterid ORDER by g.mark desc) where rownum=1;
  • 超出李晓友参加过项目的人员
  • select DISTINCT s.name from sporter s, grade g WHERE s.sporterid=g.sporterid AND g.itemid IN (select g.itemid from sporter s, grade g WHERE s.sporterid=g.sporterid  AND s.name='李晓友');
  • 王洋因为吃了大力丸,所以成绩无效. 修改相应成绩.
  • UPDATE grade SET mark=0 WHERE sporterid = (select sporterid from sporter where name='王洋');
  • 经组委会协商,因为安全原因.取消女子跳高项目.
  • DELETE FROM item WHERE itemname='女子跳高';

 

集合操作

UNION, INTERSECT, MINUS

  • UNION: 将多个查询结果组合到一个查询结果. 无重复
  • UNION ALL:  如上, 当允许重复
  • INTERSECT: 返回多个查询的相同部分
  • MINUS: 返回多个查询的差

CREATE TABLE emp20 AS SELECT * FROM emp WHERE deptno=20;

  • UNION:     select * from emp UNION select * from emp20;
  • UNION ALL: select * from emp UNION ALL select * from emp20;
  • INTERSECT: select * from emp INTERSECT select * from emp20;
  • MINUS: select * from emp MINUS select * from emp20;

集合操作符不适用于LOB、VARRAY和嵌套表列,必须确保不同查询的列个数和数据类型匹配.

order  by 必须放在最后一条select 语句之后,当列名相同时,可以直接用列名排序,如果不同可以用位置排序,也可以使用别名使其相同

select  id, name  x from new_emp
union all
select  empno, ename  x from emp order by x;

Posted in Oracle, 编程学习 | Tagged | Leave a comment

Oracle(6)

 

约束 (Ristriktion,constraint)

例子> 一个杯赛的对阵表

  • create table national(name VARCHAR2(30));
  • --增加测试数据
  • insert into national (name) values ('CHINA');
  • insert into national (name) values ('USA');
  • insert into national (name) values ('Holland');
  • insert into national (name) values ('Brazil');

“--“在Oracle脚本里表示注释

  • select t1.name, t2.name from national t1, national t2 where t1.name!=t2.name;

在数据库开发中, Ristriktion是必不可少的支持, 它可以保证数据库数据的完整性.

在实际中Ristriktion分为以下5种:

  1. 主键约束: 主键表示一个唯一的标识, 且不为空;
  2. 唯一约束: 一个表中, 只能有一个主键约束, 而其他列不希望出现重复值, 则使用唯一约束;
  3. 检查约束: 检查一个内容是否合法,例如性别只可能有3种;
  4. 非空约束: 比如姓名这样的字段内容不能为空;
  5. 外键约束: 在多张表中的约束操作

 

1.主键约束(Primary KEy)

在建表的时候设置. 比如

create table person ( pid VARCHAR2(9) Primary Key , name VARCHAR2(20), age NUMBER(3), birthday DATE, sex VARCHAR2(6) DEFAULT 'male'); --此处, DEFAULT标识要放在其他表示前

唯一约束和非空约束:

INSERT INTO person (pid,name,age,birthday,sex) VALUES('11111111', '令狐笑笑',30,to_date('1979/1/3','fmyyyy/mm/dd'),'female');

INSERT INTO person (pid,name,age,birthday,sex) VALUES('11111111', '令狐小胖',30,to_date('1979/1/3','fmyyyy/mm/dd'),'female'); 违反唯一约束

INSERT INTO person (pid,name,age,birthday,sex) VALUES(null, '令狐笑笑',30,to_date('1979/1/3','fmyyyy/mm/dd'),'female'); 违反非空约束

自定义主键constraint约束.

create table person ( pid VARCHAR2(9), name VARCHAR2(20), age NUMBER(3), birthday DATE, sex VARCHAR2(6) DEFAULT 'male',CONSTRAINT person_pid_pk PRIMARY KEY(pid));

其中person_pid_pk 是指定的主键约束.

 

2.非空约束(NOT NULL)  无自定义CONSTRAINT,直接在定义处后面标识

create table person ( pid VARCHAR2(9), name VARCHAR2(20)  NOT NULL, age NUMBER(3), birthday DATE, sex VARCHAR2(6) DEFAULT 'male',CONSTRAINT person_pid_pk PRIMARY KEY(pid));

3. 唯一约束 (UNIQUE)

create table person ( pid VARCHAR2(9), name VARCHAR2(20) UNIQUE NOT NULL, age NUMBER(3), birthday DATE, sex VARCHAR2(6) DEFAULT 'male',CONSTRAINT person_pid_pk PRIMARY KEY(pid));

自定义唯一约束

create table person ( pid VARCHAR2(9), name VARCHAR2(20) NOT NULL, age NUMBER(3), birthday DATE, sex VARCHAR2(6) DEFAULT 'male',CONSTRAINT person_pid_pk PRIMARY KEY(pid), CONSTRAINT person_name_uk UNIQUE(name));

4. 检查约束(CHECK)

create table person (pid VARCHAR2(9), name VARCHAR2(20) UNIQUE NOT NULL, age NUMBER(3) , birthday DATE, sex VARCHAR2(6) DEFAULT 'male',  CONSTRAINT person_pid_pk PRIMARY KEY(pid), CONSTRAINT person_age_ck CHECK(age BETWEEN 0 AND 150), CONSTRAINT person_sex_ck CHECK(sex in('male','female')));

 

5. 外键约束

多表情况, 关联后子表的数据要跟随主表变化. 保持两张表的数据完整性.

create table book (bid NUMBER, bname VARCHAR2(20) NOT NULL, bprice NUMBER(5,2), pid VARCHAR2(9), CONSTRAINT book_bid_pk PRIMARY KEY(bid), CONSTRAINT book_pid_fk FOREIGN KEY(pid) REFERENCES person(pid) ON DELETE CASCADE);

INSERT INTO book (bid,bname,bprice,pid) VALUES (1,'JAVAEE', 78.49,'11111111');

-- 错误:违反唯一约束条件 (SCOTT.BOOK_BID_PK)

INSERT INTO book (bid,bname,bprice,pid) VALUES (1,'JAVAEE', 78.49,'11111112');

  • 在子表中设置的外键,在主表中必须是主键.
  • 删除中,需要先删除子表. 再删除主表。但也可以使用 CASCADE CONSTRAINT参数强行删除主表.

--错误: 表中的唯一/主键被外键引用

删除表

drop table book; drop table person;

但可以使用强制性删除.  DROP TABLE person CASCADE CONSTRAINT; 但不推荐.

删除记录

delete from person where pid='11111111';

--错误:违反完整约束条件 (SCOTT.BOOK_PID_FK) - 已找到子记录

所以希望一个表中删除记录时, 想同时自动删除其关联的子表记录. 则要在创建子表时, 在FOREIGN KEY约束声明时添加 ON DELETE CASCADE属性. 

 

修改约束

1.增加约束

如果一张表已经建立, 可以为其添加约束. 但是NOT NULL不能加. 必须建表时候就写好.

格式: ALTER TABLE 表名 ADD CONSTRAINT 约束名称 约束类型;

2.删除约束

格式: ALTER TABLE 表名 DROP CONSTRAINT 约束名称;

 

ROWNUM

表示行号, 实际上此是一个列, 但是这是个伪列. 此列可以在每张表中出现. 从1开始.

  • select rownum, empno, ename from emp where rownum<=5; --前5条记录
  • 如果想要进行中间的截取操作, 只能使用子查询.
    • select rownum rn from emp where rownum<=10;
    • select temp.rn from (select rownum rn from emp where rownum<=10) temp where temp.rn between 5 and 10; --查询5到10之间的记录
    • select ed.* from(select rownum rn, e.* from emp e) ed where ed.rn>= (select count(*) from emp)-4 ; --最后5条记录
Posted in Oracle, 编程学习 | Tagged , | Leave a comment

Oracle (5)

常用数据类型

No. 数据类型 描述
1 VARCHAR 表示字符串, 255长度
2 NUMBER NUMBER(n):表示一个整数,也可以为INT;
NUMBER(m,n):表示小数. 也可以使用FLOAT;
3 DATE 表示日期. 按标准日期格式存放.
4 CLOB 大对象, 表示大的文本数据.可以存放4G的文本
5 BLOB 大对象,表示二进制数据,可以存放最大4G, 比如电影,图片
     

 

建立表

CREATE TABLE 表名称(

字段名1 字段类型 [DEFAULT 默认值]

字段名2 字段类型

);

复制表

CREATE TABLE 表名称 AS (子查询);

如果子查询中的查询条件是一个无效的条件, 这表示只复制表的结构, 而不复制表的内容.

  • create table test as (select * from dept where 1=2);

建立如下表格person.

No. 字段名称 字段类型 描述
1 pid VARCHAR2(1 8) 身份号码
2 name VARCHAR2(20) 姓名
3 age NUMBER(3) 年龄
4 birthday DATE 生日
5 sex VARCHAR2(6) 性别, 默认male.
  • create table person ( pid VARCHAR2( 8) , name VARCHAR2(20), age NUMBER(3), birthday DATE, sex VARCHAR2(6) DEFAULT 'male');
  • INSERT INTO person (pid,name,age,birthday,sex) VALUES('11111111', '令狐笑笑',30,to_date('1979/1/3','fmyyyy/mm/dd'),'female');
  • INSERT INTO person (pid,name,age,birthday) VALUES('22222222', '小胖',20,to_date('1989/11/3','fmyyyy/mm/dd'));

如果想要增加字段, 方法可如下(实际开发中, 是强烈不推荐使用ALTER TABLE):

  1. 笨办法, 删除原表, 重新编写新的脚本; (不推荐)
  2. 新增和修改表结构的语法.
    • ALTER TABLE 表名 ADD (新字段 字段类型 DEFAULT 默认值)指令增加列.
    • ALTER TABLE person ADD (address VARCHAR(20) DEFAULT 'N/A');
  3. ALTER TABLE 表名 MODIFY (新字段 字段类型 DEFAULT 默认值)修改
    • ALTER TABLE person MODIFY (name VARCHAR(1 8) DEFAULT 'N/A');
    • 如果修改字段中已经有数据, 但是这个数据不符合修改类型, 则会失败.
  4. INSERT INTO person (pid,age,birthday) VALUES('333333', 27,to_date('1981/11/3','fmyyyy/mm/dd'));

数据库脚本(删除表dorp table, 创建表create table, 插入数据insert into …values…)

重命名表 (only in oracle)

RENAME命令

RENAME 旧表 TO 新表;

  • rename person to tperson;

截断表 (only in oracle)

TRUNCATE TABLE 表名; 表示清空表数据,而且无回滚需求. 也就是说表的资源立即被释放,不可恢复

 

删除表

DROP TABLE 表名称

Posted in Oracle, 编程学习 | Tagged , , , , | Leave a comment

Oracle(4)

数据库更新操作

在进行更新操作前, 也就是insert , update, delete

一般要执行备份操作. 也就是复制一下原表.

备份

CREATE TABLE myemp AS SELECT * FROM emp;

添加数据

INSERT INTO myemp (字段名称1, 字段名称2,…) VALUES (值1, 值2,…); 标准模式

  • INSERT INTO myemp(empno, ename, job,mgr,hiredate,sal,comm,deptno) VALUES (7899, '张三','清洁工',7369,'17-12月-1995', 8000,300,40);

简略写法 (不推荐)

  • 只要数据和字段名称相对应. 那么就不需要写字段名称. 直接写VALUES
    • INSERT INTO myemp VALUES (8899, '李四','清洁工',7369,'17-12月-1995', 8000,300,40);

如果要添加的记录中有不明确的值, 那么那一项的字段名称也不要写.  或者缩略写法, 用null

  • INSERT INTO myemp(empno, ename, job,hiredate,sal,deptno) VALUES (7899, '王五','清洁工','17-12月-1995', 8000,40);
  • INSERT INTO myemp VALUES (9899, '李四','清洁工',null,'17-12月-1995', 8000,null,40);

格式变化 to_date();

  • INSERT INTO myemp(empno, ename, job,hiredate,sal,deptno) VALUES (8888, '王五','清洁工',to_date('1781-12-3','fmyyyy-mm-dd'), 8000,40);

修改内容

  1. UPDATE myemp SET 修改的字段1=新值1, 修改的字段2=新值2, …; (全部修改).慎用!
  • UPDATE myemp SET comm= 1000;

   2.   UPDATE myemp SET 修改的字段1=新值1, 修改的字段2=新值2, … WHERE 修改条件 (修改局部)

  • UPDATE myemp SET sal= 50000 where empno= 7899;
  • UPDATE myemp SET mgr= null where empno= 7899;
  • UPDATE myemp SET mgr =null, comm=null where empno IN(7369,8899,778 8) ;

删除数据 (不是删除表格, 删除表格为 DROP TABLE )

DELETE FROM 表名称; (开发中, 禁止使用)

DELETE FROM 表名称 WHERE 删除条件;

  • DELETE FROM myemp where empno IN(7369,8899,778 8) ;

事务处理

CREATE TABLE emp10 AS SELECT * FROM emp WHERE deptno=10;

DELETE FROM emp10 WHERE empno= 7782;

然后再开一个sqlplusw. 结果empno没有变化. 这就是所谓的事务处理.

所谓的事务处理, 就是保证数据操作的完整性. 要么同时成功, 要么同时失败. 在Orcale后每一个数据库窗口在连接后实际上就是一个session. 一个session对数据库所做的修改, 不会立即在数据库真实数据上修改. 是允许回滚的. 只有在session完成所有操作后. 提交事务了. 才会在真实数据上操作.

  • 回滚事务: ROLLBACK;
  • 提交事务: COMMIT;

死锁概念, 也就由此产生.

一个session如果更新了数据库中的记录, 其他session是无法立刻更新的. 要等待对方提交之后才允许更新

 

前期内容例子总结:

  • select d.*, ed.count from dept d, (select deptno, count(empno) count from emp group by deptno HAVING COUNT(empno)>1) ed where d.deptno=ed.deptno; 列出部门人数大于1的部门信息
  • select * from emp where sal> (select sal from emp where ename=UPPER('smith'));  列出薪金比smith多的员工
  • select e.ename name, m.ename bossname from emp e, emp m where e.mgr=m.empno(+); 列出员工和其上司名字.
  • select e.empno, e.ename, d.dname from emp e, dept d, emp m where e.mgr=m.empno AND e.hiredate<m.hiredate AND e.deptno=d.deptno; 入职日期比其上司早的员工和其部门
  • select d.dname, e.* from dept d, emp e where e.deptno(+)=d.deptno; 列出所有部门名称和其员工.
  • select e.ename, e.job, d.dname, ed.cou FROM emp e, dept d, (select deptno, count(empno) cou from emp group by deptno) ed WHERE job='CLERK' AND e.deptno=d.deptno AND e.deptno=ed.deptno; 查出职位是clerk的员工名字, 部门名称和部门人数.
  • select e.job, COUNT(e.empno) from emp e where e.job IN (select job from emp group by job HAVING MIN(sal)>1500) group by e.job; 列出最低薪金大于1500的工作已经该工作的人数.
  • select ename from emp  where deptno=(select deptno from dept where dname=UPPER('sales')); 列出sales部门的员工姓名
  • select e.ename,e.job,e.empno, e.sal, d.*, m.ename bossname, s.grade from emp e, emp m, dept d, salgrade s where e.sal>(select avg(sal) from emp) AND e.mgr=m.empno(+) AND e.deptno = d.deptno AND e.sal BETWEEN s.losal AND s.hisal; 找出薪金大于平均薪金的员工,其部门信息,上司以及薪金等级
Posted in Oracle, 编程学习 | Tagged , | Leave a comment

Oracle(3)

多表查询
(select count(*) from emp; 来得出emp表中的记录数)

  • select * from emp, dept;  这样直接查询多表, 会产生笛卡尔积. 想要去掉笛卡尔积. 就要使用字段关联.  加入where. 
    • select * from emp,dept where emp.deptno=dept.deptno;
    • 在开发中, 如果多表查询. 最好制定别名. 增加阅读性.
  • 一个表自己与自己自身关联.
    • select e.ename emp, e.job job, m.ename boss, d.dname dep from emp e, emp m, dept d where e.mgr=m.empno(+) AND e.deptno=d.deptno ORDER BY dep, job;
  • 若干例子>
    • 1. 雇员名字,工资,部门名称,工资等级,及其领佳节又重阳导名字,和工资的等级
      • SELECT e.ename, e.sal, d.dname, s.grade, m.ename, ms.grade FROM emp e, dept d, salgrade s, emp m, salgrade ms WHERE e.deptno=d.deptno AND e.sal BETWEEN s.losal AND s.hisal AND e.mgr=m.empno AND m.sal BETWEEN ms.losal AND ms.hisal ; 要分解的求出最后结果.
      • 并且按照一定格式显示工资等级. 也就是使用decode()函数. SELECT e.ename, e.sal, d.dname, DECODE(s.grade,1,'第五等',2,'第四等',3,'第三等',4,'第二等',5,'第一等') salgrade , m.ename, DECODE(ms.grade,1,'第五等',2,'第四等',3,'第三等',4,'第二等',5,'第一等') salgrade FROM emp e, dept d, salgrade s, emp m, salgrade ms WHERE e.deptno=d.deptno AND e.sal BETWEEN s.losal AND s.hisal AND e.mgr=m.empno AND m.sal BETWEEN ms.losal AND ms.hisal ;

左右联接

  • 消除笛卡尔积的时候可能会消除一些没有符合关联的记录. 使用(+)放在相反的一边, 变成右或左联接.  SELECT e.empno, e.ename, d.deptno, d.dname, d.loc FROM emp e, dept d WHERE e.deptno(+) = d.deptno;
  • 一般在开发中, 在查找雇员姓名和雇员领佳节又重阳导时候. 就要求使用左右联接.

SQL99语法, 在FROM后面直接操作表格关系.

CROSS JOIN 交叉联接

  • select ename FROM emp CROSS JOIN dept; 生产笛卡尔积

NATURAL JOIN 自然联接 自动进行关联字段的匹配

  • select ename FROM emp NATURAL JOIN dept;

使用JOIN USING子句,可以手工操作关联字段.

  • select ename FROM emp e JOIN dept d USING(deptno) ;

ON 子句, 用户自己编写连接条件.

LEFT OUTER JOIN, RIGHT OUTER JOIN,

 

组函数和分组统计

组函数:

  • COUNT() 求出记录数
    • select count(empno) from emp;
  • MAX(), MIN(),求出最大最小值. 一般针对数字的应用
    • select min(sal) from emp;
    • select max(sal) from emp;
  • SUM(), AVG(), 求出总和和平均值
    • select sum(sal) from emp where deptno=20;
    • select avg(sal) from emp where deptno=20;

分组统计:

语法格式: GROUP BY 分组条件 , 放置在最后

  •  select count(empno) from emp group by deptno;
  • select avg(sal), deptno from emp group by deptno;
  1. 如果程序中使用了分组函数, 则有两种可以使用的情况.
    1. 程序中存在GROUP BY,并且制定了分组条件. 这样可以将分组条件一起查询出来. 如上例
    2. 如果不使用分组GROUP BY, 那么只能单独使用分组函数.
  2. 在使用分组函数的时候, 不能出现分组函数和分组条件之外的字段.
  • select count(e.empno), d.dname from dept d, emp e where d.deptno= e.deptno group by d.dname ;
  • 分组函数不允许在WHERE中使用. 如果要制定分组条件, 则要使用HAVING
  • select deptno, round(avg(sal)) from emp group by deptno having avg(sal)>2000;
  • select empno from emp where job!= UPPER('Saleman');
  • select job, sum(sal) su from emp group by job HAVING job!= UPPER('Saleman') AND sum(sal)>5000 ORDER BY su ASC;

 

  1. 只要一列上有存在重复内容才有可能考虑到分组.
  2. 分组函数可以嵌套使用, 但是在组函数嵌套使用的时候不能再出现分组条件的查询语句. 而且必须使用GROUP BY
  • select deptno, MAX(AVG(sal)) from emp group by deptno;  X!
  • select MAX(AVG(sal)) from emp group by deptno;

子查询

在一个查询还包括另一个查询

子查询在from或者where后面插入,要加括号

  • select sal from emp where empno= 7654;
  • select empno, sal from emp where sal> (select sal from emp where empno= 7654);
  1. 单列子查询, 返回结果是一列的一个内容
  2. 单行子查询, 返回多个列, 或者一个完整记录
  3. 多行子查询, 返回多条记录
  • select empno, sal, job from emp where sal> (select sal from emp where empno= 7654) AND job = (select job from emp where empno= 778 8) ;
  • select ename, job, sal from emp where sal=(select MIN(sal) from emp);
  • select count(empno), avg(sal), min(sal) MIN from emp  GROUP BY deptno ;(临时表)
  • SELECT d.dname, ed.EMPs, ed.AVGsal, e.ename FROM emp e, dept d, (select deptno, count(empno) EMPs, avg(sal) AVGsal, min(sal) MIN from emp  GROUP BY deptno) ed WHERE d.deptno = ed.deptno AND e.sal=ed.MIN; 这个只能处理不重复的最低工资值.

 

IN, ANY, ALL在子查询的操作符号.

  • IN操作符, 制定一个查询范围. (对返回多行数据)
  • select * from emp where sal IN (select min(sal) from emp group by deptno);
  • ANY操作符>
  • =ANY : 与IN完全一样. select * from emp where sal =ANY (select min(sal) from emp group by deptno);
  • >ANY : 比里面最小的值要大. select * from emp where sal >ANY (select min(sal) from emp group by deptno);
  • <ANY : 比里面最大的值要小. select * from emp where sal <ANY (select min(sal) from emp group by deptno);
  • ALL操作符
  • >ALL: 比里面最大的值要大. select * from emp where sal >ALL (select min(sal) from emp group by deptno);
  • <ALL: 比最小的值要小. select * from emp where sal < ALL (select min(sal) from emp group by deptno);

多列子查询中同时返回多个查询列 (开发中不常用).

select * from emp where (sal, nvl(comm, -1)) IN (SELECT sal, nvl(comm, -1) from emp where deptno= 20);

Posted in Oracle, 编程学习 | Tagged , , , | Leave a comment