您的位置:首页 > 职场人生

程序员常见面试之 数据库 知识点小结(二)

2015-12-24 21:43 579 查看

前言

笔者悉心整理的数据库面试知识点,希望对各位朋友有所帮助。

文章链接 /article/3605324.html ,转载请保留出处。

聚簇索引与非聚簇索引的区别

聚簇索引的顺序就是数据的物理存储顺序

每个表中只能有一个聚集索引

聚集索引要求:“既不能绝大多数都相同,又不能只有极少数相同”的规则。

非聚簇索引的解释是:索引顺序与数据物理排列顺序无关

一个表最多只能有一个聚簇索引。

建立索引代码

[code]-----------------------------------------------------------
---- 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)


非聚集索引代码

[code]-----------------------------------------------------------
---- 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)


NonClustered 和 Clustered 就是聚集和非聚集的区别

稠密和非稠密的区别

稠密就是一条搜索码值都有一个索引,

非稠密索引中,只为搜索码的某些值建立索引项。非稠密是一个索引对应一些记录的范围

Note

辅助索引必须是稠密索引

游标

比如 select * from table_a 可以得到结果集,游标用来定位结果集的行,可以对结果集修改等等。

@@FETCH_STATUS 全局变量可以判断游标是不是到了最后,该变量为非0表示到了最后或者出错

代码

[code]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;


触发器

触发器是一个特殊的存储过程。 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 表被删除一条记录时,把被删除记录写到职工表删除日志表中去。

[code]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;


[code]    Oracle 中默认的相关名称分别为OLD和NEW。触发器的PL/SQL块中应用相关名称时,必须在它们之前加冒号(:),但在WHEN子句中则不能加冒号。


例2:限制对Departments表修改(包括INSERT,DELETE,UPDATE)的时间范围,即不允许在非工作时间修改departments表。

[code]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;


其他示例

我为什么要使用触发器?比如,这么两个表:

[code]      Create Table Student(              --学生表 
        StudentID int primary key,       --学号 
        .... 
       ) 

      Create Table BorrowRecord(               --学生借书记录表 
        BorrowRecord   int identity(1,1),       --流水号   
        StudentID      int ,                    --学号 
        BorrowDate     datetime,                --借出时间 
        ReturnDAte     Datetime,                --归还时间 
        ... 
      )


[code] 用到的功能有: 
    1.如果我更改了学生的学号,我希望他的借书记录仍然与这个学生相关(也就是同时更改借书记录表的学号); 
    2.如果该学生已经毕业,我希望删除他的学号的同时,也删除它的借书记录。 
 等等。 

 这时候可以用到触发器。对于1,创建一个Update触发器:


[code]     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


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 行。

如果文章对您有所帮助,不妨支持一注2块彩票钱



参考文章

索引的一些总结

深入浅出理解索引结构

聚簇索引与非聚簇索引的区别以及SQL Server查询优化技术

SQL Sever数据库开发经典案例解析/经典案例解析丛书

Oracle中Cursor介绍

ORACLE PL/SQL编程之八: 把触发器说透

详细讲解4种SQL Server 2008数据库备份类型

SQLSERVER备份事务日志的作用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: