任务3 使用SQL语句操作数据表

关键步骤如下。

使用CREATE TABLE创建数据表stuInfo。

使用SELECT语句操作数据表stuInfo。

使用COMMIT、ROLLBACK、SAVEPOINT管理事务。

SQL是高级的结构化查询语言。当用户使用SQL 语句进行数据操作时,只需要提出“做什么”,而不必指明“怎么做”,具体的执行过程由系统自动完成,大大减轻了用户负担。SQL语句是数据库服务器和客户端之间的重要沟通手段,用于存取数据及查询、更新和管理关系型数据库系统。

经过多年的发展,SQL已经成为关系型数据库的标准语言。SQL支持如下类别的命令。

数据定义语言(DDL):CREATE(创建)、ALTER(更改)、TRUNCATE(截断)和DROP(删除)命令。

数据操纵语言(DML):INSERT(插入)、SELECT(选择)、DELETE(删除)和UPDATE(更新)命令。

事务控制语言(TCL):COMMIT(提交)、SAVEPOINT(保存点)和ROLLBACK(回滚)命令。

数据控制语言(DCL):GRANT(授予)和REVOKE(回收)命令。

1.3.1 使用DDL操作数据表

数据定义语言(DDL)中,CREATE TABLE语句用来创建新表,ALTER TABLE语句用来修改表结构,TRUNCATE TABLE语句用来删除表中所有记录,DROP TABLE语句用来删除表。本节结合以前学过的DDL的知识,主要介绍数据定义语言中较常用的CREATE TABLE命令和相对较陌生的TRUNCATE TABLE命令。

1.CREATE TABLE命令

创建表的语法如下。

    CREATE TABLE [schema.]table

    (column datatype [, column datatype [, …]] );

其中:

schema表示对象的所有者,即模式的名称。如果用户在自己的模式中创建表,则可以不指定所有者名称。

table表示表的名称。

column表示列的名称。

datatype表示该列的数据类型及其宽度。

创建表时,需要指定唯一的表名称、表内唯一的列名称、列的数据类型及其宽度。

示例3

创建一个stuInfo表,用来存储有关学员的个人信息,如姓名、学号和年龄等。

关键代码

SQL>CREATE TABLE stuInfo /*-创建学员信息表-*/

  (

  stuNo CHAR(6) NOT NULL, --学号,非空(必填)

  stuName VARCHAR2(20) NOT NULL, --学员姓名,非空(必填)

  stuAge NUMBER(3,0) NOT NULL, --年龄,非空(必填)

  stuID NUMBER(18,0), --身份证号,代表18位数字,小数位数为0

  stuSeat NUMBER(2,0) --座位号

  );

如果上述命令执行成功,将显示消息“表已创建”。

由此可以看出,表名应该严格遵循下列命名规则。

首字符应该为字母。

不能使用Oracle保留字来为表命名。

表名的最大长度为30个字符。

同一用户模式下的不同表不能具有相同的名称。

可以使用下划线、数字和字母,但不能使用空格和单引号。

提示

Oracle中的表名(还有列名、用户名和其他对象名)不区分大小写,系统会自动转换成大写。

Oracle中也有VARCHAR数据类型,但不建议使用,建议使用VARCHAR2,该数据类型是Oracle标准数据类型。

通过以上学习可以看出,Oracle在创建表时与MySQL基本没有区别。两者之间部分数据类型的默认映射情况如表1-3所示。

表1-3 Oracle和MySQL之间数据类型的默认映射情况

续表

2.TRUNCATE TABLE命令

如果存储在表中的数据不再使用,可以只删除表中的记录而不删除表结构。使用TRUNCATE TABLE 命令将删除表中的所有行且不记录日志,因此与DELETE命令删除表中全部记录相比,既节省资源,执行速度也较快。

TRUNCATE TABLE命令的语法如下。

 TRUNCATE TABLE <tablename>;

1.3.2 使用DML操作数据表

数据操纵语言(DML)用于检索、插入和修改数据库信息,是最常用的SQL命令,如INSERT(插入)、UPDATE(更新)、SELECT(选择)、DELETE(删除)。在学习MySQL时已经详细介绍过,这里只做补充介绍。

stuInfo表中的数据如表1-4所示。

表1-4 stuInfo表中的数据

1.从语法的角度介绍DML操作

(1)选择无重复的行

要防止选择重复的行,可以在SELECT命令中包含DISTINCT子句。

示例4

不重复显示所有学员的姓名和年龄。

  SQL>SELECT DISTINCT stuName,stuAge

    FROM stuInfo;

输出结果:

  stuName  stuAge

------------------------

  王五    15

  张三    18

  李四    20

  张三    20

注意

使用DISTINCT子句后,对筛除结果集中内容全部相同的行仅保留一行。

(2)带条件和排序的SELECT命令

要从表中选择特定的行,可以在 select命令中包含WHERE子句,它只能出现在FROM子句后面,而且只检索符合WHERE条件的行。要根据某个预定义的顺序显示行,可以使用ORDER BY子句,它还可以以升序或降序来排列行和多个列。

