数据库——SQL语言进阶

1 实验目的

  1. 学习子查询和常用函数;

  2. 了解数据库视图的操作;

  3. 学习 PL/SQL 语言实现对数据库存储过程、触发器等操作。

2 实验内容

在SQL Developer 中使用实验一创建的学生学号用户连接Oracle 数据库,使用实验一导入的EMP 表(员工表)、DEPT 表(部门表)和 SALGRADE 表(工资等级表),实现数据库子查询、视图、存储过程、触发器等的操作过程。

3 实验软件

Oracle 数据库、SQL Developer

4 实验步骤及数据记录

4.1 子查询

4.1.1 查询出销售部(SALES)下面的员工姓名、工作、工资。

SELECT ENAME,JOB,SAL FROM EMP
WHERE DEPTNO=(SELECT DEPTNO FROM DEPT WHERE DNAME='SALES');

数据库——SQL语言进阶_第1张图片

4.1.2 查询出 EMP 表中比任意一个销售员(SALESMAN)工资低(比销售员工资查询结果中的最大值小)的员工姓名、工作和工资。截图记录查询结果。

SELECT ENAME,JOB,SAL FROM EMP
WHERE SAL<ANY (SELECT SAL FROM EMP WHERE JOB='SALESMAN');

数据库——SQL语言进阶_第2张图片

4.2 伪列

4.2.1 查询出员工表中前 5 名员工的姓名、工作和工资。

SELECT ROWNUM,ENAME,JOB,SAL FROM EMP WHERE ROWNUM<=5;

数据库——SQL语言进阶_第3张图片

4.2.2 查询出工资最高的前 5 名员工的姓名、工资和工资。

SELECT ROWNUM,T.* FROM 
(SELECT ENAME,JOB,SAL
FROM EMP ORDER BY SAL DESC) T 
WHERE ROWNUM<=5;

数据库——SQL语言进阶_第4张图片

4.3 数据库对象

4.3.1 基于 EMP 表和DEPT 表创建一个只读视图,该视图中只包含员工编号、姓名、工作、入职日期和部门名称,隐藏了员工的工资、奖金、部门编号等信息。

CREATE OR REPLACE VIEW EMPDETAIL AS
SELECT EMPNO,ENAME,JOB,HIREDATE,DNAME
FROM EMP JOIN DEPT ON EMP.DEPTNO=DEPT.DEPTNO WITH READ ONLY;

查询创建的EMPDETAIL 视图:

SELECT * FROM EMPDETAIL;

数据库——SQL语言进阶_第5张图片

4.3.2 为 EMP 表的 ENAME 列创建唯一索引,为 EMP 表的工资列创建普通索引, 把JOB 列先变为小写再创建索引。

CREATE UNIQUE INDEX UQ_ENAME_IDX ON EMP(ENAME); 
CREATE INDEX IDX_SAL ON EMP(SAL); 
CREATE INDEX IDX_JOB_LOWER ON EMP(LOWER(JOB)); 

使用下面的SELECT 命令查看表EMP 的索引:

SELECT INDEX_NAME,INDEX_TYPE,TABLE_OWNER,TABLE_NAME,UNIQUENESS
FROM USER_INDEXES WHERE TABLE_NAME='EMP';

数据库——SQL语言进阶_第6张图片

4.4 块、存储过程和触发器

4.4.1 声明一个名为sname 的变量。

DECLARE
SNAME VARCHAR2(20) :='jerry'; 
BEGIN
SNAME:=SNAME||' and tom'; 
DBMS_OUTPUT.PUT_LINE (sname); 
END;

image-20230624144944924

4.4.2 创建一个显示雇员总人数的存储过程。

CREATE OR REPLACE PROCEDURE EMP_COUNT AS
V_TOTAL NUMBER(10); BEGIN
SELECT COUNT(*) INTO V_TOTAL FROM EMP;
DBMS_OUTPUT.PUT_LINE('雇员总人数为:'||V_TOTAL); END;

