MySQL

关系型数据库设计规则

关系型数据库的典型数据结构就是数据表,这些数据表的组成都是结构化的。将数据放到表中,表再放到库中。一个数据库中可以有多个表,每个表都有一个名字,用来标识自己。表名具有唯一性。

表具有一些特性,这些特性定义了数据在表中如何存储,类似类。

表、记录、字段

E-R(entity-relationship,实体-联系)模型中有三个主要概念:实体集、属性、联系集。

一个实体集(class)对应数据库中一个表(table),一个实体(instance)则对应数据库表中的一行(row),也称为一条记录(record)。一个属性(attribute)对应数据库表中的一列(column),也称为一个字段(field)。

表的关联关系

表与表之间的数据记录有关系(relationship)

一对一(one-to-one)

在实际开发中应用的不多,因为一对一可以创建成一张表

  1. 举例

    设计学生表:学号、姓名、手机号码、班级、系别、身份证号码、家庭住址、籍贯、紧急联系人

    拆为两个表:两个表的记录是一一对应关系

    基础信息表:学号、姓名、手机号码、班级、系别

    档案信息表:学号、身份证号、家庭住址、籍贯、紧急联系人

  2. 两种建表原则

    外键唯一:主表的主键和从表的外键(唯一),形成主外键关系,外键唯一

    外键是主键:主表的主键和从表的主键,形成主外键关系

    image-20220129113107954

一对多(one-to-many)

常见实例场景:客户表和订单表,分类表和商品表,部门表和员工表

  1. 举例

    员工表:编号、姓名、...所属部门

    部门表:编号、名称、简介

  2. 一对多建表原则

    在从表(多方)创建一个字段,字段作为外键指向主表(一方)的主键

image-20220129113622697

多对多(many-to-many)

要表示多对多关系,必须创建第三个表,该表通常称为联接表,它将多对多关系划分为两个一对多关系,将这两个表的主键都插入到第三个表中

  1. 举例

    学生信息表:一行代表一个学生的信息(学号、姓名、班级)

    课程信息表:一行代表一个课程的信息(课程编号、授课老师)

    选课信息表:一个学生可以选多门课,一门课可以被多个学生选

检索数据

SELECT语句

  1. 检索单个列

    SELECT 列名 FROM 表名;
    
  2. 检索多个列

    SELECT 列名1,列名2,列名3 FROM 表名;
    
  3. 检索所有列

    SELECT * FROM 表名;
    

排序检索数据

按一个列排序

子句:一个子句通常由一个关键字加上所提供的数据组成

为了明确排序用SELECT语句检索出的数据,可使用ORDER BY子句

ORDER BY子句取一个或多个列的名字,据此对输出进行排序

SELECT 列名 FROM 表名 ORDER BY 列名;

按多个列排序

指定列名,列名之间用逗号分开

SELECT 列名1,列名2,列名3
FROM 表名 ORDER BY 列名2,列名3;

按列位置排序

ORDER BY 2表示按SELECT中出现的第二列,ORDER BY 2,3表示先按SELECT中出现的第二列,再按第三列排序

SELECT 列名1,列名2,列名3
FROM 表名 ORDER BY 2,3;

指定排序方向

默认升序,降序用DESC

SELECT 列名1,列名2,列名3
FROM 表名 ORDER BY 列名2 DESC;

用多个列排序:先以降序排序产品,再对产品名排序

SELECT prod_id,prod_price,prod_name
FROM Products
ORDER BY prod_price DESC, prod_name;

如果想在多个列上进行降序排序,必须对每个列指定DESC关键字

过滤数据

WHERE子句

在SELECT语句中,数据根据WHERE子句中指定的搜索条件进行过滤

SELECT prod_name,prod_price
FROM Products
WHERE prod_price = 3.49;

操作符

= 等于
<> 不等于
!= 不等于
< 小于
<= 小于等于
!< 不小于
> 大于
>= 大于等于
!> 不大于
BETWEEN 在指定的两个值之间
IS NULL 为NULL值

检查单个值

