第3章 创建、修改和删除表
SQL的数据定义功能主要体现在对表、索引、视图的创建、修改和删除功能。在SQL环境中,表是数据管理的基本单元,大部分SQL编程都与它有一定关系。SQL提供了3种语句用于定义、修改和删除表:CREAT TABLE语句用户创建表,ALTER TABLE语句用户修改表,DROP TABLE用于删除表。
3.1 表的基础知识
关系数据库通常包含多个表。数据库实际是表的集合,数据库的数据或信息都是存储在表中的。表是对数据进行存储和操作的一种逻辑结构。对用户而言,一个表表示一个数据库对象。例如,一个公司数据库中,会有雇员表、部门表、库存表、销售表、工资表等。
3.1.1 表的基本结构
数据库中的表与人们日常生活中使用的表格类似,也是由行(Row)和列(Column)组成。列由同类的信息组成,每列又称为一个字段,每列的标题称为字段名。行包括了若干列信息项,一行数据称为一条记录,表达有一定意义的信息组合。一个表由一条或多条记录组成,没有记录的表称为空表。每个表中通常都有一个主关键字,用于唯一地确定一条记录。
经常见到的成绩表就是一种表,它由行和列组成,并且可以通过名字来识别数据,列包含了列的名字、数据类型以及列的其他属性;行包含了列的记录或者数据。下面我们给出一个成绩表MARK,其中学号、姓名、语文、数学、英语都是列,而行包含了这个表的数据,即每个人的各科成绩,表的结构如图3-1所示。在SQL中,表有如下规定。
图3-1 MARK表结构
• 每张表都有一个名字,通常称为表名或关系名。表名必须以字母开头,最大长度为30个字符。
• 一张表可以由若干列组成。同一张表中,列名唯一,列名也称为属性名或字段。
• 同一列的数据必须有相同的数据类型。
• 表中的每一列值必须是不可分割的基本数据项。
• 表中的一行称为一个元组,相当于一条记录。
3.1.2 表的种类
在SQL中,并不是所有的表都是相同的。有些表是永久的,有些表则是临时的。有些表是模式对象,而有些表则包含在模块中,所有的模块表也是临时的。
说明
模块是指与主机编程语言相分离的SQL语句代码块,是一个包含SQL语句、例程或过程的对象。
SQL支持以下3种类型的表。
1.永久表
永久表保存存储在数据库中的SQL数据。它是一种最常见的表,如果没有特别说明,通常所说的表就是指永久表。只要表的定义存在,永久表就始终存在。它的创建语句为CREAT TABLE。
2.全局临时表
这种表只有在SQL会话的上下文引用该表的定义时实际的表才会存在,对话结束后表就不再存在,不能从一个SQL会话访问在另一个会话中创建的表。全局临时表的创建语句为CREAT GLOBAL TEMPORARY TABLE。
说明
SQL会话是指用户与SQL之间的连接。在连接期间,一系列的SQL语句被该用户调用,然后执行。
3.局部临时表
和全局临时表一样,局部临时表只有在SQL会话的过程中才能被引用,并且不能从另一个SQL会话对其进行访问。而与全局临时表不同之处在于:我们在SQL会话内的任何地方都可以访问全局临时表;而局部临时表只有在相关的SQL模块内才能被访问。局部临时表的创建语句为CREAT LOCAL TEMPORARY TABLE。
本章介绍的表的创建、修改和删除操作,所指的表都是永久表。
3.2 SQL数据类型
表中的列包含了列的名字、数据类型等属性,在介绍表的创建之前我们有必要介绍一下有关SQL支持的数据类型。SQL支持的数据类型主要包括预定义的数据类型和用户自定义的数据类型,其中,SQL预定义的数据类型主要包括:字符型数据、数字型数据、日期时间型数据和二进制数据。
3.2.1 字符型数据
在数据库表中,字符型数据是最常用的数据类型之一。例如经常用到的通信录中的姓名、地址、电子信箱甚至电话号码都是字符型的。
字符型变量又可分为两种——固定长度型字符变量和可变长度字符变量。固定长度型字符变量的字符数在数据库表创建的时候就指定了,并分配了存储空间。如指定通信录表姓名的字符数为20,如果用户输入姓名的字符数超过20,那么数据库只记录前20个字符;如果输入的字符数少于20,则数据库会自动在字符右边以空格填补到20个字符。
可变长度字符串可以存储任意长度的字符(其最大存储长度取决于采用的数据类型和数据库管理系统(DBMS)),它不需要预先指定存储长度,而是根据用户的输入动态地分配存储空间。既然可变长度字符变量用起来如此灵活,那么为什么我们还要采用固定长度字符变量呢?这是因为固定长度字符变量相比于可变长度字符变量,有以下两点优势。
• DBMS在进行排序或处理字符时,对固定长度字符变量的处理效率要远远高于可变长度字符变量。
• 许多DBMS不允许为可变长度字符变量创建索引,而只允许对固定长度字符变量创建索引。
SQL常用的字符型数据类型如表3-1所示。
表3-1 字符型数据类型
在数据库中,字符型数据的应用是十分灵活与广泛的。如前面提到的电话号码信息,虽然是一些数字信息,但是一般均采用字符型数据进行存储。如某人的电话号码为“01067846050”,采用数字数据存储,则最左边的“0”将被忽略,记录的信息实际为“1067846050”;而采用字符型数据进行存储则不会出现这个问题。
3.2.2 数字型数据
数字型数据主要用来存储数据信息。所有的数字数据类型都有精度,有些数据类型还有范围。精度是指可以存储的数字的数据,范围是指该值的小数部分(小数点右边的数字)数字的数目。比如,数字3428.54的精度是6,范围是2。范围不能是负数,也不能大于精度。范围为0表示该数字是一个整数,不包含小数部分。
多数数据库管理系统支持多种类型的数字型数据,不同的类型支持不同的数字形式与数字范围。SQL常用的数字型数据类型如表3-2所示。
表3-2 数字型数据类型
注意
不同的数据库管理系统所支持的数据类型不尽相同。如在SQL Server中,Number数据类型被写成Decimal或Numeric。
当处理那种只有两个值的数据时,我们可以使用Bit数据类型,如可使用Bit字段来存储Yes/No或者Ture/Fasle调查问题的答案。按照通常的约定,在Bit中的1表示True,0表示Fasle。
在数据库中,Number数据类型运用最普遍,它常用两种形式Number(size)和Number(size,d),具体含义如表3-3所示。
表3-3 Number数据类型的具体含义
另外,多数数据库管理系统提供了一种特殊的数字类型数据——货币数据类型。货币数据类型用于存储货币值,在使用货币数据类型时,应在数据前加上货币符号,系统才能辨识其为哪国的货币。如果不加货币符号,则默认为“¥”。
在SQL Server数据库系统中,货币数据类型有MONEY和SMALLMONEY两种类型,如表3-4所示。
表3-4 货币数据类型
3.2.3 日期数据类型
和数字型数据类型一样,DBMS提供了多种日期类型,用于存储不同精度和范围的时间、日期数据。SQL-92标准指定了5种日期数据类型,如表3-5所示。
表3-5 日期数据类型
然而,并不是所有的DBMS产品都支持所有这5种标准的SQL日期时间数据类型。不同DBMS中往往采用的时间、日期数据类型也不尽相同。
如在Oracle数据库中,日期型数据,用7个字节表示,每个日期型数据包含如下内容。
• Century(世纪)
• Year(年)
• Month(月)
• Day(天)
• Hour(小时)
• Minute(分)
• Second(秒)
在SQLServer数据库系统中,用到的日期和时间数据类型为DATETIME和SMALL DATETIME。
• DATETIME数据类型用于存储日期和时间的结合体。它可以存储从公元1753年1月1日零时起到公元9999年12月31日23时59分59秒之间的所有日期和时间,其精确度可达三百分之一秒,即3.33毫秒。DATETIME数据类型所占用的存储空间为8个字节,其中前4个字节用于存储1900年1月1日以前或以后的天数,数值分正负,正数表示在此日期之后的日期,负数表示在此日期之前的日期;后4个字节用于存储从此日零时起所指定的时间经过的毫秒数。如果我们在输入数据时省略了时间部分,则系统将12:00:00:000AM作为时间缺省值;如果省略了日期部分,则系统将1900年1月1日作为日期缺省值。
• SMALLDATETIME数据类型与DATETIME数据类型相似,但其日期时间范围较小,为从1900年1月1日到2079年6月6日。精度较低,只能精确到分钟,以30秒为界进行四舍五入。如DATETIME时间为14:38:30.283时,SMALLDATE TIME认为是14:39:00。SMALLDATETIME数据类型使用4个字节存储数据,其中前两个字节存储从基础日期1900年1月1日以来的天数,后两个字节存储此日零时起所指定的时间经过的分钟数。
说明
DATETIME数据类型在SQL Server、SQLBase、Sybase数据库系统中均支持。
下面我们以SQL Server数据库系统为准,介绍日期和时间的输入格式。
1.日期输入格式
日期的输入格式很多,大致可分为3类。
(1)英文+数字格式:此类格式中,月份可用英文全名或缩写,且不区分大小写;年和月日之间可不用逗号;年份可为4位或两位,当其为两位时,若值小于50,则视为20××年,若大于或等于50,则视为19××年;若日部分省略,则视为当月的1号。以下格式均为正确的日期格式。
June 212000 Oct 11999 January 2000 2000 February 2000 May 1 2000 1 Sep 99 June July 00
(2)数字+分隔符格式:允许把斜杠(/)、连接符(-)和小数点(.)作为用数字表示的年、月、日之间的分隔符,如下所示。
YMD : 2000/6/22 2000-6-22 2000.6.22 MDY : 3/5/2000 3-5-2000 3.5.2000 DMY : 31/12/1999 31-12-1999 31.12.2000
(3)纯数字格式:纯数字格式是以连续的4位、6位或8位数字来表示日期。如果输入的是6位或8位数字,系统将按年、月、日来识别,即YMD格式,并且月和日都是用两位数字来表示;如果输入的数字是4位数,系统认为这4位数代表年份,其月份和日缺省为此年度的1月1日,如下所示。
20000601——2000年6月1日 991212——1999年12月12日 1998——1998年
2.时间输入格式
在输入时间时,我们必须按“小时、分钟、秒、毫秒”的顺序来输入,在其间用冒号“:”隔开,毫秒部分可以用小数点“.”分隔,其后第一位数字代表十分之一秒,第二位数字代表百分之一秒,第三位数字代表千分之一秒。
当使用12小时制时,我们用AM(am)和PM(pm)分别指定时间是午前或午后,若不指定,系统默认为AM。AM与PM均不区分大小写,如下所示。
3:5:7.2pm——下午3时5分7秒200毫秒 10:23:5.123Am——上午10时23分5秒123毫秒
在SQL Server中,我们可以使用SET DATEFORMAT命令来设定系统默认的日期时间格式。
3.2.4 二进制数据类型
与前面介绍的数据类型不同,二进制数据类型不专门用于存储特定类型的数据,几乎可以存储任何类型的数据,包括图形图像、多媒体和字处理文档等。SQL中常用的二进制数据类型如表3-6所示。
表3-6 二进制数据类型
SQL Server数据库系统中,采用的二进制数据类型为BINARY和VARBINARY。一般情况下,BINARY数据类型长度固定,因此它比VARBINARY类型的处理速度快。我们分别作一下简单介绍。
1.BINARY
BINARY数据类型用于存储二进制数据。其定义形式为BINARY(n),n表示数据的长度,取值为1到8000。在使用时必须指定BINARY类型数据的大小,至少应为1个字节。BINARY类型数据占用n+4个字节的存储空间,在输入数据时必须在数据前加上字符“0x”作为二进制标识,例如要输入“abc”则应输入“0xabc”,如果输入的数据过长,将会截掉其超出部分;如果输入的数据位数为奇数,则会在起始符号“0x”后添加一个0,如上述的“0xabc”会被系统自动变为“0x0abc”。
2.VARBINARY
VARBINARY数据类型的定义形式为VARBINARY(n)。与BINARY类型相似,n的取值也为1到8000,如果输入的数据过长,将会截掉其超出部分。不同的是,VARBINARY数据类型具有变动长度的特性,因为VARBINARY数据类型的存储长度为实际数值长度+4个字节。当BINARY数据类型允许NULL值时,将被视为VARBINARY数据类型。
3.2.5 文本和图形数据类型
另外,SQL Server还提供了文本和图形数据类型,这类数据类型用于存储大量的字符或二进制数据,分别介绍如下。
1.TEXT
TEXT数据类型用于存储大量文本数据,其容量理论上为1~231-1(2147 483647)个字节,在实际应用时需要视硬盘的存储空间而定。
2.NTEXT
NTEXT数据类型与TEXT类型相似。不同的是,NTEXT类型采用UNICODE标准字符集(Character Set),因此其理论容量为230-1(1073 741823)个字节。
3.IMAGE
IMAGE数据类型用于存储大量的二进制数据(Binary Data),理论容量为231-1(2147 483647)个字节,存储数据的模式与TEXT数据类型相同。它通常用来存储图形等OLE(Object Linking and Embedding,对象连接和嵌入)对象。在输入数据时同BINARY数据类型一样,我们必须在数据前加上字符“0x”作为二进制标识。
3.2.6 自定义数据类型
除了使用系统提供的数据类型外,用户还可以用自定义的数据类型来定义表的列或声明变量。SQL提供的CREATE TYPE语句用于自定义数据类型,如下面语句将创建一个基于NUMERIC数据类型的用户自定义的类型。
CREATE TYPE Wage AS NUMERIC(6,1)
创建了这个用户定义的数据类型后,我们就可以像其他预定义数据类型一样使用了。因此Wage数据类型就代表NUMERIC数据类型,其精度为6,范围为1。
然而,创建自定义数据类型的方法和数据库产品有很大的关系,如在SQL Server中,我们就不能采用CREATE TYPE语句定义用户的数据类型,可以采用其提供的企业管理器(Enterprise Manager)创建一个用户定义的数据类型。
实例1 使用企业管理器建一个用户定义的数据类型
我们同样以创建Wage数据类型为例,讲解其创建步骤。
(1)启动企业管理器(Enterprise Manager),找到要操作的数据库。
(2)右击该数据库名,打开快捷菜单,选择“新建”→“用户定义的数据类型”命令,如图3-2所示。
图3-2 企业管理器执行操作界面
说明
也可以通过主窗口“操作”→“新建”→“用户定义的数据类型”菜单项执行该命令。
(3)在弹出的用户定义的数据类型对话框中,在“名称”区域键入数据类型的名称。对于本例,键入“Wage”。
(4)在“数据类型”下拉列表中选择一个数据类型,对于本例来说,选择“numeric”。
(5)在“长度”区域键入数据长度,对于本例键入“6,1”。如果想要对用户定义的数据类型的列允许NULL值,则选中“允许NULL值”复选框,对话框的设置如图3-3所示。
图3-3 用户定义的数据类型对话框
(6)单击“确定”按钮即可实现数据类型的定义。
完成后,企业管理器将把数据类型定义保存在DBMS的系统表中。这样我们就可以使用刚才定义的数据类型了。
3.3 表的创建(CREATE)
常用的创建数据库表的方法有两种:一种是通过数据库管理系统(DBMS)提供的交互式创建工具创建,另一种是通过SQL直接创建。本节主要讨论通过SQL直接创建数据库表。
3.3.1 创建基本表
在SQL中,创建数据库表的基本关键字为Create Table,在其后要指明创建的数据库表的名称,接着要分别定义表中各列的名称、数据类型等。语法如下。
CREATE TABLE table_name ( column_name1 data_type, column_name2 data_type, ...... )
表的名字对大小写不敏感。表名要紧接在Create Table关键词的后面,且第一个字符必须是A~Z之一,其余的字符可以是字母,也可以是“_”、“#”、“$”和“@”等符号。表中各列的定义在括号中完成,且各列之间以逗号隔开。不同的表,其列名可以相同,但是在同一个表中,不允许出现相同的列名。在定义了列名后,我们一定要指明该列的数据类型。
说明
前面已经讲过,如果没有特别说明,本书的实例代码均是在SQL Server数据库系统中通过查询分析器编译运行的。
实例2 创建数据库表
创建一个学生表(student),包含学号(sno,DECIMAL型)、姓名(sname,CHAR型)、性别(sex,CHAR型)、出生年月(birthday,DATETIME型)、系号(dno,CHAR型)等几个字段信息。实现代码如下。
CREATE TABLE student ( sno DECIMAL, sname CHAR, sex CHAR, birthday DATETIME, dno CHAR )
运行结果如图3-4所示。
图3-4 学生表
说明
运行结果为在SQL Server中通过企业管理器查看生成表的结构,下同。
默认情况下,SQL Server会根据类型不同,为每个字段设定最大数据长度。用户实际创建表时,都需要根据自己的数据特点,定义字段的最大存储长度。
实例3 指定表字段的最大长度
如果最多有几万个学生,那么学号sno则有五位数就可以了,即可以定义为:sno DECIMAL (5)。对实例2,指定最大字段长度可用以下代码实现。
CREATE TABLE student ( sno DECIMAL (5) , sname CHAR(6) , sex CHAR(2) , birthday DATETIME , dno CHAR(3) )
运行结果如图3-5所示。
图3-5 修正的学生表
注意
创建表,必须要保证该表名在数据库中不存在,否则数据库会提示创建失败。如果需要创建已经存在的表,我们必须先将原来的表删除,再重新创建。
3.3.2 非空约束
SQL允许表中列的值为NULL,即空值。表中某列的值为NULL,表明该列不存在值。创建数据库表时,数据库管理系统允许通过NOT NULL关键字为创建的每列指明非空约束,这样在添加数据时,如果该列的值为NULL,那么数据库就会报错,添加失败。
非空约束在实际应用中是十分有用的,它保证了信息的完整性,避免了由于用户的误操作而导致的数据的不完整。
实例4 创建非空约束
创建与3.3.1节相同的学生表(student),为学号(sno)、姓名(sname)、性别(sex)3列添加非空约束。代码如下。
CREATE TABLE student ( sno DECIMAL(5) NOT NULL, sname CHAR(6) NOT NULL, sex CHAR(2) NOT NULL, birthday DATETIME , dno CHAR(3) )
运行结果如图3-6所示。
图3-6 非空约束表
实例4 创建的表中,sno、sname和sex 3列为非空(NOT NULL)的,即如果插入的值为NULL,则数据库会报错,插入失败。而余下的birthday和dno两列则允许为空(NULL)。在创建表时,各列缺省设置认为是允许为NULL的,除非指明NOT NULL属性。
例如,通过如下代码向student表中添加数据。
INSERT INTO student(sno,sex,birthday,dno) VALUES (12,'男','1979/9/4',5)
由于没有给非空字段sname赋值,数据库系统会报告错误信息,插入操作被取消。在查询分析器的Result窗格将显示如下信息。
Cannot insert the value NULL into column 'sname', table 'pubs.dbo.student'; column does not allow nulls. INSERT fails. The statement has been terminated.
实例5 允许为空字段的插入操作
当然,如果对允许为空的字段不给赋值,插入操作也会正确地执行,如下面代码所示。
INSERT INTO student(sno,sname,sex,dno) VALUES (12,'王小二','男',5) SELECT * FROM student
运行结果如图3-7所示。
图3-7 数据插入
我们可以发现,虽然没有对birthday字段赋值,但是因为它可以为NULL,所以插入数据操作能够成功执行。
注意
这里所讲的NULL与空字符串是不同的。如,我们可以通过“‘ ’”(两个单引号,中间没有任何值)设置空字符串,但它不是NULL。
3.3.3 DEFAULT指定缺省值
采用SQL创建表时,允许为每列指定缺省值。即向表中插入值时,当不指明该列的值时,数据库会自动地采用缺省值。指定缺省值是通过DEFAULT关键字来实现的。
具有缺省值的列定义的简单语法如下。
<column name> <data type> DEFAULT <default value>
在DEFAULT关键字后面指定该列的缺省值,该值可以是SQL数据值、日期值或者与会话有关的用户功能。无论<default value>使用什么类型的值,它都必须符合在列定义中指定的数据要求。比如,如果我们使用INT数据类型,那么指定的默认值也必须是INT数据类型的。
实例6 指定表中列的缺省值
创建与3.3.2节相同的学生表(student),为性别(sex)列指定缺省值为“男”。
实例的代码如下。
CREATE TABLE student ( sno DECIMAL(5) NOT NULL, sname CHAR(6) NOT NULL, sex CHAR(2) NOT NULL DEFAULT '男', birthday DATETIME, dno CHAR(3) )
当向表student中插入记录时,如果不指明sex的值,则数据库会为其添加缺省值“男”,如下面的插入数据代码。
INSERT INTO student(sno,sname,dno) VALUES (12,'王小二',5)
代码并没有给sex字段插入数据,而sex字段设置有非空约束,但是因为在创建表时,为sex字段指定了默认值,所以数据库系统并没有报错,插入操作成功完成。
SELECT * FROM student
运行结果如图3-8所示。
图3-8 查询结果表
在设置日期类型值时,我们通常指定当前日期为缺省日期。在SQL Server中,我们可采用DEFAULT GETDATE()指定当前日期为缺省日期,而在Oracle数据库系统则是通过DEFAULT SYSDATE来实现。表3-7列出了不同数据库系统获取当前日期的函数。
表3-7 获取当前日期的函数
3.4 表的修改
在实际设计和创建数据库表的时候,我们很难做到一步到位,往往需要在使用的过程中,不断地修改完善。在SQL中,我们可以采用ALTER TABLE命令来修改已经创建的表结构。使用ALTER TABLE命令可以向表中增加新列、删除已有的列、也可以修改已经创建的列。
注意
对表定义的修改,不同的数据库系统有不同的限制。例如,Oracle数据库就限制对列的修改只能是加大列的宽度而不能是缩小,而且不能删除列。
3.4.1 增加新列
给表增加新列在数据库的应用中是经常需要用到的。当一个数据库表创建完成后,在使用过程中随着时间的推移,往往就需要向其中增加新的信息。如前面介绍的student表,应用中我们还需要统计每个学生的Email信息,由于student表中可能包含了大量的数据,再重新创建表显然已经不现实了,这时,就可以采用SQL提供的ADD关键字向表中添加新列。语法如下。
ALTER TABLE table_name ADD column_name data_type
table_name指的是要修改的表的名字,ADD关键字后面接要创建列的列名、数据类型等,当然也可以对列设置非空约束和缺省值。
当用ALTER TABLE语句向表中添加新列时,DBMS向表的列定义的尾部添加列,即在查询中将位于表的最右边。除非指定默认值,DBMS为已有行上的新列设NULL值。
由于DBMS为已有行上的新列设NULL值,当使用ALTER TABLE语句向表中添加新列时,我们不能简单地添加NOT NULL约束,还必须提供缺省值。因为如果没有提供缺省值,DBMS假设已有行上的新列为NULL值,这就和NOT NULL约束相抵触。当然,如果表中不存在数据,则不存在这个问题。
实例7 向已有表中增加非空约束的列
这里向3.3.3节创建的学生表(student)中添加一列Email信息,并要求该列具有非空约束。
因为该student表中已经有了一条记录,所以如果对增加列采用NOT NULL约束而不指定缺省值,如下面的代码所示。
ALTER TABLE student ADD Email CHAR(15) NOT NULL
则SQL Server数据库系统会报错,在查询分析器的Result窗格将显示如下信息。
ALTER TABLE only allows columns to be added that can contain nulls or have a DEFAULT definition specified. Column 'Email' cannot be added to table 'student' because it does not allow nulls and does not specify a DEFAULT definition.
实例8 增加非空约束的列,指明缺省值
对增加的列采用NOT NULL约束,必须指明缺省值。实例代码如下。
ALTER TABLE student ADD Email CHAR(15) NOT NULL DEFAULT 'No Email'
运行结果如图3-9所示。
图3-9 增加列
查看student表中的数据,代码如下。
SELECT * FROM student
结果如图3-10所示。
图3-10 增加列结果
我们可以发现,在表的最右边增加了一列Email,并将记录中该列的值设为默认值“No Email”。
3.4.2 删除列
同样,在使用数据库表的过程中,如果其某列信息已经无效或不再需要,为了节省数据库空间,提高查询性能,我们可以采用DROP COLUMN关键字删除表中的某列,语法如下。
ALTER TABLE table_name DROP COLUMN column_name
table_name是要修改的表的名字,DROP COLUMN关键字后面接要删除列的名字。当然,一次可以删除多个列,只需要在DROP COLUMN关键字后面依次列出要删除的列的名字,中间用逗号分开即可。
实例9 删除学生表中的birthday列
将3.4.1节中最终生成的学生表(student)中的birthday列删除。实例代码如下。
ALTER TABLE student DROP COLUMN birthday
运行结果如图3-11所示。
图3-11 删除列
我们可以发现birthday列被删除,当然,birthday列中的数据也就不复存在。
然而,在SQL Server中,那些赋予默认值的列、作为主键或者在另外表中标识为外键约束的列将不能被删除。而具有非空约束的列则可以被删除。
实例10 直接删除具有非空约束的列
继续删除student表中的sex列。
ALTER TABLE student DROP COLUMN sex
查询分析器的Result窗格将显示如下信息。
Server: Msg 5074, Level 16, State 1, Line 1 The object 'DF__student__sex__4CA06362' is dependent on column 'sex'. Server: Msg 4922, Level 16, State 1, Line 1 ALTER TABLE DROP COLUMN sex failed because one or more objects access this column.
由此可见,;因为sex列设有默认值,所以系统不允许直接删除sex列。如果一定要删除该列,我们必须首先采用ALTER TABLE语句删除默认值约束。语法如下。
ALTER TABLE table_name DROP CONSTRAINT constraint_name
constraint_name为要删除的约束对应的约束名,是由DBMS创建的。对于sex列的缺省值约束来说,约束名可从直接删除该列系统的出错报告信息中获取,为“DF__student__sex__4CA06362”。
实例11 删除约束后,删除非空约束的列
删除sex列的约束后,再删除sex列的代码如下。
ALTER TABLE student DROP CONSTRAINT DF__student__sex__4CA06362 ALTER TABLE student DROP COLUMN sex
运行结果如图3-12所示。
图3-12 删除列结果
可见,sex列已经被成功删除。
注意
DBMS赋予未命名约束的名称在每次创建约束时都不相同,即使删除并重新指定同一约束,其名称也是不同的。
3.4.3 修改列
如果发现数据库表中某列的结构不能满足实际的需求,在不破坏数据的情况下,SQL允许利用MODIFY关键字修改表中某列的结构。常用的修改操作主要包括字符长度限制的修定和非空约束的限制或取消,语法如下。
ALTER TABLE table_name MODIFY column_name data_type
table_name是要修改的表的名字,MODIFY关键字后面接要修改列的列名和修改后的数据条件。
注意
在SQL Server数据库系统中,并不支持MODIFY关键字。要修改数据库中的列,我们可以通过ALTER COLUMN关键字实现,即将MODIFY替换为ALTER COLUMN即可。
实例12 修改列
在3.4.2节中最终生成的学生表(student)中,将Email列的最大字符数由15增加到25。实例代码如下。
ALTER TABL student ALTER COLUMN Email CHAR(25)
运行结果如图3-13所示。
图3-13 修改列
我们可以发现,Email列的数据允许的最大长度已经更改为25。
注意
用户可以通过MODIFY关键字或者ALTER COLUMN关键字增加或减少表中某列的最多字符数,但是,当要减少表中某列的最多字符数要特别慎重。当数据库表中该列存在已有记录的字符数多于减少后的最多字符限制时,表的修改就会失败。
当然,我们也可以通过MODIFY或者ALTER COLUMN关键字增加或取消表中某列的非空约束。
实例13 取消student表中sname列的非空约束
ALTER TABLE student ALTER COLUMN sname CHAR(10) NULL
运行结果如图3-14所示。
图3-14 修改列结果
修改表中的某列,为其增加非空约束时,我们必须要确保该列已经存在的所有记录中没有NULL值。
与许多DBMS产品不同,SQL Serve不仅允许改变列的数据长度,而且还允许改变其数据类型。但是当列为以下情况时,我们则不能改变其数据类型。
• 列是TEXT、IMAGE、NTEXT或TIMESTAMP类型。
• 列是索引的一部分。
• 列是PRIMARY或者KEY FOREIGN KEY的一部分。
• 列具有缺省值约束。
• 列具有CHECK约束。
• 列具有UNIQUE约束。
当改变列的数据类型时,列中已有的数据必须与新的数据类型兼容。比较常用的转换是从INTEGER转换为字符型,因为CHAR列可保存数字、字母和特殊符号。但是,如果要将CHAR类型转换为INTEGER类型,必须保证表的每行上所转换的CHAR字段具有数字或NULL值。
实例14 将student表的sno列的类型转换为CHAR类型
ALTER TABLE student ALTER COLUMN sno CHAR(5) NOT NULL
运行结果如图3-15所示。
图3-15 修改列类型
我们可以发现,sno列的数据类型已经变为CHAR类型了。
SELECT * FROM student
结果如图3-16所示。
图3-16 查看结果
sno列的记录并没有变化,实际上只是变为字符“12”而已。
注意
使用ALTER TABLE修改表要特别慎重,因为有些操作对数据库影响很大,且是不可逆的。如用户采用DROP COLUMN关键字删除表中的某列,则该列所有已经存在的数据记录均会被删除。
3.5 表的删除与重命名
3.5.1 重命名表
在创建表的时候,表的名字就被确定了,但在实际应用中,有时候需要修改表的名字而不改变其他信息,这时候就可以采用SQL的重命名表命令。
不同的DBMS对表的重命名提供的命令不尽相同。在DB2、MySQL,、Oracle数据库系统中可采用RENAME关键词,而在SQL Server和Sybase数据库系统中可采用SP_RENAME关键词重命名表。
实例15 重命名表
将学生表(student)重命名为Mystudent。
SP_RENAME 'student' , 'Mystudent'
运行结果如下。
The object was renamed to 'Mystudent'
此时我们会发现数据库中的student表不见了,取而代之的是表Mystudent。
除了可以对表进行重命名以外,我们还可以对表中的列进行重命名。在SQL Server数据库系统中,重命名表中的列同样使用SP_RENAME关键词。
实例16 重命名表中的列
将Mystudent表(由student表重命名生成的表)中的sname列更名为Studentname。
SP_RENAME 'Mystudent.sname' , 'Studentname', 'COLUMN'
运行结果如下。
The COLUMN was renamed to 'Studentname'.
此时,表Mystudent的结构如图3-17所示。
图3-17 重命名表结果
3.5.2 删除表
表的删除非常容易,使用DROP TABLE关键词即可实现。语法如下。
DROP TABLE table_name
只要在DROP TABLE关键词后面接上要删除表的名字即可。这里表的删除不仅删除了表内存储的数值,而是整个表结构都被删除了,也就是该表不存在了。下面我们通过一个具体的实例说明表的删除操作。
实例17 删除表
将学生表(Mystudent)删除。实例代码如下。
DROP TABLE Mystudent
执行该语句后,我们会发现Mystudent已经从数据库中删除。
注意
当某表与其他的表存在关联关系时,一些DBMS会不允许用户通过DROP TABLE语句来删除该表,只有当这种关联关系被删除以后,才能删除该表。
3.6 创建、删除数据库
本章主要介绍表的相关操作,然而表是存在于特定的数据库中的。如本章前面表的有关操作实例都是在pubs数据库中进行的。对于那些支持多数据库的数据库系统,一般都支持基于SQL语言的CREATE DATABASE语句创建数据库,这些数据库系统包括Oracle、MySQL、SQL Server等。而删除数据库则通过DROP DATABASE语句来实现。
3.6.1 数据库的创建
虽然我们可以基于CREATE DATABASE语句创建数据库,但是该语句可以定义哪些参数,执行该语句需要什么许可,以及系统如何实现数据库对象等,都会因为数据库产品的不同而不同。不过,大部分产品都使用相同的语法创建数据库对象。语法如下。
CREATE DATABASE database_name additional parameters
这里,CREATE DATABASE语句创建数据库,除了要指明数据库名字外,还需要设置数据库的一些基本参数。
3.6.2 SQL Server中数据库的创建
SQL Server允许为每个数据库服务创建多个数据库。在MS-SQL Server中,使用CREATE DATABASE语句创建数据库的完整语法如下所示。
CREATE DATABASE database_name [ ON [ < filespec > [ ,...n ] ] [ , < filegroup > [ ,...n ] ] ] [ LOG ON { < filespec > [ ,...n ] } ]
其中< filespec >定义为:
( [ NAME = logical_file_name , ] FILENAME = 'os_file_name' [ , SIZE = size ] [ , MAXSIZE = { max_size | UNLIMITED } ] [ , FILEGROWTH = growth_increment ] ) [ ,...n ])
各关键字和选项的含义如表3-8所示。
表3-8 CREATE DATABASE语句中关键字和选项的含义
注意
数据库文件的后缀名为“.mdf”,而事务处理日志文件的后缀名为“.ldf”。
实例18 创建数据库
在MS-SQL Server中,创建一数据库Sales。
CREATE DATABASE Sales ON ( NAME = Sales_dat, FILENAME = 'c:\program files\microsoft sql server\mssql\data\saledat.mdf', SIZE = 10, MAXSIZE = 50, FILEGROWTH = 5 ) LOG ON ( NAME = 'Sales_log', FILENAME = 'c:\program files\microsoft sql server\mssql\data\salelog.ldf', SIZE = 5MB, MAXSIZE = 25MB, FILEGROWTH = 5MB )
在查询分析器中,运行该代码,即可完成数据库Sales的创建。此时查询分析器的Result窗格将显示如下信息。
The CREATE DATABASE process is allocating 10.00 MB on disk 'Sales_dat'. The CREATE DATABASE process is allocating 5.00 MB on disk 'Sales_log'.
通过SQL Server企业管理器查看数据库Sales的结构和属性,结果如图3-18所示。
图3-18 数据库Sales的结构和属性
3.6.3 删除数据库
与表的删除类似,数据库的删除是通过DROP DATABASE语句来实现的,语法如下。
DROP DATABASE database_name [ ,...n ]
实例19 删除数据库
删除数据库Sales。
DROP DATABASE Sales
此时,Sales数据库被删除,查询分析器的Result窗格将显示如下信息。
Deleting database file 'c:\program files\microsoft sql server\mssql\data\ salelog.ldf'. Deleting database file 'c:\program files\microsoft sql server\mssql\data\ saledat.mdf'.
如果该数据库正在被使用,通过DROP DATABASE语句删除数据库操作就会失败。