美文网首页数据库
[数据库之五] 高级 SQL

[数据库之五] 高级 SQL

作者: 小胡_鸭 | 来源:发表于2021-05-28 18:08 被阅读0次

1、使用程序设计语言访问数据库

  标准:JDBC(Java)、ODBC(C、C++、C#、VB)


2、函数和过程

(1)函数的声明和调用

// 声明一个函数,根据传入的学院名称得到该学院中的教师数
create function dept_count(dept_name varchar(20))
    returns integer
    begin
    declare d_count integer;
        select count(*) into d_count
        from instructor
        where instructor.dept_name = dept_name
    return d_count;
    end
    
// 使用函数,返回教师数大于 12 的所有系的名称和预算
select dept_name, budget
from department
where dept_count(dept_name) > 12;


// 声明一个表函数,即返回关系作为结果的函数,获得某个系的所有老师
create function instructor_of (dept_name varchar(20))
    returns table (
        ID varchar(5),
        name varchar(20),
        dept_name varchar(20),
        salary numeric(8, 2))
return table
    (select ID, name, dept_name, salary
     from instructor
     where instructor.dept_name = instructor_of.dept_name);
     
// 使用表函数,返回金融系的所有老师
select * 
from table(instructor_of('Finance'));

(2)存储过程的声明和调用

// 声明一个存储过程,获得某个系的老师人数
create procedure dept_count_proc(in dept_name varchar(20), out d_count integer)
    begin
        select count(*) into d_count
        from instructor
        where instructor.dept_name = dept_count_proc.dept_name
    end
    
// 使用存储过程,获得物理系的老师人数
declare d_count integer;
call dept_count_proc('Physics', d_count);

(3)函数和存储过程的区别

① 传参的差异:函数只能返回一个参数(值或表对象),存储过程可以返回。

② 调用方式的差异:函数可以作为查询语句的一个部分来调用(SELECT调用),由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面; 存储过程一般是作为一个独立的部分来执行(EXEC执行)。

③ 功能实现上:存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。

  从本质上,函数和存储过程的执行没有什么区别。


3、触发器

  当数据库被修改时,有时需要有一种机制来实现特定事件发生的情况下,去执行某些动作,这就是触发器的作用。

(1)对触发器的需求

  触发器常用来实现未被 SQL 约束机制指定的某些完整性约束。

  比如大学数据库中,takes 表示学生的选课情况,如果某门课已经结课并出成绩,就应该更新 student 关系中选课的学生所对应元组,把该课的学分加入这个学生的总学分中。

【学生】student ( <u>id</u>, name, dept_name, tot_cred )
【学生课表】takes ( <u>id</u>, <u>course_id</u>, <u>sec_id</u>, <u>semester</u>, <u>year</u>, grade )

(2)触发器的定义和使用

【课程段】section ( <u>course_id</u>, <u>sec_id</u>, <u>semester</u>, <u>year</u>, building, room_number, time_slot_id )

【上课时段】time_slot ( <u>time_slot_id</u>, day, start_time, end_time )

【学生】student ( <u>id</u>, name, dept_name, tot_cred )

【学生课表】takes ( <u>id</u>, <u>course_id</u>, <u>sec_id</u>, <u>semester</u>, <u>year</u>, grade )
【课程】course ( <u>course_id</u>, title, dept_name, credits )

  • 新增时执行触发器

    当新增一个课程段时,需要触发器检查新插入 section 关系的元组中的 time_slot_id 是否合法,不合法则回滚取消插入。

create trigger timeslot_check1 after insert on section
    referencing new row as nrow
    for each row
    when (nrow.time_slot_id not in (
            select time_slot_id
            from time_slot))    /* time_slot 中不存在该 time_slot_id */
    begin
        rollback
    end;
  • 删除时执行触发器

    删除一个上课时段时,需要触发器检查当前有没有课程段使用了该时段,是则不允许删除。

create trigger timeslot_check2 after delete on time_slot
    referencing old row as orow
    for each row
    when (orow.time_slot_id not in (
            select time_slot_id
            from time_slot)     /* 在 time_slot 中刚刚被删除的 time_slot_id */
    and orow.time_slot_id in (
            select time_slot_id
            from section))      /* 在 section 中仍含有该 time_slot_id 的引用 */
    begin
        rollback
    end;
  • 更新时执行触发器

    当关系 takes 中的元组的属性 grade 被更新时,需要用触发器来维护 student 里元组的 tot_cred 属性,使其保持实时更新。

    使用 after update of takes on grade 来标示当更新关系 takes 的属性 grade 时执行触发器。

create trigger credits_earned after update on takes on (grade)
    referencing new row as nrow
    referencing old row as orow
    for each row
    when nrow.grade <> 'F' and nrow.grade is not null
        and (orow.grade = 'F' or orow.grade is null)
    begin atomic
        update student
        set tot_cred = tot_cred +
            (select credits
             from course
             where course.course_id = nrow.course_id)
        where student.id = nrow.id;
    end;

  上述的三个例子触发器都是在 SQL 执行之后触发,实际上触发器也可以在事件之前触发,作为避免非法更新、插入或删除的额外约束。

  • 事件之前执行触发器

    学生选课插入的分值为空白表明分数发生缺失,定义触发器用 null 值代替。

create trigger setnull before update of takes
    referencing new row as nrow
    for each row
    when (nrow.grade = '')
    begin atomic
        set nrow.grade = null;
    end;

  触发器创建时默认有效,可使用以下语法设置为无效:

alter trigger trigger_name disable;
(一些数据库的语法) disable trigger trigger_name;

  删除触发器使用以下语法:

drop trigger trigger_name;

相关文章

  • [数据库之五] 高级 SQL

    1、使用程序设计语言访问数据库   标准:JDBC(Java)、ODBC(C、C++、C#、VB) 2、函数和过程...

  • 数据库SQL语句

    数据库之SQL语句(二) 数据库之SQL语句(一)[https://www.jianshu.com/p/460e3...

  • UNIQUE ,PRIMARY KEY

    GO ON----(SQL高级) SQL UNIQUE 约束 UNIQUE 约束唯一标识数据库表中的每条记录。 U...

  • MySQL优化

    数据库SQL优化大总结之 百万级数据库优化方案

  • 数据库知识点

    数据库知识点 数据库相关概念 mysql安装与使用 navicat的使用 SQL语言的查询(重点) 高级(了解) ...

  • iOS数据库存储之SQLite3

    资源连接: iOS数据库存储之SQL语句; iOS数据存储之文件沙盒; iOS数据存储之NSCoding; SQL...

  • 数据库基础Database3-高级SQL

    数据库基础Database3 四 高级SQL 4.1 使用程序设计语言访问数据库 JDBC 4.2 函数和过程 (...

  • iOS数据存储之文件沙盒

    资源连接: iOS数据库存储之SQL语句; iOS数据库存储之SQLite3; iOS数据存储之NSCoding;...

  • SQL高级

    高级sql语句 1.select top limit rownum (不同数据库使用不同的) 2.SELE...

  • 小迪16期-20170305

    第三天:Sql注入技巧篇 1.Sql注入之access注入 access数据库结构数据库表名数据库列名数据 1.a...

网友评论

    本文标题:[数据库之五] 高级 SQL

    本文链接:https://www.haomeiwen.com/subject/xtassltx.html