理解为一种依照特定数据模型组织、存储和管理数据的文件集合。在信息系统中,数据库的基本作用是组织与存储系统数据,并为系统软件从中存取数据提供支持。与文件系统中普通数据文件有明显不同,数据库文件具有如下特点。数据一般不重复存放。可支持多个应用程序并发访问。数据结构独立于使用它的应用程序。对数据增、删、改、查操作均由数据库系统软件进行管理和控制。
借助数据库进行信息化处理的计算机应用系统被称为数据库应用系统。
从功能角度数据库应用系统可以划分为四个层次来实现:
数据库应用系统的生命周期:

关系数据库的突出优势是,数据表示的 3 级模式(外模式、模式、内模式) 保证了数据的逻辑独立性(外模式和模式之间,需要修改外模式/映像)和物理独立性(模式和内模式间,需要修改模式/内模式映像),完整的事务处理机制保持数据的一致性(事务的 ACID,即原子性、一致性、隔离性、持久性);
对数据的数据项、数据结构、数据流、数据存储、处理逻辑等进行定义和描述。
关系特性



CONSTRAINT CoursePlanID_FK FOREIGN Key(CoursePlanID)
REFERENCES Plan(CoursePlanID)
CONSTRAINT CoursePlan_PK PRIMARY Key(CourseID,TeacherID)
SELECT C.CourseName AS 课程名称,T.TeacherName AS 教师,COUNT(R.CoursePlanID) AS 选课人数
FROM Course AS C JOIN Plan AS P
ON C.CourseID=P.CourseID
JOIN Teacher AS T ON P.TeacherID=T.TeacherID
LEFT JOIN Register AS R ON P.CoursePlanID=R.CoursePlanID GROUP BY C.CourseName, T.TeacherName;
SELECT College.CollegeName AS 学院名称, COUNT(Teacher.CollegeID) AS 教师人数
FROM Teacher, College WHERE Teacher.CollegeID=College.CollegeID
GROUP BY College.CollegeName ORDER BY College.CollegeName DESC;
CREATE INDEX BirthDay_Idx ON Student(BirthDay);

转换为关系模型


这个箭头是标识符依赖的意思


X → Y:Y 依赖于 X,若 Y 不依赖于 X 的任何真子集,则称为 Y 完全依赖于 X。例如{X,Y}是主键,故{X,Y}→N,则该关系中属性间约束为完全函数依赖,反之为部分函数依赖。
X→Y, Y 不 →X,Y→Z 称为传递依赖。第二个条件为了保证 X 和 Y 不一一对应。
多值依赖: 有课程、教师和参考书,其属性间约束的语义:一门课程可以有多个任课教师,也可以有多本参考书;每个任课教师可以任意选择他的参考书。例如,存在(课程 A,教师 1,参考书 1)、(课程 A,教师 2,参考书 2)、(课程 A,教师 1,参考书 2)和(课程 A,教师 2,参考书 1)等元组,即该关系存在多值 依赖 Course→→Teacher,Course→→Book。简单来说,对任意确定的课程都有一组教师的取值与之对应,同样每个课程 都有一组参考书与之对应,而教师的取值与参考书的取值是相互独立的。
一个只满足 1NF 的关系可能存在的四方面问题是:数据冗余度大、插入异常、修改异常和删除异常
STU_ID 是 21,它有两门课程,计算机和数学以及两个爱好,舞蹈和歌唱。 因此,对 STU_ID 存在多值依赖性,这导致不必要的数据重复)在数据库中,事务(Transaction)是指由构成单个业务处理单元的一组数据库访问操作,要求它们要么都成功执行,要么都不执行。同时,事务也是 DBMS 最小的故障恢复任务单元和并发控制任务单元。其生命周期状态变迁如图所示。
事务 ACID 特性:
事务并发执行是指多个事务程序在数据库系统中同一时段运行。
事务并发执行原因:
BEGIN 或 START TRANSACTION ;事务开始语句
ROLLBACK 事务回滚语句
COMMIT 事务提交语句
SAVEPOINT 事务保存点语句,回滚到这里
之所以将插入单独列出来称为幻象读取
是因为新数据的插入除了对聚合函数结果有影响,并没有影响原有数据。
因此对多次读取发现数据有新增的容忍度会高一些。
在事务并发执行中,只有当事务中数据操作调度顺序的执行结果与事务串行执行结果一样时,该并发事务调度才能保证数据操作的正确性和一致性。符合这样效果的调度称为可串行化调度。
排它锁定(Lock-X)——锁定后,不允许其它事务对共享数据再加锁
共享锁定(Lock-S)——锁定后,只允许其它事务对共享数据添加读取锁
增长阶段,事务只能获得锁,但不能释放锁。
缩减阶段,事务只能释放锁,但不能获得新锁
若并发事务执行的所有事务都遵从两阶段锁定协议,则这些事务的任何并发调度都是可串行化调度,即这些并发调度执行结果可以保证数据库一致性。