示例5

按照姓名升序排序。如果姓名相同,则按照年龄降序排序。

    SQL>SELECT stuNo,stuName, stuAge

       FROM stuInfo

      WHERE stuAge>17

        ORDER BY stuName ASC, stuAge DESC;

输出结果:

 stuNo stuName   stuAge

-----------------------------------

  2   李四    20

  5   张三    20

  4   张三    18

  1   张三    18

(3)使用列别名

列别名是为列表达式提供的另一个名称,位于列表达式后面,并显示在列标题中。列别名不会影响列的实际名称。

示例6

使用别名显示姓名、年龄和身份证号。

  SQL> SELECT stuName as “姓 名",stuAge as “年 龄", stuID as 身份证号

    FROM stuInfo;

输出结果:

    姓 名 年 龄 身份证号

    --------------------------

    张三  18

    李四  20

    王五  15

    张三  18

    张三  20

如列别名是含有特殊字符(如空格)的列标题,则使用双引号括起来。

(4)利用现有的表创建新表

Oracle允许利用现有的表创建新表,完成此操作的语法如下。

  CREATE TABLE <newtable>

    AS

  SELECT { * | column(s)}

  FROM <oldtable> [WHERE <condition> ];

此命令可以把现有表中的所有记录复制到新表中,也可以仅复制选定的列或只复制结构而不复制记录。

示例7

  SQL> CREATE TABLE newStuInfo1

     AS

    SELECT * FROM stuInfo;

上述语句将创建newStuInfo1表,此表是stuInfo表及其所有记录的完全复制。也可以用选定的列创建新表。下列语句将创建一个名为newStuInfo2的新表,它包括来自stuInfo表的学员姓名、学员编号和年龄的所有记录。

  SQL> CREATE TABLE newStuInfo2

     AS

   SELECT stuName,stuNo,stuAge FROM stuInfo;

还可以仅复制表的结构,而不复制记录。下列语句将创建一个名为newStuInfo3的新表,没有任何记录。

SQL> CREATE TABLE newStuInfo3

AS

SELECT * FROM stuInfo WHERE 1=2;

2.从使用技巧的角度介绍DML操作

(1)查看表中行数

示例8

执行语句:

  SQL> SELECT COUNT(*) FROM stuInfo; --效率较低

执行语句:

  SQL> SELECT COUNT(1) FROM stuInfo; --效率较高

(2)取出stuName、stuAge列不存在重复数据的记录

示例9

  SQL> SELECT stuName,stuAge

    FROM stuInfo

     GROUP BY stuName,stuAge

   HAVING(COUNT(stuName||stuAge) <2);

输出结果:

    stuName stuAge

    --------------------------

    王五   15

    李四   20

    张三   20

提示

“||”操作符为连接操作符,将在本章SQL操作符部分介绍,功能是将两部分内容连接在一起。因为示例9中COUNT函数的参数只能有一个,所以用连接操作符连接。

(3)删除stuName、stuAge列重复的行(保留一行)

示例10

   SQL>DELETE

     FROM stuInfo

    WHERE ROWID NOT IN(

         SELECT MAX(ROWID)

          FROM stuInfo

            GROUP BY stuName,stuAge

    );

删除后查看输出结果:

    SQL> SELECT * FROM stuInfo;

    stuNo  stuName stuAge  stuID  stuSeat

    ----------------------------------------

     1   张三  18   1

     2   李四  20   2

     3   王五  15   3

     5   张三  20   5

(4)查看当前所有数据量大于100万的用户表的信息

示例11

     SELECT table_name

      FROM user_all_tables a

     WHERE a.num_rows>1000000;

提示

user_all_tables为系统提供的数据视图,使用者可以通过查询该视图获得当前用户表的描述。

1.3.3 使用TCL管理事务

在Oracle数据库中,事务控制语句(TCL)主要由以下部分组成。

(1)COMMIT:提交事务,即永久保存事务中对数据库的修改。

(2)ROLLBACK:回滚事务,即取消对数据库所做的任何修改。

(3)SAVEPOINT:在事务中创建存储点。

(4)ROLLBACK TO <SavePoint_Name>:将事务回滚到存储点。

问答

问题1:何时开启事务?

解答:在Oracle中,事务在上一次事务结束以后,数据“第一次”被修改时自动开启。

问题2:何时结束事务?

解答:有以下两种情况。

(1)数据被提交。

发出COMMIT命令。

执行DDL或DCL语句后,当前事务自动被提交。

与Oracle分离,如退出PL/SQL Developer。

(2)数据被撤销。

发出ROLLBACK命令。

服务器进程异常结束。

DBA停止会话。

示例12

需求说明

事务控制语句应用举例,创建部门表(dept),插入部门记录。

关键代码

--执行步骤一:创建dept 表

SQL>CREATE TABLE dept

  (

  deptno NUMBER(2) PRIMARY KEY,      --部门编号

  dname VARCHAR2(14),           --部门名称

  loc VARCHAR2(13)             --地址

   );