列出价格小于10美元的所有产品

SELECT prod_name,prod_price
FROM Products WHERE prod_price < 10;

不匹配检查

列出不是由供应商DLL01制造的所有商品

SELECT vend_id,prod_name
FROM Products WHERE vend_id <> 'DLL01';

范围值检查

检索价格在5美元和10美元之间的东西

SELECT prod_name,prod_price
FROM Products WHERE prod_price BETWEEN 5 AND 10;

空值检查

在一个列不包含值时,称其为包含空值NULL

可以用SELECT语句的IS NULL子句来检查是否具有空值

SELECT prod_name
FROM Products WHERE prod_price IS NULL;

高级数据过滤

组合WHERE子句

操作符:用来连结或改变WHERE子句中的子句关键字,也称为逻辑操作符

AND操作符

SELECT prod_id,prod_price,prod_name
FROM Products WHERE vend_id='DLL01' AND prod_price<=4 

OR操作符

SELECT prod_id,prod_price,prod_name
FROM Products WHERE vend_id='DLL01' OR prod_price<=4 

计算次序

AND优先级比OR高,可以用圆括号分组

SELECT prod_name,prod_price
FROM Products
WHERE (vend_id = 'DLL01' OR vend_id = 'BRS01')
	AND prod_price >= 10;

IN操作符

用来指定条件范围,范围中的每个条件都可以进行匹配

SELECT prod_name,prod_price
FROM Products WHERE vend_id IN ('DLL01','BRS01')
ORDER BY prod_name;

NOT操作符

在WHERE子句中用来否定后跟条件的关键字

列出除DLL01之外的所有供应商制造的产品:

SELECT prod_name FROM Products
WHERE NOT vend_id = 'DLL01' ORDER BY prod_name;

用通配符进行过滤

通配符:用来匹配值的一部分特殊字符

搜索模式:由字面值,通配符或两者组合构成的搜索条件

百分号(%)通配符

%表示任何字符出现任意次数

找出所有以FISH起头的产品:

SELECT prod_id,prod_name FROM Products
WHERE prod_name LIKE 'Fish%';

找出以F起头以y结尾的所有产品:

SELECT prod_name FROM Products
WHERE prod_name LIKE 'F%y';

%可以匹配0个,1个,多个字符

下划线(_)通配符

用途和%一样,但只匹配单个字符

方括号([])通配符

用来指定一个字符集,必须匹配指定位置(通配符位置)的一个字符

只支持Microsoft Access,Microsoft SQL Server和Sybase Adaptive Server

找出所有名字以J或M起头的联系人

SELECT cust_contact
FROM Customers WHERE cust_contact LIKE '[JM]%'
ORDER BY cust_contact;

也可以用前缀字符(^)来否定

SELECT cust_contact FROM Customers
WHERE cust_contact LIKE '[^JM]%'
ORDER BY cust_contact;

通配符置于搜索模式的开始处,搜索起来是最慢的,尽量不要用

用正则表达式进行搜索

image-20220205181802695

image-20220205181840041

举例

正则表达式\\([0-9]sticks?\\)需要解说一下:

\\(匹配),[0-9]匹配任意数字(这个例子中为1和5),sticks?匹配stick和sticks(s后的?使s可选,因为?匹配它前面的任何字符的0次或1次出现),\\)匹配),没有?,匹配stick和sticks会非常困难

SELECT prod_name FROM products
WHERE prod_name REGEXP '\\([0-9]sticks?\\)'
ORDER BY prod_name;

[:digit:]匹配任意数字,因而它为数字的一个集合。{4}确切地要求它前面的字符(任意数字)出现四次,所以[[:digit:]]{4}匹配连在一起的任意4位数字

SELECT prod_name FROM products
WHERE prod_name REGEXP '[[:digit:]]{4}'
ORDER BY prod_name;

image-20220205183231928

创建计算字段

计算字段

字段:基本上与列的意思相同,计算字段的连接的时候用”字段“

拼接字段

拼接:将值连结到一起构成单个值,用CONCAT()函数