调用存储过程,在工作表中输入以下语句并执行:

EXECUTE EMP_COUNT;

image-20230624144950419

4.4.3 制作一个数据库触发器。记录所有对EMP表进行的INSERT、UPDATE 、DELETE操作

CREATE TABLE EMP_LOG( 
who varchar2(30), when date);
CREATE OR REPLACE TRIGGER EMP_OP 
BEFORE INSERT OR UPDATE OR DELETE 
ON EMP 
BEGIN 
INSERT INTO EMP_LOG (who,when) 
VALUES(user,sysdate); 
END EMP_OP;

执行EMP 表更新操作,查看日志表

UPDATE EMP SET SAL=SAL*1.1;
SELECT * FROM EMP_LOG;

数据库——SQL语言进阶_第7张图片

5 思考题

5.1 查询出比所有销售员的工资都高的员工姓名、工作和工资。请写出 SELECT命令,并给出查询结果截图。

SELECT ENAME,JOB,SAL
FROM EMP
WHERE SAL > ALL (SELECT SAL FROM EMP WHERE JOB='SALESMAN');

或者如下命令也可实现:

SELECT ENAME,JOB,SAL
FROM EMP
WHERE SAL > (SELECT MAX(SAL) FROM EMP WHERE JOB='SALESMAN');

数据库——SQL语言进阶_第8张图片

5.2 查询出 EMPDETAIL 视图中第 5 条到第 10 条之间的记录。请写出 SELECT命令,并给出查询结果截图。

SELECT * 
FROM (SELECT EMPDETAIL.*,ROWNUM RN FROM EMPDETAIL) TEMP
WHERE TEMP.RN>=5 AND TEMP.RN<=10;

数据库——SQL语言进阶_第9张图片

5.3 创建一个存储过程,显示工资最低的雇员名字。请写出创建存储过程的代码, 并给出存储过程的执行结果截图。

CREATE OR REPLACE PROCEDURE EMP_SAL_LEAST  
AS  
EMP_NAME VARCHAR2(20);
BEGIN 
SELECT ENAME INTO EMP_NAME FROM (SELECT ENAME FROM EMP WHERE ROWNUM=1 ORDER BY SAL ASC ); 
DBMS_OUTPUT.PUT_LINE('最低工资的员工是'||EMP_NAME);
END;

编译语句为:

set serveroutput on
EXECUTE EMP_SAL_LEAST;

image-20230624145017845

6 总结及心得体会

在本次实验中,我们利用搭建好的环境进行了SQL语言的进阶练习,如了解了子查询的原理并使用子查询与常见函数简化了查询过程和查询步骤;认识了伪列以及伪列的使用、注意事项;对存储过程、块、触发器也有了进一步的理解和认识。我们也通过思考题的方式了解到了伪列使用的特殊方法,掌握了不从头开始进行伪列查询的代码。收获良多。

全部代码:

