资料
Mysql入门很简单.pdf 链接:https://pan.baidu.com/s/1SojegIqbWz8Dt8-iIjmJzA
提取码:qt4a
数据库篇
SHOW DATABASES; //显示数据库系统中已经存在的数据库
CREATE DATABASE 数据库名; //创建数据库
DROP DATABASE 数据库名; //删除数据库
表篇
注:在使用操作表语句前,首先要使用USE语句选择数据库。选择数据库语句的基本格式为“USE 数据库名”。否则会报错,1046;
CREATE TABLE 表名 ( 属性名 数据类型 [完整性约束条件],
属性名 数据类型 [完整性约束条件],
属性名 数据类型
);
表名不能为SQL语句的关键字,一个表可以有多个属性。定义时,字母大小写均可,各属性之间用逗号隔开,最后一个属性不需要加逗号。
利用CREATE TABLE创建表,必须给出下列信息:
- 新表的名字,在关键字CREATE TABLE之后给出;
- 表列的名字和定义,用逗号分隔;
- 有的DBMS还要求指定表的位置。
前面提到,不同DBMS的CREATE TABLE的语法有所不同,这个简单脚本也说明了这一点。这条语句在Oracle、PostgreSQL、SQL Server和SQLite中有效,而对于MySQL, varchar必须替换为text;对于DB2,必须从最后一列中去掉NULL。这就是对于不同的DBMS,要编写不同的表创建脚本的原因(参见附录A)。
提示:替换现有的表在创建新的表时,指定的表名必须不存在,否则会出错。防止意外覆盖已有的表,SQL要求首先手工删除该表(请参阅后面的内容),然后再重建它,而不是简单地用创建表语句覆盖它。
注意:理解NULL不要把NULL值与空字符串相混淆。NULL值是没有值,不是空字符串。如果指定’'(两个单引号,其间没有字符),这在NOT NULL列中是允许的。空字符串是一个有效的值,它不是无值。NULL值用关键字NULL而不是空字符串指定。
指定默认值
提示:使用DEFAULT而不是NULL值许多数据库开发人员喜欢使用DEFAULT值而不是NULL列,对于用于计算或数据分组的列更是如此。
更新表
- 理想情况下,不要在表中包含数据时对其进行更新。应该在表的设计过程中充分考虑未来可能的需求,避免今后对表的结构做大改动。□ 所有的DBMS都允许给现有的表增加列,不过对所增加列的数据类型(以及NULL和DEFAULT的使用)有所限制。
- 许多DBMS不允许删除或更改表中的列。
- 多数DBMS允许重新命名表中的列。
- 许多DBMS限制对已经填有数据的列进行更改,对未填有数据的列几乎没有限制。
- 在ALTER TABLE之后给出要更改的表名(该表必须存在,否则将出错);
- 列出要做哪些更改。
完整性约束条件
主键
主键有唯一值
单字段主键
属性名 数据类型 primary key //创建主键,写在属性名数据类型后面;
多字段主键
primary key(属性名 1,属性名2,属性名n)
两者的组合可以确定唯一的一条记录;
外键
外键不一定必须为父表的主键,但必须是唯一性索引,主键约束和唯一性约束都是唯一性索引;
外键可以为空值;
设置外键的基本语法规则如下:
CONSTRAINT 外键别名 FOREIGN KEY(属性 1.1,属性1.2,属性1.n)
REFERENCES 表名(属性2.1,属性2.2,属性2.n)
其中,“外键别名”参数是为外键的代号;“属性1”参数列表是子表中设置的外键;“表名”参数是指父表的名称;“属性2”参数列表是父表的主键。
设置表的非空约束
设置表的唯一性约束
设置表的属性值自动增加
查看表结构
DESCRIBE 表名; // 查看表基本结构语句,可缩写为desc 表名
SHOW CREATE TABLE 表名; //查看表详细结构语句 (包含存储引擎、字符编码)
删除表
DROP TABLE 表名;//删除没有被关联的普通表
删除父表需要先将外键删除,然后才能去删除父表。
字段篇
//通过ALTER TABLE语句
ALTER TABLE 旧表名 RENAME [TO] 新表名;//修改表名 TO参数是可选参数,是否在语句中出现不会影响语句的执行。
ALTER TABLE 表名 MODIFY 属性名 数据类型; //修改字段的数据类型(可以在此修改完整性约束条件)
ALTER TABLE 表名 CHANGE 旧属性名 新属性名 数据类型;//修改字段名和字段数据类型(两项都不可为空,都必须要填写,不然会报错)
MODIFY和CHANGE都可以改变字段的数据类型,不同的是,CHANGE可以在改变字段数据类型的同时,改变字段名。
ALTER TABLE 表名 ADD 属性名1 数据类型 [完整性约束条件] [FIRST | AFTER 属性名2]; //增加字段
属性名1为需要增加的字段的名称,完整性约束条件、FIRST、AFTER都是可选参数,FIRST、AFTER用来安排新字段的存放位置。否则默认为最后一个字段。
ALTER TABLE 表名 DROP 属性名;// 删除字段
ALTER TABLE 表名 MODIFY 属性名 数据类型 FIRST|AFTER 属性名2; //修改字段的排列位置
ALTER TABLE 表名 ENGINE = 存储引擎名; // 更改表的存储引擎
注:如果表中已经有很多的数据,改变引擎可能会造成意料之外的影响
查询(query)任何SQL语句都是查询。但此术语一般指SELECT语句。
说明:MySQL支持如果使用MySQL,应该知道对子查询的支持是从4.1版本引入的。MySQL的早期版本不支持子查询。
查询数据
1、基本查询语句
SELECT 属性表
FROM 表名和视图列表
[WHERE 条件表达式1]
[GROUP BY 属性名1 [HAVING 条件表达式2]]
[ORDER BY 属性名2 [ASC | DESC]]
"属性列表"参数表示查询的字段名;“表名和视图列表”参数表示从此处指定的表或者视图中查询数据,表和视图可以有多个;“条件表达式1”参数指定查询条件;“属性名1”参数指按该字段中的数据进行分组;“条件表达式2”参数表示满足该表达式的数据才能输出;“属性名2”参数指按该字段中的数据进行排序,排序方式由ASC和DESC两个参数指出;ASC参数表示按升序的顺序进行排序,这是默认参数;DESC参数表示按降序的顺序进行排序。
AS关键字
IN关键字
为什么要使用IN操作符?其优点如下。
- 在有很多合法选项时,IN操作符的语法更清楚,更直观。
- 在与其他AND和OR操作符组合使用IN时,求值顺序更容易管理。
- IN操作符一般比一组OR操作符执行得更快(在上面这个合法选项很少的例子中,你看不出性能差异)。
- IN的最大优点是可以包含其他SELECT语句,能够更动态地建立WHERE子句。
NOT关键字
NOTWHERE子句中用来否定其后条件的关键字。
对于这里的这种简单的WHERE子句,使用NOT确实没有什么优势。但在更复杂的子句中,NOT是非常有用的。例如,在与IN操作符联合使用时,NOT可以非常简单地找出与条件列表不匹配的行
[NOT] BETWEEN 取值1 AND 取值2
“取值1”表示范围的起始值,“取值2”表示范围的终止值。
LIKE
通配符(wildcard)
用来匹配值的一部分的特殊字符。
搜索模式(search pattern)由字面值、通配符或两者组合构成的搜索条件。
说明:请注意后面所跟的空格包括Access在内的许多DBMS都用空格来填补字段的内容。例如,如果某列有50个字符,而存储的文本为Fish bean bag toy(17个字符),则为填满该列需要在文本后附加33个空格。这样做一般对数据及其使用没有影响,但是可能对上述SQL语句有负面影响。子句WHEREprod_name LIKE 'F%y’只匹配以F开头、以y结尾的prod_name。如果值后面跟空格,则不是以y结尾,所以Fish bean bag toy就不会检索出来。简单的解决办法是给搜索模式再增加一个%号:'F%y%'还匹配y之后的字符(或空格)。更好的解决办法是用函数去掉空格
使用通配符的技巧正如所见,SQL的通配符很有用。但这种功能是有代价的,即通配符搜索一般比前面讨论的其他搜索要耗费更长的处理时间。这里给出一些使用通配符时要记住的技巧。
- 不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。
- 在确实需要使用通配符时,也尽量不要把它们用在搜索模式的开始处。把通配符置于开始处,搜索起来是最慢的。
- 仔细注意通配符的位置。如果放错地方,可能不会返回想要的数据。总之,通配符是一种极其重要和有用的搜索工具,以后我们经常会用到它。
“%”可以代表任意长度的字符串,长度可以为0;
IS NULL关键字用来判断字段的值是否为空值(NULL),如果字段的值为空值,则满足查询条件。
IS [NOT] NULL
AND关键字用来联合多个条件进行查询,只有同时满足所有条件的记录才会被查询出来。
条件表达式1 AND 条件表达式2 [...AND 条件表达式n]
OR关键字用来联合多个条件进行查询,但使用OR关键字时,只需要满足这几个查询条件的其中一个,就会被查询出来。
条件表达式1 OR 条件表达式2 [...OR 条件表达式n]
注:OR可以和AND一起使用。当两者一起使用时,AND要比OR先运算可以使用圆括号进行分割。
消除重复结果
SELECT DISTINCT 属性名 // “属性名”参数表示要消除重复记录的字段的名词
eg: SELECT DISTINCT d_id FROM empliyee
对查询结果进行排序
SELECT prod_name,prod_price,prod_id /* 注释*/ FROM products ORDER BY prod_price,prod_name
警告:在多个列上降序排序如果想在多个列上进行降序排序,必须对每一列指定DESC关键字。
WHERE字句操作符
注意:WHERE子句的位置在同时使用ORDER BY和WHERE子句时,应该让ORDER BY位于WHERE之后,否则将会产生错误(关于ORDER BY的使用,请参阅第3课)。
提示:何时使用引号如果仔细观察上述WHERE子句中的条件,会看到有的值括在单引号内,而有的值未括起来。单引号用来限定字符串。如果将值与字符串类型的列进行比较,就需要限定引号。用来与数值列进行比较的值不用引号。
空值检查
NULL无值(no value),它与字段包含0、空字符串或仅仅包含空格不同。
分组查询
SELECT vend_id,COUNT(*) AS num FROM products GROUP BY vend_id;上面的SELECT语句指定了两个列:
WITH ROLLUP关键字将会在所有记录的最后加上一条记录。该记录是上面所有记录的总和。(int类型则值相加、字符类型则一一列举出来)
1、单独使用GROUP BY关键字,查询的结果就是字段取值的分组情况。但每组只显示该组的第一条记录。
2、GROUP BY关键字可以和GROUP_CONCAT()函数一起使用时,GROUP_CONCAT()函数会把每个分组中指定字段值都显示出来。
3、GROUP BY关键字与集合函数一起使用时(集合函数包括COUNT()、SUM()、AVG()、MAX()、MIN());通常先使用GROUP BY关键字将记录分组,然后每组都使用集合函数进行计算。在统计时经常需要使用GROUP BY关键字和集合函数。
4、GROUP BY关键字与HAVING 一起使用,“HAVING条件表达式”可以限制输出的结果。
说明:“HAVING条件表达式”与“WHERE条件表达式”都是用来限制显示的。但是,两者起作用的地方不一样。“WHERE条件表达式”作用于表或者视图,是表和视图的查询条件。“HAVING条件表达式”作用于分组后的记录,用于选择满足条件的组。
5、按多字段进行分组
GROUP BY 属性名1,属性名2
在使用GROUP BY子句前,需要知道一些重要的规定。
- GROUP BY子句可以包含任意数目的列,因而可以对分组进行嵌套,更细致地进行数据分组。
- 如果在GROUP BY子句中嵌套了分组,数据将在最后指定的分组上进行汇总。换句话说,在建立分组时,指定的所有列都一起计算(所以不能从个别的列取回数据)。
- GROUP BY子句中列出的每一列都必须是检索列或有效的表达式(但不能是聚集函数)。如果在SELECT中使用表达式,则必须在GROUP BY子句中指定相同的表达式。不能使用别名。
- 大多数SQL实现不允许GROUP BY列带有长度可变的数据类型(如文本或备注型字段)。
- 除聚集计算语句外,SELECT语句中的每一列都必须在GROUP BY子句中给出。
- 如果分组列中包含具有NULL值的行,则NULL将作为一个分组返回。如果列中有多行NULL值,它们将分为一组。
- GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。
提示:HAVING支持所有WHERE操作符在第4课和第5课中,我们学习了WHERE子句的条件(包括通配符条件和带多个操作符的子句)。学过的这些有关WHERE的所有技术和选项都适用于HAVING。它们的句法是相同的,只是关键字有差别。
说明:HAVING和WHERE的差别这里有另一种理解方法,WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。这是一个重要的区别,WHERE排除的行不包括在分组中。这可能会改变计算值,从而影响HAVING子句中基于这些值过滤掉的分组。
说明:使用HAVING和WHEREHAVING与WHERE非常类似,如果不指定GROUP BY,则大多数DBMS会同等对待它们。不过,你自己要能区分这一点。使用HAVING时应该结合GROUP BY子句,而WHERE子句用于标准的行级过滤。
分组和排序
提示:不要忘记ORDER BY一般在使用GROUP BY子句时,应该也给出ORDER BY子句。这是保证数据正确排序的唯一方法。千万不要仅依赖GROUP BY排序数据。
用LIMIT限制查询结果的数量
LIMIT关键字有两种使用方式:不指定初始位置、指定初始位置。
SELECT prod_name FROM products LIMIT 5
LIMIT 记录数 //仅显示“记录数”的条数
SELECT prod_name FROM products LIMIT 2,2
LIMIT关键字可以指定从哪条记录开始显示,并且可以指定显示多少条记录。
LIMIT 初始位置,记录数 //“初始位置”参数指定从哪条记录开始显示;“记录数”参数辨识显示的条数 注:位置从零开始计数
使用集合函数查询(放置在SELECT后、FROM前)
聚集函数(aggregate function)对某些行运行的函数,计算并返回一个值。
COUNT()函数有两种使用方式:
- 使用COUNT(*)对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值。
- 使用COUNT(列或行)对特定列中具有值的行进行计数,忽略NULL值。
说明:NULL值如果指定列名,则COUNT()函数会忽略指定列的值为空的行,但如果COUNT()函数中用的是星号(*),则不忽略。
提示:在多个列上进行计算如本例所示,利用标准的算术操作符,所有聚集函数都可用来执行多个列上的计算。
提示:对非数值数据使用MAX()虽然MAX()一般用来找出最大的数值或日期值,但许多(并非所有)DBMS允许将它用来返回任意列中的最大值,包括返回文本列中的最大值。
在用于文本数据时,MAX()返回按该列排序后的最后一行。
说明:NULL值MAX()函数忽略列值为NULL的行。
提示:对非数值数据使用MIN()虽然MIN()一般用来找出最小的数值或日期值,但许多(并非所有)DBMS允许将它用来返回任意列中的最小值,包括返回文本列中的最小值。在用于文本数据时,MIN()返回该列排序后最前面的行。
说明:NULL值MAX()函数忽略列值为NULL的行。
注意:只用于单个列AVG()只能用来确定特定数值列的平均值,而且列名必须作为函数参数给出。为了获得多个列的平均值,必须使用多个AVG()函数。
说明:NULL值AVG()函数忽略列值为NULL的行。
- 对所有行执行计算,指定ALL参数或不指定参数(因为ALL是默认行为)。
- 只包含不同的值,指定DISTINCT参数。
注意:取别名在指定别名以包含某个聚集函数的结果时,不应该使用表中实际的列名。虽然这样做也算合法,但许多SQL实现不支持,可能会产生模糊的错误消息。
select子句顺序
子查询
可以把一条SELECT语句返回的结果用于另一条SELECT语句的WHERE子句。
注意:完全限定列名你已经看到了为什么要使用完全限定列名,没有具体指定就会返回错误结果,因为DBMS会误解你的意思。有时候,由于出现冲突列名而导致的歧义性,会引起DBMS抛出错误信息。例如,WHERE或ORDER BY子句指定的某个列名可能会出现在多个表中。好的做法是,如果在SELECT语句中操作多个表,就应使用完全限定列名来避免歧义。完全限定类名包含表名和列名,这样的话不会出现无法明确指定。
提示:格式化SQL包含子查询的SELECT语句难以阅读和调试,它们在较为复杂时更是如此。如上所示,把子查询分解为多行并进行适当的缩进,能极大地简化子查询的使用。顺便一提,这就是颜色编码起作用的地方,好的DBMS客户端正是出于这个原因使用了颜色代码SQL。
注意:子查询和性能这里给出的代码有效,并且获得了所需的结果。但是,使用子查询并不总是执行这类数据检索的最有效方法
提示:不止一种解决方案正如这一课前面所述,虽然这里给出的样例代码运行良好,但它并不是解决这种数据检索的最有效方法。
注意:只能是单列作为子查询的SELECT语句只能查询单个列。企图检索多个列将返回错误。
联结表
可伸缩(scale)能够适应不断增加的工作量而不失败。设计良好的数据库或应用程序称为可伸缩性好(scalewell)。
简单说,联结是一种机制,用来在一条SELECT语句中关联表,因此称为联结。使用特殊的语法,可以联结多个表返回一组输出,联结在运行时关联表中正确的行。
警告:完全限定列名就像前一课提到的,在引用的列可能出现歧义时,必须使用完全限定列名(用一个句点分隔表名和列名)。如果引用一个没有用表名限制的具有歧义的列名,大多数DBMS会返回错误。
笛卡儿积(cartesian product)由没有联结条件的表关系返回的结果为笛卡儿积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。
提示:叉联结有时,返回笛卡儿积的联结,也称叉联结(cross join)。
注意:不要忘了WHERE子句要保证所有联结都有WHERE子句,否则DBMS将返回比想要的数据多得多的数据。同理,要保证WHERE子句的正确性。不正确的过滤条件会导致DBMS返回不正确的数据。
内联结
目前为止使用的联结称为等值联结(equijoin),它基于两个表之间的相等测试。这种联结也称为内联结(inner join)。
SELECT vend_name,prod_name,prod_price FROM vendors,products WHERE vendors.vend_id = products.vend_id标准格式
SELECT vend_name,prod_name,prod_price FROM vendors INNER JOIN products NO vendors.vend_id = products.vend_id
说明:“正确的”语法ANSI SQL规范首选INNER JOIN语法,之前使用的是简单的等值语法。其实,SQL语言纯正论者是用鄙视的眼光看待简单语法的。这就是说,DBMS的确支持简单格式和标准格式,我建议你要理解这两种格式,具体使用就看你用哪个更顺手了。
多表联结
注意:性能考虑DBMS在运行时关联指定的每个表,以处理联结。这种处理可能非常耗费资源,因此应该注意,不要联结不必要的表。联结的表越多,性能下降越厉害。
注意:联结中表的最大数目虽然SQL本身不限制每个联结约束中表的数目,但实际上许多DBMS都有限制。请参阅具体的DBMS文档以了解其限制。
提示:多做实验可以看到,执行任一给定的SQL操作一般不止一种方法。很少有绝对正确或绝对错误的方法。性能可能会受操作类型、所使用的DBMS、表中数据量、是否存在索引或键等条件的影响。因此,有必要试验不同的选择机制,找出最适合具体情况的方法。
创建高级联结
使用表别名
- 缩短SQL语句;
- 允许在一条SELECT语句中多次使用相同的表。
需要注意,表别名只在查询执行中使用。与列别名不一样,表别名不返回到客户端。
自联结
提示:用自联结而不用子查询自联结通常作为外部语句,用来替代从相同表中检索数据的使用子查询语句。虽然最终的结果是相同的,但许多DBMS处理联结远比处理子查询快得多。应该试一下两种方法,以确定哪一种的性能更好。
自然联结
外联结
- 对每个顾客下的订单进行计数,包括那些至今尚未下订单的顾客;
- 列出所有产品以及订购数量,包括没有人订购的产品;
- 计算平均销售规模,包括那些至今尚未下订单的顾客。
注意:语法差别需要注意,用来创建外联结的语法在不同的SQL实现中可能稍有不同。
下面段落中描述的各种语法形式覆盖了大多数实现,在继续学习之前请参阅你使用的DBMS文档,以确定其语法。
提示:
外联结的类型要记住,总是有两种基本的外联结形式:左外联结和右外联结。它们之间的唯一差别是所关联的表的顺序。换句话说,调整FROM或WHERE子句中表的顺序,左外联结可以转换为右外联结。因此,这两种外联结可以互换使用,哪个方便就用哪个。
注意:FULL OUTER JOIN的支持Access、MariaDB、MySQL、Open Office Base和SQLite不支持FULL OUTER JOIN语法。
聚集函数可与联结一起使用
使用联结和联结条件
- 注意所使用的联结类型。一般我们使用内联结,但使用外联结也有效。
- 关于确切的联结语法,应该查看具体的文档,看相应的DBMS支持何种语法(大多数DBMS使用这两课中描述的某种语法)。
- 保证使用正确的联结条件(不管采用哪种语法),否则会返回不正确的数据。
- 应该总是提供联结条件,否则会得出笛卡儿积。
- 在一个联结中可以包含多个表,甚至可以对每个联结采用不同的联结类型。虽然这样做是合法的,一般也很有用,但应该在一起测试它们前分别测试每个联结。这会使故障排除更为简单。
组合查询
- 在一个查询中从不同的表返回结构数据;
- 对一个表执行多个查询,按一个查询返回数据。
提示:组合查询和多个WHERE条件多数情况下,组合相同表的两个查询所完成的工作与具有多个WHERE子句条件的一个查询所完成的工作相同。换句话说,任何具有多个WHERE子句的SELECT语句都可以作为一个组合查询,在下面可以看到这一点。
创建组合查询
提示:UNION的限制使用UNION组合SELECT语句的数目,SQL没有标准限制。但是,最好是参考一下具体的DBMS文档,了解它是否对UNION能组合的最大语句数目有限制。
注意:性能问题多数好的DBMS使用内部查询优化程序,在处理各条SELECT语句前组合它们。理论上讲,这意味着从性能上看使用多条WHERE子句条件还是UNION应该没有实际的差别。不过我说的是理论上,实践中多数查询优化程序并不能达到理想状态,所以最好测试一下这两种方法,看哪种工作得更好。
UNION规则
- UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔(因此,如果组合四条SELECT语句,将要使用三个UNION关键字)。
- UNION中的每个查询必须包含相同的列、表达式或聚集函数(不过,各个列不需要以相同的次序列出)。
- 列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含转换的类型(例如,不同的数值类型或不同的日期类型)。
提示:UNION与WHERE这一课一开始我们说过,UNION几乎总是完成与多个WHERE条件相同的工作。UNION ALL为UNION的一种形式,它完成WHERE子句完成不了的工作。如果确实需要每个条件的匹配行全部出现(包括重复行),就必须使用UNION ALL,而不是WHERE。
说明:其他类型的UNION某些DBMS还支持另外两种UNION:EXCEPT(有时称为MINUS)可用来检索只在第一个表中存在而在第二个表中不存在的行;而INTERSECT可用来检索两个表中都存在的行。实际上,这些UNION很少使用,因为相同的结果可利用联结得到。
提示:操作多个表为了简单,本课中的例子都是使用UNION来组合针对同一表的多个查询。实际上,UNION在需要组合多个表的数据时也很有用,即使是有不匹配列名的表,在这种情况下,可以将UNION与别名组合,检索一个结果集。
插入数据
- 插入完整的行;
- 插入行的一部分;
- 插入某些查询的结果。
提示:插入及系统安全使用INSERT语句可能需要客户端/服务器DBMS中的特定安全权限。在你试图使用INSERT前,应该保证自己有足够的安全权限。
存储到表中每一列的数据在VALUES子句中给出,必须给每一列提供一个值。如果某列没有值,如上面的cust_contact和cust_email列,则应该使用NULL值(假定表允许对该列指定空值)。各列必须以它们在表定义中出现的次序填充。
提示:INTO关键字在某些SQL实现中,跟在INSERT之后的INTO关键字是可选的。但是,即使不一定需要,最好还是提供这个关键字,这样做将保证SQL代码在DBMS之间可移植。
提示:总是使用列的列表不要使用没有明确给出列的INSERT语句。给出列能使SQL代码继续发挥作用,即使表结构发生了变化。
注意:小心使用VALUES不管使用哪种INSERT语法,VALUES的数目都必须正确。如果不提供列名,则必须给每个表列提供一个值;如果提供列名,则必须给列出的每个列一个值。否则,就会产生一条错误消息,相应的行不能成功插入。
注意:省略列
如果表的定义允许,则可以在INSERT操作中省略某些列。省略的列必须满足以下某个条件。
- 该列定义为允许NULL值(无值或空值)。
- 在表定义中给出默认值。这表示如果不给出值,将使用默认值。
注意:省略所需的值如果表中不允许有NULL值或者默认值,这时却省略了表中的值,DBMS就会产生错误消息,相应的行不能成功插入。
插入检索出的数据
说明:新例子的说明这个例子从一个名为CustNew的表中读出数据并插入到Customers表。为了试验这个例子,应该首先创建和填充CustNew表。CustNew表的结构与附录A中描述的Customers表相同。在填充CustNew时,不应该使用已经在Customers中用过的cust_id值(如果主键值重复,后续的INSERT操作将会失败)。
这个例子使用INSERT SELECT从CustNew中将所有数据导入Customers。SELECT语句从CustNew检索出要插入的值,而不是列出它们。SELECT中列出的每一列对应于Customers表名后所跟的每一列。这条语句将插入多少行呢?这依赖于CustNew表有多少行。如果这个表为空,则没有行被插入(也不产生错误,因为操作仍然是合法的)。如果这个表确实有数据,则所有数据将被插入到Customers。
提示:INSERT SELECT中的列名为简单起见,这个例子在INSERT和SELECT语句中使用了相同的列名。但是,不一定要求列名匹配。事实上,DBMS一点儿也不关心SELECT返回的列名。它使用的是列的位置,因此SELECT中的第一列(不管其列名)将用来填充表列中指定的第一列,第二列将用来填充表列中指定的第二列,如此等等。
提示:插入多行INSERT通常只插入一行。要插入多行,必须执行多个INSERT语句。INSERT SELECT是个例外,它可以用一条INSERT插入多行,不管SELECT语句返回多少行,都将被INSERT插入。
从一个表复制到另一个表
说明:DB2不支持DB2不支持这里描述的SELECT INTO。
说明:INSERT SELECT与SELECT INTO它们之间的一个重要差别是前者插入数据,而后者导出数据。
这条SELECT语句创建一个名为CustCopy的新表,并把Customers表的整个内容复制到新表中。因为这里使用的是SELECT *,所以将在CustCopy表中创建(并填充)与Customers表的每一列相同的列。要想只复制部分的列,可以明确给出列名,而不是使用*通配符。
MariaDB、MySQL、Oracle、PostgreSQL和SQLite使用的语法稍有不同。
- 任何SELECT选项和子句都可以使用,包括WHERE和GROUP BY;
- 可利用联结从多个表插入数据;
- 不管从多少个表中检索数据,数据都只能插入到一个表中。
提示:进行表的复制SELECT INTO是试验新SQL语句前进行表复制的很好工具。先进行复制,可在复制的数据上测试SQL代码,而不会影响实际的数据。
更新、修改数据
- 更新表中的特定行;
- 更新表中的所有行。
注意:不要省略WHERE子句在使用UPDATE时一定要细心。因为稍不注意,就会更新表中的所有行。使用这条语句前,请完整地阅读本节。
提示:UPDATE与安全在客户端/服务器的DBMS中,使用UPDATE语句可能需要特殊的安全权限。在你使用UPDATE前,应该保证自己有足够的安全权限。命令:update 表名 set 字段名 = 新内容
- 要更新的表;
- 列名和它们的新值;
- 确定要更新哪些行的过滤条件。
提示:在UPDATE语句中使用子查询UPDATE语句中可以使用子查询,使得能用SELECT语句检索出的数据更新列数据。
提示:FROM关键字有的SQL实现支持在UPDATE语句中使用FROM子句,用一个表的数据更新另一个表的行。如想知道你的DBMS是否支持这个特性,请参阅它的文档。
删除数据
提示:友好的外键第12课介绍了联结,简单联结两个表只需要这两个表中的公用字段。也可以让DBMS通过使用外键来严格实施关系(这些定义在附录A中)。存在外键时,DBMS使用它们实施引用完整性。例如要向Products表中插入一个新产品,DBMS不允许通过未知的供应商id插入它,因为vend_id列是作为外键连接到Vendors表的。那么,这与DELETE有什么关系呢?使用外键确保引用完整性的一个好处是,DBMS通常可以防止删除某个关系需要用到的行。例如,要从Products表中删除一个产品,而这个产品用在OrderItems的已有订单中,那么DELETE语句将抛出错误并中止。这是总要定义外键的另一个理由。
提示:FROM关键字在某些SQL实现中,跟在DELETE后的关键字FROM是可选的。但是即使不需要,也最好提供这个关键字。这样做将保证SQL代码在DBMS之间可移植。
提示:更快的删除如果想从表中删除所有行,不要使用DELETE。可使用TRUNCATETABLE语句,它完成相同的工作,而速度更快(因为不记录数据的变动)。
- 除非确实打算更新和删除每一行,否则绝对不要使用不带WHERE子句的UPDATE或DELETE语句。
- 保证每个表都有主键(如果忘记这个内容,请参阅第12课),尽可能像WHERE子句那样使用它(可以指定各主键、多个值或值的范围)。
- 在UPDATE或DELETE语句使用WHERE子句前,应该先用SELECT进行测试,保证它过滤的是正确的记录,以防编写的WHERE子句不正确。
- 使用强制实施引用完整性的数据库(关于这个内容,请参阅第12课),这样DBMS将不允许删除其数据与其他表相关联的行。
- 有的DBMS允许数据库管理员施加约束,防止执行不带WHERE子句的UPDATE或DELETE语句。如果所采用的DBMS支持这个特性,应该使用它。若是SQL没有撤销(undo)按钮,应该非常小心地使用UPDATE和DELETE,否则你会发现自己更新或删除了错误的数据。
注释
SELECT prod_name -- 注释 FROM products LIMIT 2,2注意:要在“--”后加一个空格,才会有效果
在一行的开始处使用#,这一整行都将作为注释。
SELECT prod_name # 注释 FROM products LIMIT 2,2注释从/*开始,到*/结束,/*和*/之间的任何内容都是注释。这种方式常用于给代码加注释,
SELECT prod_name /* 注释*/ FROM products LIMIT 2,2
视图
视图是虚拟的表。与包含数据的表不一样,视图只包含使用时动态检索数据的查询。为什么使用视图
- 重用SQL语句。
- 简化复杂的SQL操作。在编写查询后,可以方便地重用它而不必知道其基本查询细节。
- 使用表的一部分而不是整个表。
- 保护数据。可以授予用户访问表的特定部分的权限,而不是整个表的访问权限。
- 更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。
性能问题因为视图不包含数据,所以每次使用视图时,都必须处理查询执行时需要的所有检索。如果你用多个联结和过滤创建了复杂的视图或者嵌套了视图,性能可能会下降得很厉害。因此,在部署使用了大量视图的应用前,应该进行测试。
创建视图
说明:视图重命名删除视图,可以使用DROP语句,其语法为DROP VIEW viewname;覆盖(或更新)视图,必须先删除它,然后再重新创建。
利用视图简化复杂的联结
视图的规则较多,在创建视图前,有必要花点时间了解必须遵守的规定。
小结
视图为虚拟的表。它们包含的不是数据而是根据需要检索数据的查询。视图提供了一种封装SELECT语句的层次,可用来简化数据处理,重新格式化或保护基础数据。