SELECT CONCAT(vend_name,'(',vend_country,')')
FROM Vendors ORDER BY vende_name;

去掉空格

RTRIM()函数去掉值右边的所有空格

LTRIM()去掉值左边的所有空格

TRIM()去掉左右两边的空格

SELECT RTRIM(vend_name) + '(' + RTRIM(vend_country) + ')' FROM Vendors ORDER BY vend_name;

使用别名

列别名:一个值或一个字段的替换名,用AS关键字赋予

SELECT RTRIM(vend_name) + '(' + RTRIM(vend_country) + 
')' + AS vend_title FROM Vendors ORDER BY vend_name;

执行算数计算

expanded_price列为一个计算字段,此计算为quantity*item_price

现在可以使用这个新计算列,就像使用其他列一样

SELECT prod_id,quantity,item_price,
	quantity*item_price AS expanded_price
FROM OrderItems
WHERE order_num = 200008;
+
-
*
/

使用数据处理函数

文本处理函数

Upper()将文本转换为大写

SELECT vend_name,Upper(vend_name) AS vend_name_upcase
FROM vendors ORDER BY vend_name;
Left() 返回串左边的字符
Length() 返回串的长度
Locate() 找出串的一个子串
Lower() 将串转化为小写
LTrim() 去掉串左边的空格
Right() 返回串右边的字符
RTrim() 去掉串右边的空格
Soundex() 返回串的SOUNDEX值
SubString() 返回子串的字符
Upper() 将串转换为大写

Sondex()可以匹配发音类似于这个值的东西

日期和时间处理函数

addDate() 增加一个日期(天、周等)
addTime() 增加一个时间(时、分等)
CurTime() 返回当前时间
Date() 返回日期时间的日期部分
DateDiff() 计算两个日期之差
Date_Add() 高度灵活的日期运算函数
Date_Format() 返回一个格式化的日期或时间串
Day() 返回一个日期的天数部分
DayOfWeek() 对于一个日期,返回对应的星期几
Hour() 返回一个时间的小时部分
Minute() 返回一个时间的分钟部分
Month() 返回一个日期的月份部分
Now() 返回当前日期和时间
Second() 返回一个时间的秒部分
Time() 返回一个日期时间的时间部分
Year() 返回一个日期的年份部分

日期格式必须为yyyy-mm-dd

SELECT cust_id,order_num FROM orders
WHERE order_date = '2005-09-01';

SELECT cust_id,order_num FROM orders
WHERE Date(order_date) = '2005-09-01';

数值处理函数

Abs() 返回一个数的绝对值
Cos() 返回一个角度的余弦
Exp() 返回一个数的指数值
Mod() 返回除操作的余数
Pi() 返回圆周率
Rand() 返回一个随机数
Sin() 返回一个角度的正弦
Sqrt() 返回一个数的平方根
Tan() 返回一个角度的正切

汇总数据

聚集函数

运行在行组上,计算和返回单个值的函数

AVG() 返回某列的平均值
COUNT() 返回某列的行数
MAX() 返回某列的最大值
MIN() 返回某列的最小值
SUM() 返回某列值之和

AVG函数

使用AVG返回products表中所有产品的平均价格

SELECT AVG(prod_price) AS avg_price FROM products;

COUNT函数

使用COUNT(*)对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值

使用COUNT(column)对特定列中具有值的行进行计数,忽略null值

MAX函数

MAX()返回指定类中的最大值,要求指定列名

SELECT MAX(prod_price) AS max_price FROM products;

MIN函数

用来返回指定列值的和

聚集不同值

对所有行执行计算,指定ALL参数或不给参数(因为ALL是默认行为)

只包含不同的值,指定DISTINCT参数

下面的例子使用AVG()函数返回特定供应商提供的产品的平均价格,它与上面的SELECT语句相同,且使用了DISTINCT函数,因此平均值只考虑各个不同的价格

SELECT AVG(DISTINCT prod_price) AS avg_price
FROM products WHERE vend_id = 1003;

组合聚集函数

SELECT COUNT(*) AS num_items,
	MIN(prod_price) AS price_min,
	MAx(prod_price) AS price_max,
	AVG(prod_price) AS price_avg
FROM products;

分组数据

数据分组

返回供应商1003提供的产品数目

SELECT COUNT(*) AS num_prods FROM products
WHERE vend_id = 1003;

GROUP BY

SELECT指定了两个列,vend_id包含供应商的ID,num_prods为计算字段,GROUP BY 子句指示MySQL按照vend_id排序并分组数据,这导致对每个vend_id而不是整个表计算num_prods一次

SELECT vend_id,COUNT(*) AS num_prods FROM products
GROUP BY vend_id;

因为使用了GROUP BY,就不必指定要计算和估计的每个组了,系统会自动完成。GROUP BY 子句指示MySQL分组数据,然后对每个组而不是整个结果集进行聚集

  1. GROUP BY子句可以包含任意数目的列,这使得能对分组进行嵌套,为数据分组提供更细致的控制
  2. 如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上进行汇总,在建立分组时,指定的所有列一起计算
  3. GROUP BY子句中列出的每个列都必须是检索列或有效的表达式(但不能是聚集函数),如果在SELECT中使用表达式,则必须在GROUP BY子句中指定相同的表达式,不能使用别名
  4. 除聚集计算语句外,SELECT语句中的每个列都必须在GROUP BY子句中给出
  5. 如果分组列中具有NULL值,则NULL将作为一个分组返回,如果列中有多行NULL值,它们将分为一组
  6. GROUP BY子句必须出现在WHERE子句之后ORDER BY子句之前

ROLLUP

WITH ROLLUP关键字,可以得到每个分组以及每个分组汇总级别的值

SELECT vend_id,COUNT(*) AS num_prods FROM products
GROUP BY vend_id WITH ROLLUP

过滤分组

WHERE过滤行,HAVING过滤分组

HAVING

SELECT cust_id,COUNT(*) AS orders FROM orders
GROUP BY cust_id HAVING COUNT(*) >= 2;

WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤

WHERE排除的行不包括在分组中,这可能会改变计算值,从而影响HAVING子句中基于这些值过滤掉的分组

列出具有2个或以上,价格为10或以上产品的供应商

SELECT vend_id,COUNT(*) AS num_prods FROM products
WHERE prod_price >= 10 GROUP BY vend_id
HAVING COUNT(*) >= 2;

分组和排序

ORDER BY GROUP BY
排序产生的输出 分组行,但输出可能不是分组的顺序
任意行都可以使用,甚至非选择的列也可以使用 只可能使用选择列或表达式列,而且必须使用每个选择列表达式
不一定需要 如果与聚集函数一起使用列或表达式,则必须使用

一般在使用GROUP BY子句时,应该也给出ORDER BY子句,这是保证数据正确的唯一方法,千万不要仅依赖GROUP BY排序数据

检索总订单价格大于等于50的订单的订单号和总订单价格

SELECT order_num,SUM(quantity*item_price) AS ordertotal FROM orderitems GROUP BY order_num
HAVING SUM(quantity*item_price) >= 50;

为按总订单价格排序输出,需要添加ORDER BY子句,如下所示

SELECT order_num,SUM(quantity*item_price) AS ordertotal FROM orderitems GROUP BY order_num
HAVING SUM(quantity*item_price) >= 50
ORDER BY ordertotal;

GROUP BY子句用来按订单号分组数据,以便SUM(*)函数能够返回总订单价格,HAVING子句过滤数据,使得只返回总计订单大于等于50的订单,最后用ORDER BY子句排序输出

SELECT子句排序

SELECT 要返回的列或表达式
FROM 从中检索数据的表 仅在从表选择数据时使用
WHERE 行级过滤
GROUP BY 输出排序顺序
LIMIT 要检索的行数
HAVING 组级过滤
ORDER BY 输出排序顺序

使用子查询

子查询

嵌套在其他查询中的查询

利用子查询进行过滤

对于prod_id为TNT2的所有订单物品,它检索其order_num列,输出两个包含此物品的清单