--执行步骤二:插入数据

SQL>INSERT INTO dept VALUES (10,’ACCOUNTING’,’NEW YORK’);

SQL>INSERT INTO dept VALUES (20,'RESEARCH','DALLAS');

SQL>INSERT INTO dept VALUES (30,'SALES','CHICAGO');

SQL>INSERT INTO dept VALUES (40,'OPERATIONS','BOSTON');

SQL>COMMIT;

--执行步骤三:操作dept 表

SQL>INSERT INTO dept VALUES(50,'a',NULL);

SQL>INSERT INTO dept VALUES(60,'b',NULL);

SQL>SAVEPOINT a;

SQL>INSERT INTO dept VALUES(70,'c',NULL);

SQL>ROLLBACK TO SAVEPOINT a;

--执行步骤四:查看dept 表,有50、60 号部门

SQL>SELECT * FROM dept;

--执行步骤五:回滚

SQL>ROLLBACK;--没有50、60 号部门

--执行步骤六:查看dept 表

SQL>SELECT * FROM dept;

分析

(1)回滚到保存点“a”,表示保存点以后的所有数据操作取消,故只插入了两个部门。

(2)事务没有结束,必须再执行COMMIT或者ROLLBACK命令来结束事务。

注意

执行了3个INSERT语句,如果要提交,则只能提交所有的SQL语句,不能部分提交;

如果要回滚,则可以利用“事务保存点”来做局部回滚,此时事务并没有结束。

1.3.4 使用DCL控制权限

数据控制语言为用户提供权限控制命令。数据库对象(如表)的所有者对这些对象拥有控制权限。所有者可以根据自己的意愿决定其他用户如何访问对象,授予其他用户权限(INSERT、SELECT、UPDATE…),使他们可以在其权限范围内执行操作。例如,如果一个用户仅被授予对某个表的SELECT权限,那么他只可以查看数据,而不能执行其他任何DML 操作。授予的权限还可以由所有者随时撤销。第2章会详细介绍数据控制语言。

技能训练

上机练习2——创建员工表,并对表中数据进行插入查询操作

训练要点

(1)创建员工表。

(2)插入数据。

(3)添加约束。

(4)添加列。

(5)删除列。

(6)查询数据。

需求说明

使用System用户登录,创建员工表employee,并为员工编号创建主键约束,部门编号列创建外键约束。根据提供的资料插入数据,显示员工表中薪水从高到低排序的记录。

实现思路及关键代码

(1)使用System用户连接orcl数据库。

(2)创建employee表。

  SQL>CREATE TABLE employee /*-创建员工信息表-*/

    (empno NUMBER(4)NOT NULL,   --员工编号

    ename VARCHAR2(10),       --员工姓名

    job VARCHAR2(9),        --员工工种

    mgr NUMBER(4),         --上级经理编号

    hiredate DATE,          --受雇日期

    sal NUMBER(7,2),         --员工薪水

    comm NUMBER(7,2),       --福利

    deptno NUMBER(2)        --部门编号

    );

(3)插入数据。可以直接插入数据,也可以利用Scott用户下emp表中的数据进行插入。

插入Scott.emp表数据的代码如下。

INSERT INTO employee SELECT * FROM SCOTT.emp;

(4)添加约束。将员工编号作为主键,部门编号作为外键与部门表相关联。

外键约束的代码如下。

ALTER TABLE employee

  ADD CONSTRAINT FK_deptno

  FOREIGN KEY(deptno) REFERENCES dept(deptno);

(5)向employee表添加empTel_no和empAddress两列。创建empTel_no列以存储员工的电话号码,empAddress列以存储地址。

添加列的代码如下。

ALTER TABLE employee

  ADD (empTel_no VARCHAR2 (12),

    empAddress VARCHAR2(20));

(6)删除empTel_no和empAddress两列。

(7)按照薪水从高到低显示数据。

上机练习3——根据创建的员工表,实现分页查询

训练要点

分页查询。

需求说明

使用System用户登录,根据employee表的现有记录,查询员工表中按薪水从高到低排序的第5~9条记录。

实现思路及关键代码

(1)使用System用户连接orcl数据库。

(2)对员工表倒序排序并生成临时结果集A。

  SQL>SELECT *

     FROM (SELECT *

        FROM employee

        ORDER BY sal DESC) A;

(3)利用ROWNUM为临时结果集A给出每行序号并生成临时结果集B。

(4)对临时结果集B进行查询,查找序号为5~9的记录。

思考

该练习相对较复杂,一共用到3层子查询。当编写程序时,要认真思考每一步、每一个语句的原理。例如,ORDER BY语句是针对结果集进行排序,即先产生查询结果集,再排序。在上面的练习中就用到了这个原理,你是否已经感受到了呢?如果将SQL语句写成

  SELECT employee.*, ROWNUM FROM employee ORDER BY sal DESC;

得到的结果不符合上面练习的需求就是违背了这个原理。