SQL 子查询
子查询或内部查询是嵌套在另一个SQL查询中的SQL查询。它嵌入在SQL语句的HAVING或WHERE子句中。
以下是SQL子查询必须遵守的重要规则:
1. SQL子查询可以与以下语句一起使用,以及SQL表达式运算符:
- SELECT语句,
- UPDATE语句,
- INSERT语句,以及
- DELETE语句。
2. SQL中的子查询总是被括在括号中,并放置在SQL运算符的右侧。
3. 我们不能在子查询中使用ORDER BY子句。但是,我们可以使用GROUP BY子句,它执行与ORDER BY子句相同的功能。
4. 如果子查询返回多个记录,我们必须在子查询之前使用多值运算符。
5. 我们可以在子查询中使用BETWEEN运算符,但不能与子查询一起使用。
使用SELECT语句的子查询
在SQL中,最常与SELECT语句一起使用内嵌查询或嵌套查询。子查询与SELECT语句的语法如下所示:
SELECT Column_Name1, Column_Name2, ...., Column_NameN
FROM Table_Name WHERE Column_Name Comparison_Operator
( SELECT Column_Name1, Column_Name2, ...., Column_NameN
FROM Table_Name WHERE condition;
使用SELECT语句的子查询示例
示例1: 此示例使用了Subquery和大于比较运算符。
假设我们有以下名为Student_Details的表,其中包含Student_RollNo.、Stu_Name、Stu_Marks和Stu_City列。
Student_RollNo. | Stu_Name | Stu_Marks | Stu_City |
---|---|---|---|
1001 | Akhil | 85 | Agra |
1002 | Balram | 78 | Delhi |
1003 | Bheem | 87 | Gurgaon |
1004 | Chetan | 95 | Noida |
1005 | Diksha | 99 | Agra |
1006 | Raman | 90 | Ghaziabad |
1007 | Sheetal | 68 | Delhi |
以下SQL查询返回那些成绩高于总成绩平均分的学生记录:
SELECT * FROM Student_Details WHERE Stu_Marks> ( SELECT AVG(Stu_Marks ) FROM Student_Details);
输出:
Student_RollNo. | Stu_Name | Stu_Marks | Stu_City |
---|---|---|---|
1003 | Bheem | 87 | Gurgaon |
1004 | Chetan | 95 | Noida |
1005 | Diksha | 99 | Agra |
1006 | Raman | 90 | Ghaziabad |
示例2: 此示例使用子查询的IN操作符。
我们来看一下下面的两个表,名称分别为 Faculty_Details 和 Department 。其中 Faculty_Details 表包含了教师的ID、姓名、部门ID和地址。而 Department 表包含了部门ID、教师ID和部门名称。
Faculty_ID | Name | Dept_ID | Address
—|—|—|—
101 | Bheem | 1 | Gurgaon
102 | Chetan | 2 | Noida
103 | Diksha | NULL | Agra
104 | Raman | 4 | Ghaziabad
105 | Yatin | 3 | Noida
106 | Anuj | NULL | Agra
107 | Rakes | 5 | Gurgaon
Dept_ID | Faculty_ID | Dept_Name |
---|---|---|
1 | 101 | BCA |
2 | 102 | B.Tech |
3 | 105 | BBA |
4 | 104 | MBA |
5 | 107 | MCA |
SELECT * FROM Department WHERE Faculty_ID IN (
SELECT Faculty_ID FROM Faculty WHERE City = 'Noida' OR City = 'Gurgaon' ) ;
输出:
Dept_ID | Faculty_ID | Dept_Name |
---|---|---|
1 | 101 | BCA |
2 | 102 | B.Tech |
3 | 105 | BBA |
5 | 107 | MCA |
子查询与INSERT语句
在结构化查询语言中,我们也可以使用子查询和嵌套查询与INSERT语句一起使用。我们可以将子查询的结果插入到外部查询的表中。子查询与INSERT语句的语法如下所示:
INSERT INTO Table_Name SELECT * FROM Table_Name WHERE Column_Name Operator (Subquery);
插入语句中子查询的示例
示例1: 此示例使用带有WHERE子句的子查询将一张表的记录插入到另一张表中。
让我们来看看Old_Employee和New_Employee表。Old_Employee和New_Employee表包含相同数量的列。但是,两个表包含不同的记录。
Emp_ID | Emp_Name | Emp_Salary | Address |
---|---|---|---|
1001 | Akhil | 50000 | Agra |
1002 | Balram | 25000 | Delhi |
1003 | Bheem | 45000 | Gurgaon |
1004 | Chetan | 60000 | Noida |
1005 | Diksha | 30000 | Agra |
1006 | Raman | 50000 | Ghaziabad |
1007 | Sheetal | 35000 | Delhi |
表格:Old_Employee
Emp_ID | Emp_Name | Emp_Salary | Address |
---|---|---|---|
1008 | Sumit | 50000 | Agra |
1009 | Akash | 55000 | Delhi |
1010 | Devansh | 65000 | Gurgaon |
表:New_Employee
New_Employee包含新员工的详细信息。如果您想将薪资大于40000的员工的详细信息从Old_Employee表移动到New_Employee表中。针对这个问题,您需要在SQL中键入以下查询:
INSERT INTO New_Employee SELECT * FROM Old_Employee WHERE Emp_Salary > 40000;
现在,您可以使用以下SELECT查询来检查更新的New_Employee表的详细信息:
SELECT * FROM New_Employee;
输出:
Emp_ID | Emp_Name | Emp_Salary | Address |
---|---|---|---|
1008 | Sumit | 50000 | Agra |
1009 | Akash | 55000 | Delhi |
1010 | Devansh | 65000 | Gurgaon |
1001 | Akhil | 50000 | Agra |
1003 | Bheem | 45000 | Gurgaon |
1004 | Chetan | 60000 | Noida |
1006 | Raman | 50000 | Ghaziabad |
表:New_Employee
示例2: 这个示例描述了如何在INSERT语句中使用带有子查询的ANY运算符。
这里我们已经取出了New_Employee、old_Employee和Department表的数据。
New_Employee表的数据如下表所示:
Emp_ID | Emp_Name | Emp_Salary | Dept_ID |
---|---|---|---|
1008 | Sumit | 50000 | 401 |
表格: New_Employee
旧员工表的数据如下表所示:
Emp_ID | Emp_Name | Emp_Salary | Dept_ID |
---|---|---|---|
1001 | Akhil | 50000 | 404 |
1002 | Balram | 25000 | 403 |
1003 | Bheem | 45000 | 405 |
1004 | Chetan | 60000 | 402 |
1005 | Ram | 65000 | 407 |
1006 | Shyam | 55500 | NULL |
1007 | Shobhit | 60000 | NULL |
表格:Old_Employee
Dept_ID | Dept_Name | Emp_ID |
---|---|---|
401 | Administration | 1008 |
402 | HR | 1004 |
403 | Testing | 1002 |
404 | Coding | 1001 |
405 | Sales | 1003 |
406 | Marketing | NULL |
407 | Accounting | 1005 |
INSERT INTO New_Employee
SELECT * FROM Old_Employee
WHERE Emp_ID = ANY( SELECT Emp_ID FROM Department WHERE Dept_ID = 407 OR Dept_ID = 406 );
现在,通过使用以下SELECT语句检查New_Employee表的详细信息:
输出:
Emp_ID | Emp_Name | Emp_Salary | Dept_ID |
---|---|---|---|
1008 | Sumit | 50000 | 401 |
1005 | Ram | 65000 | 407 |
UPDATE语句中的子查询
子查询和嵌套查询可以在结构化查询语言中与UPDATE语句一起使用,用于更新现有表的列。我们可以使用带有UPDATE语句的子查询轻松地更新一个或多个列。
使用UPDATE语句的子查询的语法
UPDATE Table_Name SET Column_Name = New_value WHERE Value OPERATOR (SELECT COLUMN_NAME FROM TABLE_NAME WHERE Condition) ;
使用UPDATE语句的子查询示例
这个例子使用UPDATE语句中的IN运算符和子查询更新了一个表的记录。
让我们来看一个Employee_Details和Department表。
Employee_Details表的数据如下所示:
Emp_ID | Emp_Name | Emp_Salary | Dept_ID |
---|---|---|---|
1001 | Akhil | 50000 | 404 |
1002 | Balram | 25000 | 403 |
1003 | Bheem | 45000 | 405 |
1004 | Chetan | 60000 | 402 |
1005 | Ram | 65000 | 407 |
1006 | Shyam | 55500 | NULL |
1007 | Shobhit | 60000 | NULL |
表格:员工详情
下表显示了部门表的数据:
Dept_ID | Dept_Name | Emp_ID | Dept_Grade |
---|---|---|---|
401 | Administration | 1008 | B |
402 | HR | 1004 | A |
403 | Testing | 1002 | A |
404 | Coding | 1001 | B |
405 | Sales | 1003 | A |
406 | Marketing | NULL | C |
407 | Accounting | 1005 | A |
以下是将部门等级为A的员工的薪水更新:
UPDATE Employee_Details SET Emp_Salary = Emp_Salary + 5000 WHERE Emp_ID IN ( SELECT Emp_ID FROM Department WHERE Dept_Grade = 'A' ) ;
以下查询将在输出中显示Employee_Details表的更新数据:
SELECT * FROM Employee_Details ;
输出:
Emp_ID | Emp_Name | Emp_Salary | Dept_ID |
---|---|---|---|
1001 | Akhil | 50000 | 404 |
1002 | Balram | 30000 | 403 |
1003 | Bheem | 50000 | 405 |
1004 | Chetan | 65000 | 402 |
1005 | Ram | 70000 | 407 |
1006 | Shyam | 55500 | NULL |
1007 | Shobhit | 60000 | NULL |
表格:员工详情
删除语句中的子查询
我们可以使用结构化查询语言中的带有DELETE语句的子查询轻松地从SQL表中删除一个或多个记录。
带有DELETE语句的子查询的语法
DELETE FROM Table_Name WHERE Value OPERATOR (SELECT COLUMN_NAME FROM TABLE_NAME WHERE Condition) ;
DELETE语句中使用子查询的示例
此示例使用DELETE语句中的子查询和IN运算符从表中删除记录。
让我们来看一个Employee_Details和Department表。
Employee_Details表的数据如下表所示:
Emp_ID | Emp_Name | Emp_Salary | Dept_ID |
---|---|---|---|
1001 | Akhil | 50000 | 404 |
1002 | Balram | 25000 | 403 |
1003 | Bheem | 45000 | 405 |
1004 | Chetan | 60000 | 402 |
1005 | Ram | 65000 | 407 |
1006 | Shyam | 55500 | NULL |
1007 | Shobhit | 60000 | NULL |
1008 | Ankit | 48000 | 401 |
表: 员工详情
部门表的数据如下表所示:
Dept_ID | Dept_Name | Emp_ID | Dept_Grade |
---|---|---|---|
401 | Administration | 1008 | C |
402 | HR | 1004 | A |
403 | Testing | 1002 | C |
404 | Coding | 1001 | B |
405 | Sales | 1003 | A |
406 | Marketing | NULL | C |
407 | Accounting | 1005 | C |
以下查询从Employee_Details中删除部门等级为C的员工记录:
DELETE FROM Employee_Details WHERE Emp_ID IN ( SELECT Emp_ID FROM Department WHERE Dept_Grade = 'C' ) ;
以下查询将显示Employee_Details表的更新数据输出:
SELECT * FROM Employee_Details ;
输出:
Emp_ID | Emp_Name | Emp_Salary | Dept_ID |
---|---|---|---|
1001 | Akhil | 50000 | 404 |
1003 | Bheem | 45000 | 405 |
1004 | Chetan | 60000 | 402 |
1006 | Shyam | 55500 | NULL |
1007 | Shobhit | 60000 | NULL |
表格:员工详情