SELECT order_num FROM orderitems WHERE prod_id='TNT2'

查询具有订单20005和20007的客户ID

SELECT cust_id FROM orders WHERE order_num IN (20005,20007);

现在把第一个查询变为子查询组合两个查询

SELECT cust_id FROM orders WHERE order_num IN (
	SELECT order_num FROM orderitems 
    WHERE prod_id = 'TNT2'
);

首先它执行下面的查询

SELECT order_num FROM orderitems WHERE prod_id='TNT2'

此查询返回两个订单号:20005和20007,然后这两个值以IN操作符要求的逗号分隔的形式传递给外部查询的WHERE子句,外部查询变成

SELECT cust_id FROM orders WHERE order_num IN (20005,20007);

下一步是检索这些用户ID的客户信息,检索两列的SQL语句为

SELECT cust_name,cust_contact FROM customers
WHERE cust_id IN (10001,10004);

可以把其中的WHERE子句转换为子查询而不是硬编码这些客户ID

SELECT cust_name,cust_contact FROM customers
WHERE cust_id IN (
	SELECT cust_id FROM orders WHERE order_num IN(
		SELECT order_num FROM orderitems WHERE 				prod_id='TNT2'
    )
);

作为计算字段

对客户10001的订单进行计数

SELECT COUNT(*) AS orders FROM orders WHERE cust_id=10001

对每个客户执行COUNT(*)计算,应该将COUNT(*)作为一个子查询

SELECT cust_name, cust_state, (
	SELECT COUNT(*) FROM orders 
    WHERE orders.cust_id = customers.cust_id
) AS orders FROM customers ORDER BY cust_name;

子查询中的WHERE子句与前面使用的WHERE子句稍有不同,因为它使用了完全限定列名,下面的语句告诉SQL比较orders表中的cust_id与当前正从customers表中检索出的cust_id

WHERE orders.cust_id = customers.cust_id

相关子查询:涉及外部查询的子查询

联结表

联结

联结是利用SQL的SELECT能执行的最重要的操作

关系表

外键:外键为某个表中的一列,它包含另一个表的主键值,定义了两个表之间的关系

可伸缩性:能够适应不断增加的工作量而不失败

SELECT vend_name,prod_name,prod_price 
FROM vendors,products
WHERE vendors.vend_id = products.vend_id
ORDER BY vend_name,prod_name;

笛卡尔积:由没有连结条件的表关系返回的结果为笛卡尔积,检索出的行的数目将是第一个表中的行数乘以第二个表中的行数

叉联结:有时我们会听到返回称为叉联结的笛卡尔积的联结类型

内部联结

目前为止所用的联结称为等值联结,它基于两个表之间的相等测试,这种连结也称为内部联结

SELECT vend_name,prod_name,prod_price
FROM vendors INNER JOIN products 
ON vendors.vend_id = products.vend_id;

此语句中的SELECT语句与前面的SELECT语句相同,但FROM子句不同

这里,两个表之间的关系是FROM子句的组成部分,以INNER JOIN指定,在使用这种语法时,联结条件用特定的ON子句而不是WHERE子句给出,传递给ON的实际条件与传递给WHERE的相同

联结多个表

首先列出所有表,然后定义表之间的关系

SELECT prod_name,vend_name,prod_price,quantity
FROM orderitems,products,vendors
WHERE products.vend_id = vendors.vend_id
	AND orderitems.prod_id = products.prod_id
	AND order_num = 20005;

创建高级联结

使用表别名

给列起别名

SELECT Concat(RTrim(vend_name),'(',RTrim(vend_country),')') AS vend_title FROM vendors ORDER BY vend_name;

给表起别名

SELECT cust_name,cust_contact
FROM customers AS c,orders AS o, orderitems AS oi
WHERE c.cust_id = o.cust_id
	AND oi.order_num = o.order_num
	AND prod_id = 'TNT2';

使用不同类型的联结

迄今为止,我们使用的是内部联结或等值联结,现在来看其他三种

自联结

