笔者悉心整理的数据库面试知识点,希望对各位朋友有所帮助。
文章链接 http://blog.csdn.net/never_cxb/article/details/50420521 ,转载请保留出处。
聚簇索引与非聚簇索引的区别
- 聚簇索引的顺序就是数据的物理存储顺序
每个表中只能有一个聚集索引
聚集索引要求:“既不能绝大多数都相同,又不能只有极少数相同”的规则。 - 非聚簇索引的解释是:索引顺序与数据物理排列顺序无关
- 一个表最多只能有一个聚簇索引。
建立索引代码
-----------------------------------------------------------
---- Create T_Pet table in tempdb.
-----------------------------------------------------------
USE tempdb
CREATE TABLE T_Pet
(
animal VARCHAR(20),
[name] VARCHAR(20),
sex CHAR(1),
age INT
)
-----------------------------------------------------------
---- Create Unique Clustered Index
-----------------------------------------------------------
CREATE UNIQUE CLUSTERED INDEX T_PetonAnimal1_ClterIdx ON T_Pet (animal)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
非聚集索引代码
-----------------------------------------------------------
---- Create T_Pet table in tempdb with NONCLUSTERED INDEX.
-----------------------------------------------------------
USE tempdb
CREATE TABLE T_Pet
(
animal VARCHAR(20),
[name] VARCHAR(20),
sex CHAR(1),
age INT
)
-----------------------------------------------------------
---- Create Unique NonClustered Index
-----------------------------------------------------------
CREATE UNIQUE NONCLUSTERED INDEX T_PetonAnimal1_NonClterIdx ON T_Pet (animal)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
NonClustered 和 Clustered 就是聚集和非聚集的区别
稠密和非稠密的区别
稠密就是一条搜索码值都有一个索引,
非稠密索引中,只为搜索码的某些值建立索引项。非稠密是一个索引对应一些记录的范围
Note
辅助索引必须是稠密索引
游标
比如 select * from table_a 可以得到结果集,游标用来定位结果集的行,可以对结果集修改等等。
@@FETCH_STATUS 全局变量可以判断游标是不是到了最后,该变量为非0表示到了最后或者出错
代码
Set serveroutput on;
declare
---define Cursor
Cursor cur_policy is
select cm.policy_code, cm.applicant_id, cm.period_prem,cm.bank_code,cm.bank_account
from t_contract_master cm
where cm.liability_state = 2
and cm.policy_type = 1
and cm.policy_cate in ('2','3','4')
and rownum < 5
order by cm.policy_code desc;
curPolicyInfo cur_policy%rowtype;---定义游标变量
Begin
open cur_policy; ---open cursor
Loop
--deal with extraction data from DB
Fetch cur_policy into curPolicyInfo;
Exit when cur_policy%notfound;
Dbms_Output.put_line(curPolicyInfo.policy_code);
end loop;
Exception
when others then
close cur_policy;
Dbms_Output.put_line(Sqlerrm);
if cur_policy%isopen then
--close cursor
close cur_policy;
end if;
end;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
触发器
触发器是一个特殊的存储过程。 ORACLE事件指的是对数据库的表进行的INSERT、UPDATE及DELETE操作或对视图进行类似的操作。ORACLE将触发器的功能扩展到了触发ORACLE,如数据库的启动与关闭等
- 触发时机:指定触发器的触发时间。如果指定为BEFORE,则表示在执行DML操作之前触发,以便防止某些错误操作发生或实现某些业务规则;如果指定为AFTER,则表示在执行DML操作之后触发,以便记录该操作或做某些事后处理。
- 语句触发器是对每一个语句触发一次
- 行触发器是对语句受影响的每一行触发一次
行触发器和语句触发器的区别表现在:行触发器要求当一个DML语句操走影响数据库中的多行数据时,对于其中的每个数据行,只要它们符合触发约束条件,均激活一次触发器;而语句触发器将整个语句操作作为触发事件,当它符合约束条件时,激活一次触发器。当省略FOR EACH ROW 选项时,BEFORE 和AFTER 触发器为语句触发器,而INSTEAD OF 触发器则为行触发器。
比如 插入500行的 insert 命令,语句触发器只触发一次,而行触发器出发了500次
- 行触发器有 for each row子句。语句触发器没有for each row 子句
代码
BEFORE DELETE 这儿的 before 可以换成 after
for each row 可以有或者省略
例1: 建立一个触发器, 当职工表 emp 表被删除一条记录时,把被删除记录写到职工表删除日志表中去。
CREATE TABLE emp_his AS SELECT * FROM EMP WHERE 1=2;
CREATE OR REPLACE TRIGGER tr_del_emp
BEFORE DELETE --指定触发时机为删除操作前触发
ON scott.emp
FOR EACH ROW --说明创建的是行级触发器
BEGIN
--将修改前数据插入到日志记录表 del_emp ,以供监督使用。
INSERT INTO emp_his(deptno , empno, ename , job ,mgr , sal , comm , hiredate )
VALUES( :old.deptno, :old.empno, :old.ename , :old.job,:old.mgr, :old.sal, :old.comm, :old.hiredate );
END;
DELETE emp WHERE empno=7788;
DROP TABLE emp_his;
DROP TRIGGER del_emp;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
Oracle 中默认的相关名称分别为OLD和NEW。触发器的PL/SQL块中应用相关名称时,必须在它们之前加冒号(:),但在WHEN子句中则不能加冒号。
- 1
- 2
例2:限制对Departments表修改(包括INSERT,DELETE,UPDATE)的时间范围,即不允许在非工作时间修改departments表。
CREATE OR REPLACE TRIGGER tr_dept_time
BEFORE INSERT OR DELETE OR UPDATE
ON departments
BEGIN
IF (TO_CHAR(sysdate,'DAY') IN ('星期六', '星期日')) OR (TO_CHAR(sysdate, 'HH24:MI') NOT BETWEEN '08:30' AND '18:00') THEN
RAISE_APPLICATION_ERROR(-20001, '不是上班时间,不能修改departments表');
END IF;
END;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
其他示例
我为什么要使用触发器?比如,这么两个表:
Create Table Student( --学生表
StudentID int primary key, --学号
....
)
Create Table BorrowRecord( --学生借书记录表
BorrowRecord int identity(1,1), --流水号
StudentID int , --学号
BorrowDate datetime, --借出时间
ReturnDAte Datetime, --归还时间
...
)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
用到的功能有:
1.如果我更改了学生的学号,我希望他的借书记录仍然与这个学生相关(也就是同时更改借书记录表的学号);
2.如果该学生已经毕业,我希望删除他的学号的同时,也删除它的借书记录。
等等。
这时候可以用到触发器。对于1,创建一个Update触发器:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
Create Trigger truStudent
On Student --在Student表中创建触发器
for Update --为什么事件触发
As --事件触发后所要做的事情
if Update(StudentID)
begin
Update BorrowRecord
Set StudentID=i.StudentID
From BorrowRecord br , Deleted d ,Inserted i --Deleted和Inserted临时表
Where br.StudentID=d.StudentID
end
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
SQLServer 理解触发器里面的两个临时的表:Deleted , Inserted 。注意Deleted 与Inserted分别表示触发事件的表“旧的一条记录”和“新的一条记录”。
一个数据库系统中有两个虚拟表用于存储在表中记录改动的信息,分别是:
Tables | 虚拟表Inserted | 虚拟表Deleted |
---|---|---|
在表记录新增时 | 存放新增的记录 | 存放新增的记录 |
修改时 | 存放用来更新的新记录 | 存放更新前的记录 |
删除时 | 不存储记录 | 存放被删除的记录 |
PL SQL
PL: Procedural LanguagePL/SQL也是一种程序语言,叫做过程化SQL语言(Procedural Language/SQL)。
PL/SQL是Oracle数据库对SQL语句的扩展。在普通SQL语句的使用上增加了编程语言的特点,所以PL/SQL就是把数据操作和查询语句组织在PL/SQL代码的过程性单元中,通过逻辑判断、循环等操作实现复杂的功能或者计算的程序语言。
参见 这儿
plsql 常用函数
事务日志
事务日志文件Transaction Log File,扩展名为ldf。它是用来记录数据库更新情况的文件,它可以记录针对数据库的任何操作,并将记录的结果保存到独立的文件中。对于每一次数据库更新的过程,事务日志文件都有非常全面的记录。根据这些记录可以恢复数据库更新前的状态。
在 SQL Server 2000中,数据库至少包括一个数据文件和事务日志文件,数据和事务日志从不混在一个文件里。
在事务日志已满的情况下,用户不能更新数据。backup log语句有双重的目的,不仅可以备份事务日志,并且在事务日志满的时候,用户还可以利用他清理事务日志,移去事务日志中不活动的部分。
截断并不减少物理日志文件大小,而是减少逻辑日志文件的大小并释放磁盘空间以供重新使用。
通常情况下,事务日志备份经常与完整备份和差异备份结合使用,比如,每周进行一次完整备份,每天进行一次差异备份,每小时进行一次日志备份。这样,最多只会丢失一个小时的数据。
如何查看最早开始的活动事务的开始时间及服务器进程 ID
连接到某个数据库,执行 DBCC OPENTRAN
命令,查看 SPID 和 Start time 行。
参考文章
索引的一些总结
深入浅出理解索引结构
聚簇索引与非聚簇索引的区别以及SQL Server查询优化技术
SQL Sever数据库开发经典案例解析/经典案例解析丛书
Oracle中Cursor介绍
ORACLE PL/SQL编程之八: 把触发器说透
详细讲解4种SQL Server 2008数据库备份类型
SQLSERVER备份事务日志的作用