--DROP TABLE EMP;
--DROP TABLE BONUS;
--DROP TABLE DEPT;
--DROP TABLE EMP_LOG;
--DROP TABLE SALGRADE;
--CREATE TABLE "BONUS" (
--"ENAME" VARCHAR2(10 BYTE) NULL ,
--"JOB" VARCHAR2(9 BYTE) NULL ,
--"SAL" NUMBER NULL ,
--"COMM" NUMBER NULL
--)
--LOGGING
--NOCOMPRESS
--NOCACHE
--;
---- ----------------------------
---- Table structure for "DEPT"
---- ----------------------------
--CREATE TABLE "DEPT" (
--"DEPTNO" NUMBER(2) NOT NULL ,
--"DNAME" VARCHAR2(14 BYTE) NULL ,
--"LOC" VARCHAR2(13 BYTE) NULL
--)
--LOGGING
--NOCOMPRESS
--NOCACHE
--;
---- ----------------------------
---- Records of DEPT
---- ----------------------------
--INSERT INTO "DEPT" VALUES ('10', 'ACCOUNTING', 'NEW YORK');
--INSERT INTO "DEPT" VALUES ('20', 'RESEARCH', 'DALLAS');
--INSERT INTO "DEPT" VALUES ('30', 'SALES', 'CHICAGO');
--INSERT INTO "DEPT" VALUES ('40', 'OPERATIONS', 'BOSTON');
---- ----------------------------
---- Table structure for "EMP"
---- ----------------------------
--CREATE TABLE "EMP" (
--"EMPNO" NUMBER(4) NOT NULL ,
--"ENAME" VARCHAR2(10 BYTE) NULL ,
--"JOB" VARCHAR2(9 BYTE) NULL ,
--"MGR" NUMBER(4) NULL ,
--"HIREDATE" DATE NULL ,
--"SAL" NUMBER(7,2) NULL ,
--"COMM" NUMBER(7,2) NULL ,
--"DEPTNO" NUMBER(2) NULL
--)
--LOGGING
--NOCOMPRESS
--NOCACHE
--;
---- ----------------------------
---- Records of EMP
---- ----------------------------
--INSERT INTO "EMP" VALUES ('7369', 'SMITH', 'CLERK', '7902', TO_DATE('1980-12-17
--00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '800', null, '20');
--INSERT INTO "EMP" VALUES ('7499', 'ALLEN', 'SALESMAN', '7698',
--TO_DATE('1981-02-20 00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '1600', '300', '30');
--INSERT INTO "EMP" VALUES ('7521', 'WARD', 'SALESMAN', '7698', TO_DATE('1981-02-22
--00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '1250', '500', '30');
--INSERT INTO "EMP" VALUES ('7566', 'JONES', 'MANAGER', '7839', TO_DATE('1981-04-02
--00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '2975', null, '20');
--INSERT INTO "EMP" VALUES ('7654', 'MARTIN', 'SALESMAN', '7698',
--TO_DATE('1981-09-28 00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '1250', '1400', '30');
--INSERT INTO "EMP" VALUES ('7698', 'BLAKE', 'MANAGER', '7839', TO_DATE('1981-05-01
--00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '2850', null, '30');
--INSERT INTO "EMP" VALUES ('7782', 'CLARK', 'MANAGER', '7839', TO_DATE('1981-06-09
--00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '2450', null, '10');
--INSERT INTO "EMP" VALUES ('7788', 'SCOTT', 'ANALYST', '7566', TO_DATE('1987-04-19
--00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '3000', null, '20');
--INSERT INTO "EMP" VALUES ('7839', 'KING', 'PRESIDENT', null, TO_DATE('1981-11-17
--00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '5000', null, '10');
--INSERT INTO "EMP" VALUES ('7844', 'TURNER', 'SALESMAN', '7698',
--TO_DATE('1981-09-08 00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '1500', '0', '30');
--INSERT INTO "EMP" VALUES ('7876', 'ADAMS', 'CLERK', '7788', TO_DATE('1987-05-23
--00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '1100', null, '20');
--INSERT INTO "EMP" VALUES ('7900', 'JAMES', 'CLERK', '7698', TO_DATE('1981-12-03
--00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '950', null, '30');
--INSERT INTO "EMP" VALUES ('7902', 'FORD', 'ANALYST', '7566', TO_DATE('1981-12-03
--00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '3000', null, '20');
--INSERT INTO "EMP" VALUES ('7934', 'MILLER', 'CLERK', '7782', TO_DATE('1982-01-23
--00:00:00', 'yyyy-MM-dd HH24:mi:ss'), '1300', null, '10');
---- ----------------------------
---- Table structure for "SALGRADE"
---- ----------------------------
--CREATE TABLE "SALGRADE" (
--"GRADE" NUMBER NULL ,
--"LOSAL" NUMBER NULL ,
--"HISAL" NUMBER NULL
--)
--LOGGING
--NOCOMPRESS
--NOCACHE
--;
---- ----------------------------
---- Records of SALGRADE
---- ----------------------------
--INSERT INTO "SALGRADE" VALUES ('1', '700', '1200');
--INSERT INTO "SALGRADE" VALUES ('2', '1201', '1400');
--INSERT INTO "SALGRADE" VALUES ('3', '1401', '2000');
--INSERT INTO "SALGRADE" VALUES ('4', '2001', '3000');
--INSERT INTO "SALGRADE" VALUES ('5', '3001', '9999');28
---- ----------------------------
---- Primary Key structure for table "DEPT"
---- ----------------------------
--ALTER TABLE "DEPT" ADD CONSTRAINT PK_DEPT PRIMARY KEY ("DEPTNO");
---- ----------------------------
---- Primary Key structure for table "EMP"
---- ----------------------------
-- ALTER TABLE "EMP" ADD CONSTRAINT PK_EMP PRIMARY KEY ("EMPNO");
---- ----------------------------
---- Foreign Key structure for table "EMP"
---- ----------------------------
--ALTER TABLE "EMP" ADD CONSTRAINT FK_DEPTINO FOREIGN KEY ("DEPTNO") REFERENCES
--"DEPT" ("DEPTNO");

SELECT ENAME,JOB,SAL FROM EMP
WHERE DEPTNO=(SELECT DEPTNO FROM DEPT WHERE DNAME='SALES');

CREATE OR REPLACE VIEW EMPDETAIL AS
SELECT EMPNO,ENAME,JOB,HIREDATE,DNAME
FROM EMP JOIN DEPT ON EMP.DEPTNO=DEPT.DEPTNO WITH READ ONLY;

SELECT * FROM EMPDETAIL;

CREATE UNIQUE INDEX UQ_ENAME_IDX ON EMP(ENAME); 
CREATE INDEX IDX_SAL ON EMP(SAL); 
CREATE INDEX IDX_JOB_LOWER ON EMP(LOWER(JOB)); 

SELECT INDEX_NAME,INDEX_TYPE,TABLE_OWNER,TABLE_NAME,UNIQUENESS
FROM USER_INDEXES WHERE TABLE_NAME='EMP';

set serveroutput on
DECLARE
SNAME VARCHAR2(20) :='jerry'; 
BEGIN
SNAME:=SNAME||' and tom'; 
DBMS_OUTPUT.PUT_LINE (sname); 
END;

CREATE OR REPLACE PROCEDURE EMP_COUNT AS
V_TOTAL NUMBER(10); BEGIN
SELECT COUNT(*) INTO V_TOTAL FROM EMP;
DBMS_OUTPUT.PUT_LINE('雇员总人数为:'||V_TOTAL); END;

set serveroutput on
EXECUTE EMP_COUNT;

CREATE TABLE EMP_LOG( 
who varchar2(30), when date);
CREATE OR REPLACE TRIGGER EMP_OP 
BEFORE INSERT OR UPDATE OR DELETE 
ON EMP 
BEGIN 
INSERT INTO EMP_LOG (who,when) 
VALUES(user,sysdate); 
END EMP_OP;

UPDATE EMP SET SAL=SAL*1.1;
SELECT * FROM EMP_LOG;

CREATE OR REPLACE PROCEDURE EMP_SAL_LEAST   
AS   
EMP_NAME VARCHAR2(20);
BEGIN  
SELECT ENAME INTO EMP_NAME FROM (SELECT ENAME FROM EMP WHERE ROWNUM=1 ORDER BY SAL ASC );  
DBMS_OUTPUT.PUT_LINE('最低工资的员工是'||EMP_NAME);
END; 

set serveroutput on
EXECUTE EMP_SAL_LEAST;

SELECT * FROM emp,dept;


SELECT INDEX_NAME,INDEX_TYPE,TABLE_OWNER,TABLE_NAME,UNIQUENESS
FROM USER_INDEXES WHERE TABLE_NAME='EMP';

SELECT ENAME,JOB,SAL
FROM EMP
WHERE SAL > (SELECT MAX(SAL) FROM EMP WHERE JOB='SALESMAN');

你可能感兴趣的:(数据库,sql)