假如你发现某物品(其ID为DTNTR)存在问题,因此想知道生产该物品的供应商生产的其他物品是否也存在这些问题

方案1:使用子查询

SELECT prod_id,prod_name FROM products
WHERE vend_id = (
   SELECT vend_id FROM products WHERE prod_id='DTNTR'
);

方案2:使用联结

SELECT p1.prod_id, p1.prod_name
FROM products AS p1, products AS p2
WHERE p1.vend_id = p2.vend_id
	AND p2.prod_id = 'DTNTR';
自然联结

标准的联结返回所有数据,甚至相同的列多次出现,自然联结排除多次出现,使每个列只返回一次。怎样完成这件工作呢?答案是,系统不完成这件工作,由你自己来完成。自然联结是这样一种联结,其中你只能选择那些唯一的列,这一般是通过对表使用通配符(SELECT *),对其他所有表的列的使用明确的子集来完成的

SELECT C.*,o.order_num,o.order_date,
		oi.prod_id,oi.quantity,oi.item_price
FROM customers AS c,orders AS o,orderitems AS oi
WHERE c.cust_id = o.cust_id
	AND oi.order_num = o.order_num
	AND prod_id = 'FB';
外部联结

下面的SELECT语句中给出了一个简单的内部联结,它检索所有的客户及其订单

SELECT customers.cust_id,orders.order_num
FROM customers INNER JOIN orders
ON customers.cust_id = orders.cust_id;

外部联结语法类似,为了检索所有客户,包括那些没有订单的客户

SELECT customers.cust_id,orders.order_num
FROM customers LEFT OUTER JOIN orders
ON customers.cust_id = orders.cust_id;

这条SELECT语句使用了关键字OUTER JOIN来指定联结的类型(而不是在WHERE子句中指定),但是与内部联结关联两个表中的行不同的是,外部联结还包括没有关联行的行。在使用OUTER JOIN语法时,必须使用RIGHT或LEFT关键字指定包括其所有行的表(RIGHT指出的是OUTER JOIN右边的表,而LEFT指出的是OUTER JOIN左边的表),上面的例子使用LEFT OUTER JOIN从FROM子句的左边表(customer表)中选择所有行,为了从右边的表中选择所有行,应该使用RIGHT OUTER JOIN

SELECT customers.cust_id,orders.order_num
FROM customers RIGHT OUTER JOIN orders
ON orders.cust_id = customers.cust_id;
带聚集函数的联结

此SELECT语句使用INNER JOIN将customers和orders表互相关联,GROUP BY子句按客户分组数据,因此,函数调用COUNT(orders.order_num)对每个客户的订单计数,将它作为num_ord返回

SELECT customers.cust_name,
		customers.cust_id,
		COUNT(orders.order_num) AS num_ord
FROM customers INNER JOIN orders
ON customers.cust_id = orders.cust_id
GROUP BY customers.cust_id;

组合查询

多条SELECT结果作为单个查询结果集返回,这些组合查询称为并或复合查询

UNION

在各条语句之间放上关键字UNION

SELECT vend_id,prod_id,prod_price
FROM products WHERE prod_price <= 5 
UNION 
SELECT vend_id,prod_id,prod_price
FROM products WHERE vend_id IN (1001,1002);
  1. UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔
  2. UNION的每个查询都必须包含相同的列、表达式或聚集函数
  3. 列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐式转换的类型(例如不同的数值类型或不同的日期类型)

包含或取消重复的行

第一条SELECT语句返回4行,第二条SELECT语句返回5行,但在用UNION组合两条SELECT语句之后,只返回了8行而不是9行

UNION从查询结果中去除了重复的行,这是UNION的默认行为

如果想返回所有匹配行,可使用UNION ALL而不是UNION

SELECT vend_id,prod_id,prod_price FROM products
WHERE prod_price <= 5
UNION ALL 
SELECT vend_id,prod_id,prod_price FROM products
WHERE vend_id IN (1001,1002);

对组合查询结果排序