如果用户希望使用故障前的数据库备份文件进行恢复处理,可采用前滚事务恢复方式将数据库恢复到故障发生前一时刻的数据库状态。这是在数据库备份版本基础上,通过系统执行事务日志文件中记录的操作命令来实现数据库恢复处理,即将系统记录的后像数据重新应用到数据库中,从而将数据库恢复到故障发生前一时刻的状态。 后像数据是数据库备份时刻到故障时刻期间所记录的事务修改数据。
当用户希望使用故障后的数据库进行恢复处理时,可采用回滚事务恢复方式将数据库恢复到故障发生前一时刻的数据库状态。这是在故障后的数据库基础上,通过系统回滚事务操作来实现的。在恢复处理时,取消错误执行或部分完成的事务对数据库的修改,将系统记录的前像数据恢复到数据库中,从而将数据库恢复到故障发生前一时刻的状态。 前像数据是数据库故障时刻之前所记录的事务修改数据。

CREATE USER "userA" WITH LOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT NOREPLICATION CONNECTION LIMIT -1 PASSWORD '123456';
GRANT SELECT ON Department TO "userA";
CREATE ROLE "Role_Manager" WITH
LOGIN
NOSUPERUSER
NOCREATEDB
NOCREATEROLE
INHERIT
NOREPLICATION
CONNECTION LIMIT -1;
GRANT SELECT,INSERT,UPDATE,DELETE ON Department TO "Role_Manager"
CREATE USER "StudentUser" WITH
LOGIN
NOSUPERUSER
NOCREATEDB
NOCREATEROLE
INHERIT
NOREPLICATION
CONNECTION LIMIT -1
IN ROLE "R_Student"
PASSWORD '123456';
CREATE OR REPLACE FUNCTION countRecords ()
RETURNS integer AS $count$
DECLARE
count integer;
BEGIN
SELECT count(*) INTO count FROM Student;
RETURN count;
END;
$ count $ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION score_audit()
RETURNS TRIGGER AS $score_audit$
BEGIN
IF (TG_OP = 'DELETE') THEN
INSERT INTO Audit_score SELECT user, old.sid, old.cid, now(), OLD.score;
RETURN OLD;
ELSIF (TG_OP = 'UPDATE'') THEN
INSERT INTO Audit_score SELECT user, old.sid, old.cid, now(), OLD.score , new.score where old.sid=new.sid and old.cid=new.cid;
RETURN NEW;
ELSIF (TG_OP = 'INSERT'') THEN
INSERT INTO Audit_score SELECT user, new.sid, new.cid, now(),null, new.score;
RETURN NEW;
END IF;
RETURN NULL;
END;
$score_audit$ LANGUAGE plpgsql;
CREATE TRIGGER score_audit_trigger AFTER INSERT OR UPDATE OR DELETE ON Stu_score FOR EACH ROW EXECUTE PROCEDURE score_audit();
import java.sql.Connection;
import java.sql.DriverManager;
public class Database {
public String url = "jdbc:postgresql://localhost:5432/GradeDB";
public String username = "postgres";
public String password = "1";
public Connection conn;
Database() {
try {
Class.forName("org.postgresql.Driver");
this.conn = DriverManager.getConnection(this.url, this.username, this.password);
}
catch (Exception e) {
System.out.println("无法连接到数据库");
e.printStackTrace();
}
}
}
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
@RestController
public class GradeController {
public Database database = new Database();
@GetMapping("/students")
public List<Grade> getStudentGrade() {
String SQL = "select grade.sid, student.sname, grade.cid, course.cname, score\n" + "from grade\n" + "inner join student on student.sid = grade.sid\n" + "inner join course on course.cid = grade.cid;";
ArrayList<Grade> result = new ArrayList<>();
try {
Statement smt = database.conn.createStatement();
ResultSet rs = smt.executeQuery(SQL);
while (rs.next()) {
String sid = rs.getString("sid");
String sname = rs.getString("sname");
String cid = rs.getString("cid");
String cname = rs.getString("cname");
int score = rs.getInt("score");
result.add(new Grade(sid, cid, sname, cname, score));
}
smt.close();
rs.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
curStudent CURSOR FOR SELECT * FROM student;
curStudentOne CURSOR (key integer) IS SELECT * FROM student WHERE SID = key;
#为了兼容Oracle,FOR可以改为IS
OPEN curVars1 FOR SELECT * FROM student WHERE SID = mykey
OPEN curVars1 FOR EXECUTE 'SELECT * FROM ' || quote_ident($1);
OPEN curStudent;
OPEN curStudentOne ('20160230302001');
FETCH curVars1 INTO rowvar; --rowvar为行变量
FETCH curStudent INTO SID, Sname, sex;
CLOSE curStudent;