学习了mysql基本查询, 接着学习连接查询和子查询。
4,连接查询
连接是关系数据库模型的主要特点。连接查询是关系数据库中最主要的查询,主要包括内连接、外连接等。通过连接运算符可以实现多个表查询。在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中。当查询数据时,通过连接操作查询出存放在多个表中的不同实体的信息。当两个或多个表中存在相同意义的字段时,便可以通过这些字段对不同的表进行连接查询。本节将介绍多表之间的内连接查询、外连接查询以及复合条件连接查询。
1,内连接查询
内连接(INNER JOIN)使用比较运算符进行表间某((些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行,组合成新记录,也就是说,在内连接查询中,只有满足条件的记录才能出现在结果关系中。
首先创建数据表suppliers,SQL语句如下:
CREATE TABLE suppliers(
s_id int NOT NULL AUTO_INCREMENT,
s_name char(50) NOT NULL,
s_city char (50) NULL,
s_zip char(10) NULL,
s_call CHAR(50) NOT NULL,
PRIMARY KEY (s_id)
);
插入数据,SQL语句如下:
INSERT INTO suppliers(s_id, s_name, s_city, s_zip, s_call)
VALUES(101,'FastFruit Ine.', 'Tianjin', '300000', '148075'),
(102, 'LT Supplies', 'Chongqing', '400000', '44333'),
(103, 'ACME', 'Shanghai', '200000', '90046'),
(104, 'FNK Ine.', 'Zhongshan', '528437', '11111'),
(105, 'Good Set', 'Taiyuang', '030000', '22222'),
(106, 'Just Eat ours', 'Beijing' , '010', '45678'),
(107, 'DK inc.', 'Zhengzhou', '450000', '33332');
【例46】在fruits表和suppliers表之间使用内连接查询。查询之前,查看两个表的结构:
DESC fruits;
DESC suppliers;
由结果可以看到 fruits表和 suppliers 表中都有相同数据类型的字段s_id两个表通过s_id字段建立联系。接下来从 fruits表中查询f_name、f_price字段,从suppliers表中查询s_id、s_name,SQL语句如下:
SELECT suppliers.s_id, s_name,f_name, f_price
FROM fruits, suppliers
WHERE fruits.s_id=suppliers.s_id;
在这里,SELECT语句与前面所介绍的一个最大的差别是:SELECT后面指定的列分别属于两个不同的表,(f_name,f_price)在表 fruits中,而另外两个字段在表supplies中;同时FROM子句列出了两个表fruits和 suppliers。WHERE子句在这里作为过滤条件,指明只有两个表中的 s_id字段值相等的时候才符合连接查询的条件。从返回的结果可以看到,显示的记录是由两个表中不同列值组成的新记录。
提示:因为fruits 表和suppliers表中有相同的字段s_id,因此在比较的时候,需要完全限定表名(格式为“表名.列名”),如果只给出s_id,MySQL将不知道指的是哪一个,并返回错误信息。
下面的内连接查询语句返回与前面完全相同的结果。
【例47】在 fruits表和 suppliers表之间,使用INNER JOIN语法进行内连接查询,SQL语句如下:
SELECT suppliers.s_id, s_name,f_name, f_price
FROM fruits INNER JOIN suppliers
ON fruits.s_id = suppliers.s_id;
在这里的查询语句中,两个表之间的关系通过INNER JOIN 指定。使用这种语法的时候,连接的条件使用ON子句给出而不是WHERE,ON和 WHERE后面指定的条件相同。
使用WHERE子句定义连接条件比较简单明了,而 INNER JOIN语法是ANSI SQL的标准规范,使用INNER JOIN连接语法能够确保不会忘记连接条件,而且,WHERE子句在某些时候会影响查询的性能。
如果在一个连接查询中,涉及的两个表都是同一个表,这种查询称为自连接查询。自连接是一种特殊的内连接,它是指相互连接的表在物理上为同一张表,但可以在逻辑上分为两张表。
【例48】查询供应f_id='al'的水果供应商提供的水果种类,SQL语句如下:
SELECT f1.f_id, f1.f_name
FROM fruits AS f1, fruits AS f2
WHERE f1.s_id = f2.s_id AND f2.f_id = 'a1';
此处查询的两个表是相同的表,为了防止产生二义性,对表使用了别名,ftuits 表第Ⅰ次出现的别名为fl,第2次出现的别名为f2,使用SELECT语句返回列时明确指出返回以fl为前缀的列的全名,WHERE 连接两个表,并按照第2个表的f_id对数据进行过滤,返回所需数据。
2,外连接查询
外连接查询将查询多个表中相关联的行,内连接时,返回查询结果集合中的仅是符合查询条件和连接条件的行。但有时候需要包含没有关联的行中数据,即返回查询结果集合中的不仅包含符合连接条件的行,而且还包括左表(左外连接或左连接)、右表(右外连接或右连接)或两个连接表(全外连接)中的所有数据行。外连接分为左外连接或左连接和右外连接或右连接:
LEFT JOIN(左连接):返回包括左表中的所有记录和右表中连接字段相等的记录,
RIGHT JOIN(右连接):返回包括右表中的所有记录和左表中连接字段相等的记录。
1,LEFT JOIN(左连接)
左连接的结果包括LEFT OUTER子句中指定的左表的所有行,而不仅仅是连接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果行中,右表的所有选择列表列均为空值。
首先创建表orders,SQL语句如下:
CREATE TABLE orders
(
o_num int NOT NULL AUTO_INCREMENT,
o_date datetime NOT NULL,
c_id int NOT NULL,
PRIMARY KEY (o_num)
);
插入数据,SQL语句如下:
INSERT INTO orders(o_num,o_date, c_id)
VALUES(30001, '2008-09-01', 10001),
(30002, '2008-09-12', 10003),
(30003, '2008-09-30', 10004),
(30004, '2008-10-03', 10005),
(30005, '2008-10-08', 10001);
【例49】在customers表和 orders 表中,查询所有客户,包括没有订单的客户,SQL语句如下:
SELECT customers.c_id, orders.o_num
FROM customers LEFT OUTER JOIN orders
ON orders.c_id = customers.c_id;
结果显示了5条记录,ID 等于10002的客户目前并没有下订单,所以对应的orders 表中并没有该客户的订单信息,所以该条记录只取出了customers 表中相应的值,而从 orders表中取出的值为空值NULL。
2,RIGHT JOIN(右连接)
右连接是左连接的反向连接,将返回右表的所有行。如果右表的某行在左表中没有匹配行,左表将返回空值。
【例50】在 customers表和 orders表中,查询所有订单,包括没有客户的订单,SQL语句如下:
SELECT customers.c_id, orders.o_num
FROM customers RIGHT OUTER JOIN orders
ON orders.c_id = customers.c_id;
结果显示了5条记录,订单号等于30004的订单的客户可能由于某种原因取消了该订单,对应的customers 表中并没有该客户的信息,所以该条记录只取出了ordes 表中相应的值。而从customers表中取出的值为空值NULL。
3,复合条件连接查询
复合条件连接查询是在连接查询的过程中,通过添加过滤条件,限制查询的结果,使查询的结果更加准确。
【例51】在 customers表和 orders表中,使用 INNER JOIN语法查询customers表中 ID为10001的客户的订单信息,SQL语句如下:
SELECT customers.c_id, orders.o_num
FROM customers INNER JOIN orders
ON customers.c_id = orders.c_id
AND customers.c_id = 10001;
结果显示,在连接查询时指定查询客户ID为10001的订单信息,添加了过滤条件之后返回的结果将会变少,因此返回结果只有两条记录。
使用连接查询,并对查询的结果进行排序。
【例52】在 fruits表和 suppliers表之间,使用INNER JOIN语法进行内连接查询,并对查询结果排序,SQL语句如下:
SELECT suppliers.s_id, s_name, f_name, f_price
FROM fruits INNER JOIN suppliers
ON fruits.s_id = suppliers.s_id
ORDER BY fruits.s_id;
由结果可以看到,内连接查询的结果按照 suppliers.s_id字段进行了升序排序。
5,子查询
子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从MySQL 4.1开始引入。在SELECT子句中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或者多个表。子查询中常用的操作符有ANY (SOME)、ALL、IN、EXISTS。子查询可以添加到SELECT、UPDATE 和DELETE 语句中,而且可以进行多层嵌套。子查询中也可以使用比较运算符,如“<”、“<=”、“>”、“>=”和“!=”等。本节将介绍如何在SELECT语句中嵌套子查询。
1,带ANY、SOME关键字的子查询
ANY和 SOME关键字是同义词,表示满足其中任一条件,它们允许创建一个表达式对子查询的返回值列表进行比较,只要满足内层子查询中的任何一个比较条件,就返回一个结果作为外层查询的条件。
下面定义两个表num_tb1和 num_tb2:
CREATE table num_tb1 (num1 INT NOT NULL);
CREATE table num_tb2 (num2 INT NOT NULL);
分别向两个表中插入数据:
INSERT INTO num_tb1 values(1), (5), (13), (27);
INSERT INTO num_tb2 values(6), (14), (11), (20);
ANY 关键字接在一个比较操作符的后面,表示若与子查询返回的任何值比较为TRUE,则返回TRUE。
【例53】返回num_tb2表的所有num2列,然后将num_tbl中的num1的值与之进行比较,只要大于num2的任何1个值,即为符合查询条件的结果。
SELECT num1 FROM num_tb1 WHERE num1 > ANY(SELECT num2 FROM num_tb2);
在子查询中,返回的是num_tb2表的所有num2列结果(6,14,11,20),然后将num_tbl中的num1列的值与之进行比较,只要大于num2列的任意一个数即为符合条件的结果。
2,带ALL关键字的子查询
ALL关键字与ANY和SOME不同,使用ALL时需要同时满足所有内层查询的条件。例如,修改前面的例子,用ALL关键字替换ANY。
ALL关键字接在一个比较操作符的后面,表示与子查询返回的所有值比较为TRUE,则返回TRUE。
【例54】返回num_tb1表中比 num_tb2表num2列所有值都大的值,SQL语句如下:
SELECT num1 FROM num_tb1 WHERE num1 > ALL (SELECT num2 FROM num_tb2);
在子查询中,返回的是 num_tb2的所有num2列结果(6,14,11,20),然后将num_tbl 中的num1列的值与之进行比较,大于所有num2列值的num1值只有27,因此返回结果为27。
3,带EXISTS关键字的子查询
EXISTS关键字后面的参数是一个任意的子查询,系统对子查询进行运算以判断它是否返回行,如果至少返回一行,那么EXISTS的结果为true,此时外层查询语句将进行查询;如果子查询没有返回任何行,那么EXISTS返回的结果是false,此时外层语句将不进行查询。
【例55】查询suppliers表中是否存在.s_id=107的供应商,如果存在,则查询fruits 表中的记录,SQL语句如下:
SELECT * FROM fruits
WHERE EXISTS (SELECT s_name FROM suppliers WHERE s_id = 107);
由结果可以看到,内层查询结果表明suppliers表中存在s_id=107的记录,因此EXISTS表达式返回true;外层查询语句接收 true之后对表fruits进行查询,返回所有的记录。
EXISTS 关键字可以和条件表达式一起使用。
【例56】查询suppliers表中是否存在s_id=107的供应商,如果存在,则查询fruits 表中的f_price大于10.20的记录,SQL语句如下:
SELECT * FROM fruits
WHERE f_price>10.20
AND EXISTS (SELECT s_name FROM suppliers WHERE s_id = 107);
由结果可以看到,内层查询结果表明suppliers表中存在s_id=107的记录,因此EXISTS表达式返回 true;外层查询语句接收true之后根据查询条件f _price > 10.20对fruits 表进行查询,返回结果为4条f _price大于10.20的记录。
NOT EXISTS与 EXISTS使用方法相同,返回的结果相反。子查询如果至少返回一行,那么NOT EXISTS的结果为 false,此时外层查询语句将不进行查询;如果子查询没有返回任何行,那么NOT EXISTS返回的结果是true,此时外层语句将进行查询。
【例57】查询suppliers表中是否存在s_id=107的供应商,如果不存在则查询fruits表中的记录,SQL语句如下:
SELECT * FROM fruits
WHERE NOT EXISTS (SELECT s_name FROM suppliers WHERE s_id = 107);
查询语句“SELECT s_name FROM supplicrs WHEREs_id = 107”,对suppliers 表进行查询返回了一条记录,NOT EXISTS表达式返回false,外层表达式接收false,将不再查询 fruits表中的记录。
提示:EXISTS和 NOT EXISTS的结果只取决于是否会返回行,而不取决于这些行的内容,所以这个子查询输入列表通常是无关紧要的。
4,带IN关键字的子查询
IN关键字进行子查询时,内层查询语句仅仅返回一个数据列,这个数据列里的值将提供给外层查询语句进行比较操作。
【例58】在 order_items表中查询f_id为c0的订单号,并根据订单号查询具有订单号的客户c_id,SQL语句如下:
SELECT c_id FROM orders WHERE o_num IN
(SELECT o_num FROM order_items wHERE f_id = 'c0')
查询结果的c_id有两个值,分别为10001和10004。上述查询过程可以分步执行,首先内层子查询查出order_items表中符合条件的订单号,单独执行内查询,查询结果如下:
SELECT o_num FROM order_items wHERE f_id = 'c0';
可以看到,符合条件的 o_num列的值有两个:30003和 30005,然后执行外层查询,在orders表中查询订单号等于30003或30005的客户c_id。嵌套子查询语句还可以写为如下形式,实现相同的效果:
SELECT c_id FROM orders
WHERE o_num IN (30003,30005);
这个例子说明在处理SELECT语句的时候,MySQL 实际上执行了两个操作过程,即先执行内层子查询,再执行外层查询,内层子查询的结果作为外部查询的比较条件。
SELECT语句中可以使用NOT IN关键字,其作用与IN正好相反。
【例59】与前一个例子类似,但是在SELECT语句中使用NOT IN关键字,SQL语句如下:
SELECT c_id FROM orders WHERE o_num NOT IN
(SELECT o_num FROM order_items WHERE f_id = 'c0');
这里返回的结果有3条记录,由前面可以看到,子查询返回的订单值有两个,即 30003和30005,但为什么这里还有值为10001的c_id呢?这是因为c_id等于10001的客户的订单不止一个,可以查看订单表orders中的记录。
SELECT * FROM orders;
可以看到,虽然排除了订单号为30003和 30005的客户c_id,但是o_num为 30001的订单与30005都是10001号客户的订单。所以结果中只是排除了订单号,但是仍然有可能选择同一个客户。
子查询的功能也可以通过连接查询完成,但是子查询使得MySQL代码更容易阅读和编写。
5,带比较运算符的子查询
在前面介绍的带ANY、ALL关键字的子查询时使用了“>”比较运算符,子查询时还可以使用其他的比较运算符,如“<”、“<=”、“=”、“>=”和“!=”等。
【例60】在 suppliers表中查询s_city等于“Tianjin”的供应商s_id,然后在 fruits表中查询所有该供应商提供的水果的种类,SQL语句如下:
SELECT s_id, f_name FROM fruits
WHERE s_id=
(SELECT s.s_id FROM suppliers AS s WHERE s.s_city = 'Tianjin');
该嵌套查询首先在 suppliers 表中查找s_city 等于Tianjin的供应商的s_id,单独执行子查询查看s_id的值,执行下面的操作过程:
SELECT s.s_id FROM suppliers AS s WHERE s.s_city = 'Tianjin';
然后在外层查询时,在fruits表中查找s_id等于101的供应商提供的水果的种类,查询结果如下:
结果表明,“Tianjin”地区的供应商提供的水果种类有3种,分别为“apple”、“blackberry”、 “cherry”。
【例61】在suppliers 表中查询s_city等于“Tianjin”的供应商s_id,然后在 fruits表中查询所有非该供应商提供的水果的种类,SQL语句如下:
SELECT s_id,f_name FROM fruits
WHERE s_id <>
(SELECT s.s_id FROM suppliers As s WHERE s.s_city = 'Tianjin');
该嵌套查询执行过程与前面相同,在这里使用了不等于“心”运算符,因此返回的结果和前面正好相反。
6,合并查询结果
利用UNION关键字,可以给出多条SELECT语句,并将它们的结果组合成单个结果集。合并时,两个表对应的列数和数据类型必须相同。各个SELECT语句之间使用UNION或UNION ALL关键字分隔。UNION不使用关键字ALL,执行的时候删除重复的记录,所有返回的行都是唯一的;使用关键字ALL的作用是不删除重复行也不对结果进行自动排序。基本语法格式如下:
SELECT column, . FROM tab1e1 UNION [ALL]
SELECT column, .. FROM table2
【例62】查询所有价格小于9的水果的信息,查询s_id等于101和103所有的水果的信息,使用UNION 连接查询结果,SQL语句如下:
SELECT s_id, f_name, f_price
FROM fruits
WHERE f_price < 9.0
UNION ALL
SELECT s_id, f_name, f_price
FROM fruits
WHERE s_id IN(101,103);
合并查询结果如下:
如前所述,UNION将多个SELECT语句的结果组合成一个结果集合。可以分开查看每个SELECT语句的结果:
SELECT s_id, f_name, f_price
FROM fruits
WHERE f_price < 9.0;
SELECT s_id, f_name, f_price
FROM fruits
WHERE s_id IN(101,103);
由分开查询的结果可以看到,第1条SELECT语句查询价格小于9的水果,第2条SELECT语句查询供应商101和103提供的水果。使用UNION将两条SELECT语句分隔开,执行完毕之后把输出结果组合成单个的结果集,并删除重复的记录。
使用UNION ALL包含重复的行,在前面的例子中,分开查询时,两个返回结果中有相同的记录。UNION从查询结果集中自动去除了重复的行,如果要返回所有匹配行,而不进行删除,可以使用UNION ALL。
【例63】查询所有价格小于9的水果的信息,查询s_id等于101和103的所有水果的信息,使用UNION ALL连接查询结果,SQL语句如下:
SELECT s_id, f_name, f_price
FROM fruits
WHERE f_price < 9.0
UNION ALL
SELECT s_id, f_name, f_price FROM fruits
WHERE s_id IN(101,103);
查询结果如下:
由结果可以看到,这里总的记录数等于两条SELECT语句返回的记录数之和,连接查询结果并没有去除重复的行。
提示: UNION和 UNION ALL的区别:使用UNION ALL的功能是不删除重复行,加上ALL关键字语句执行时所需要的资源少,所以尽可能地使用它,因此知道有重复行但是想保留这些行,确定查询结果中不会有重复数据或者不需要去掉重复数据的时候,应当使用UNIONALL以提高查询效率。
7,为表和字段取别名
在前面介绍分组查询、聚合函数查询和嵌套子查询章节中,读者注意到有的地方使用了AS关键字为查询结果中的某一列指定一个特定的名字。在内连接查询时,则对相同的表fruits分别指定两个不同的名字,这里可以为字段或者表取一个别名,在查询时,使用别名替代其指 定的内容。
1,为表取别名
当表名字很长或者执行一些特殊查询时,为了方便操作或者需要多次使用相同的表时,可以为表指定别名,用这个别名替代表原来的名称。为表取别名的基本语法格式为:
表名 [AS] 表别名
“表名”为数据库中存储的数据表的名称,“表别名”为查询时指定的表的新名称,AS关键字为可选参数。
【例64】为orders表取别名o,查询30001订单的下单日期,SQL语句如下:
SELECT * FROM orders AS o
WHERE o.o_num = 30001;
在这里orders As o代码表示为 orders表取别名为o,指定过滤条件时直接使用o代替orders,查询结果如下:
【例65】为customers和 orders表分别取别名,并进行连接查询,SQL语句如下:
SELECT c.c_id, o.o_num
FROM customers AS C LEFT OUTER JOIN orders AS o ON c.c_id =o.c_id;
由结果看到,MySQL可以同时为多个表取别名,而且表别名可以放在不同的位置,如WHERE子句、SELECT 列表、ON子句以及ORDER BY子句等。
在前面介绍内连接查询时指出自连接是一种特殊的内连接,在连接查询中的两个表都是同一个表,其查询语句如下:
SELECT f1.f_id, f1.f_name
FROM fruits AS f1, fruits AS f2
WHERE f1.s_id = f2.s_id AND f2.f_id = 'a1';
在这里,如果不使用表别名,MySQL 将不知道引用的是哪个fruits表实例,这是表别名的一个非常有用的地方。
提示:在为表取别名时,要保证不能与数据库中的其他表的名称冲突。
2,为字段取别名
在使用SELECT语句显示查询结果时,MySQL会显示每个 SELECT后面指定的输出列,在有些情况下,显示的列的名称会很长或者名称不够直观,MySQL可以指定列别名,替换字段或表达式。为字段取别名的基本语法格式为:
列名 [AS] 列别名
“列名”为表中字段定义的名称,“列别名”为字段新的名称,AS关键字为可选参数。
【例66】查询fruits表,为f_name取别名fruit_name,f_price取别名 fruit_price,为 fruits表取别名fl,查询表中f _price <8的水果的名称,SQL语句如下:
SELECT f1.f_name AS fruit_name, f1.f_price AS fruit_price
FROM fruits AS f1
WHERE f1.f_price <8;
也可以为SELECT子句中的计算字段取别名,例如,对使用COUNT聚合函数或者CONCAT等系统函数执行的结果字段取别名。
【例67】查询suppliers表中字段s_name和 s_city,使用CONCAT函数连接这两个字段值,并取列别名为suppliers_title。
如果没有对连接后的值取别名,其显示列名称将会不够直观,SQL语句如下:
SELECT CONCAT(TRIM(s_name), ' (', TRIM(s_city), ' )')
FROM suppliers
ORDER BY S_name;
由结果可以看到,显示结果的列名称为SELECT子句后面的计算字段,实际上计算之后的列是没有名字的,这样的结果让人很不容易理解,如果为字段取一个别名将会使结果清晰,SQL语句如下:
SELECT CONCAT (TRIM(s_name),' (',TRIM(S_city),' )') As suppliers_title
FROM suppliers
ORDER BY s_name;
由结果可以看到,SELECT子句计算字段值之后增加了AS suppliers_title,它指示 MySQL为计算字段创建一个别名suppliers_title,显示结果为指定的列别名,这样就增强了查询结果的可读性。
提示:表别名只在执行查询的时候使用,并不在返回结果中显示,而列别名定义之后,将返回给客户端显示,显示的结果字段为字段列的别名。
8,疑问解答:
疑问1:DISTINCT可以应用于所有的列吗?
查询结果中,如果需要对列进行降序排序,可以使用DESC,这个关键字只能对其前面的列进行降序排列。例如,要对多列都进行降序排序,必须要在每一列的列名后面加DESC 关键字。
而DISTINCT不同,DISTINCT不能部分使用。换句话说,DISTINCT关键字应用于所有列而不仅是它后面的第一个指定列。例如,查询3个字段s_id,f_name,f_price,如果不同记录的这3个字段的组合值都不同,则所有记录都会被查询出来。
疑问2:ORDER BY可以和LIMIT混合使用吗?
在使用ORDER BY子句时,应保证其位于FROM子句之后,如果使用LIMIT,则必须位于ORDER BY之后,如果子句顺序不正确,MySQL将产生错误消息。
疑问3:什么时候使用引号?
在查询的时候,会看到在 WHERE子句中使用条件,有的值加上了单引号,而有的值未加。单引号用来限定字符串,如果将值与字符串类型列进行比较,则需要限定引号;而用来与数值进行比较则不需要用引号。
疑问4∶在WHERE子句中必须使用圆括号吗?
任何时候使用具有AND和OR操作符的WHERE子句,都应该使用圆括号明确操作顺序。如果条件较多,即使能确定计算次序,默认的计算次序也可能会使SQL语句不易理解,因此使用括号明确操作符的次序,是一个良好的习惯。
疑问5:为什么使用通配符格式正确,却没有查找出符合条件的记录?
MySQL中存储字符串数据时,可能会不小心把两端带有空格的字符串保存到记录中,而在查看表中记录时,MySQL不能明确地显示空格,数据库操作者不能直观地确定字符串两端是否有空格。例如,使用LIKE '%e'匹配以字母e结尾的水果的名称,如果字母e后面多了一个空格,则LIKE语句不能将该记录查找出来。解决的方法是使用TRIM函数,将字符串两端的空格删除之后再进行匹配。
9,查询实战:
1,数据准备:
建表
创建数据表employee和dept。
CREATE TABLE dept
(
d_no INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
d_name VARCHAR(50) NOT NULL,
d_location VARCHAR(100)
);
由于employee表dept _no依赖于父表dept的主键d_no,因此需要先创建dept 表,然后创建employec表。
DROP TABLE employee;
CREATE TABLE employee(
e_no INT(11) NOT NULL PRIMARY KEY,
e_name VARCHAR(50) NOT NULL,
e_gender CHAR(2),
dept_no INT(11) NOT NULL,
e_job VARCHAR(50) NOT NULL,
e_salary INT(11) NOT NULL,
hireDate DATE NOT NULL,
CONSTRAINT dno_fk FOREIGN KEY(dept_no)
REFERENCES dept(d_no)
);
插入数据
将指定记录分别插入两个表中。向dept表中插入数据,SQL语句如下:
INSERT INTO dept
VALUES (10, 'ACCOUNTING', 'ShangHai'),
(20, 'RESEARCH', 'BeiJing'),
(30, 'SALES ', 'Shenzhen'),
(40, 'OPERATIONS', 'FuJian');
向employee表中插入数据,SQL语句如下:
INSERT INTO employee
VALUES (1001, 'SMTTB', 'm',20, 'CLERK', 800, '2005-11-12'),
(1002, 'ALLEN', 'f', 30, 'SALESMAN', 1600, '2003-05-12'),
(1003, 'WARD', 'f', 30, 'SALESMAN', 1250, '2003-05-12'),
(1004, 'JONES', 'm', 20, 'MANAGER', 2975, '1998-05-18'),
(1005, 'MARTIN', 'm', 30, 'SALESMAN', 1250, '2001-06-12'),
(1006, 'BLAKE', 'f', 30, 'MANAGER', 2850, '1997-02-15'),
(1007, 'CLARK', 'm', 10, 'MANAGER', 2450, '2002-09-12'),
(1008, 'SCOTT', 'm', 20, 'ANALYST', 3000, '2003-05-12'),
(1009, 'KING', 'f', 10, 'PRESTDENT', 5000, '1995-01-01'),
(1010, 'TURNER', 'f', 30, 'SALESMAN', 1500, '1997-10-12'),
(1011, 'ADAMS', 'm', 20, 'CLERK', 1100, '1999-10-05'),
(1012, 'JAMES', 'm', 30, 'CLERK', 950, '2008-06-15');
2,查询
1,在employee表中,查询每个部门最高工资的员工信息。
SELECT dept_no, MAX(e_salary) FROM employee GROUP BY dept_no;
2,查询员工 BLAKE所在部门和部门所在地。
SELECT d_no, d_location FROM dept WHERE d_no=
(SELECT dept_no FROM employee WHERE e_name='BLAKE');
3,在employee表中,查询员工姓名以字母‘A’或‘S’开头的员工的信息。
SELECT * FROM employee WHERE e_name REGEXP '^[as]';
4,在employee表中,查询到目前为止,工龄大于等于10年的员工信息。
SELECT * FROM employee where YEAR(CURDATE())-YEAR(hireDate)>= 15;
总结:
学习了查询,后面就是多练习,不断实战。再结合后面查询优化的地方,把sql写好。
上一篇《MYSQL 基本查询》
下一篇《myql join连接 全部》