在用UNION查询时,只能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后,对于结果集,不存在用一种方式排序一部分,而又用另一种方式排序另一部分的情况,因此不允许使用多条ORDER BY子句

SELECT vend_id,prod_id,prod_price
FROM products WHERE prod_price <= 5
UNION 
SELECT vend_id,prod_id,prod_price
FROM products WHERE vend_id IN (1001,1002)
ORDER BY vend_id,prod_price;

全文本搜索

启用全文本搜索支持

一般在创建表时启用全文本搜索,CREATE TABLE语句接受FULL TEXT子句,它给出被索引列的一个逗号分隔的列表

CREATE TABLE productnotes (
	note_id		INT		NOT NULL AUTO_INCREMENT,
    prod_id		char(10) NOT NULL,
 	note_date datetime	NOT NULL,
    note_text text 		NULL,
    PRIMARY KEY(note_id),
    FULLTEXT(note_text)
)ENGINE=MyISAM;

这些列中有一个名为note_text的列,为了进行全文本搜索,MySQL根据子句FULLTEXT(note_text)的指示对它进行索引,这里的FULLTEXT索引单个列,如果需要也可以指定多个列

进行全文本搜索

在索引之后,使用两个函数Match()和Against()执行全文本搜索,其中Match()指定被搜索的列,Against()指定要使用的搜索表达式

插入数据

插入完整的行

INSERT INTO Customers
VALUES(NULL,
      'Pep E.LaPew',
      '100 Main Street',
      'Los Angeles',
      'CA',
      '90046',
      'USA',
      NULL,
      NULL);

更安全的方法

INSERT INTO customers(
    cust_name,
	cust_address,
	cust_city,
	cust_state,
	cust_zip,
	cust_country,
	cust_contact,
	cust_email)
VALUES('Pep E.LaPew',
      '100 Main Street',
      'Los Angeles',
      'CA',
      '90046',
      'USA',
      NULL,
      NULL);

插入多个行

INSERT INTO customers(cust_name,
	cust_address,
	cust_city,
	cust_state,
	cust_zip,
	cust_country,
	cust_contact,
	cust_email)
VALUES('Pep E.LaPew',
      '100 Main Street',
      'Los Angeles',
      'CA',
      '90046',
      'USA',
      NULL,
      NULL);
INSERT INTO customers(cust_name,
	cust_address,
	cust_city,
	cust_state,
	cust_zip,
	cust_country,
	cust_contact,
	cust_email)
VALUES('Pep E.LaPew',
      '100 Main Street',
      '1111111111',
      'CA',
      '90046',
      'USA',
      NULL,
      NULL);	

或者,只要每条INSERT语句中的列名和次序相同,可以如下组合

INSERT INTO customers(cust_name,
	cust_address,
	cust_city,
	cust_state,
	cust_zip,
	cust_country)
VALUES(
	'Pep E.LaPew',
      '100 Main Street',
      'Los Angeles',
      'CA',
      '90046',
      'USA'
),
(
    '111111',
    '1111',
    '111'
    '1',
    '11',
    '111'
);

插入检索出的数据

可以将一条SELECT语句的结果插入到表中

INSERT INTO customers(
	cust_id,
    cust_email,
    cust_name,
    cust_address,
    cust_city,
    cust_state,
    cust_zip,
    cust_country
)
SELECT cust_id,
	cust_email,
    cust_name,
    cust_address,
    cust_city,
    cust_state,
    cust_zip,
    cust_country
FROM custnew;

更新和删除数据

更新列

更新一列

UPDATE customers SET cust_email = 'elmer@fudd.com'
WHERE cust_id = 10005;

更新多个列

UPDATE customers 
SET cust_email = 'elmer@fudd.com',
	cust_name = 'elmer'
WHERE cust_id = 10005;

为了删除某个列的值,可将它设置为NULL

UPDATE customers
SET cust_email = NULL
WHERE cust_id = 10005;

删除数据

从customers表中删除一行

DELETE FROM customers
WHERE cust_id = 10006;

DELETE删除行而不是删除列,删除列用UPDATE的NULL