SQL基础知识--一文带你学会SQL

工欲善其事必先利其器

本专栏会提供一个基础的数据库表文件:下载地址:
DB文件
。你可以自己下载支持 sql lite 的软件例如:SQLite Expert,然后在里面执行本专栏的所有 sql 操作。
如果你不想自己安装环境,本专栏也提供了 google colab 在线sql运行
在这里插入图片描述
在线运行 sql 语句的方式,看你自己的喜好,但学任何语言都一样,一定要自己实操才会掌握的更加深刻。

数据库基础概念

数据库是一个组织数据的集合,它存储在计算机系统中以便有效地访问、管理和更新。数据库系统由一组相关的数据和用于访问、管理和操作这些数据的软件组件组成。

以下是数据库基础概念的一些重要要点:

  1. 数据库管理系统(DBMS):数据库管理系统是用于管理数据库的软件系统。它提供了一组工具和功能,用于创建、访问、修改和维护数据库。

  2. 数据库:数据库是一个包含相关数据的结构化集合。它可以是一个简单的表格,也可以是由多个表格组成的复杂结构。

  3. 表格(表):表格是数据库中数据的组织方式。表格由行和列组成,每一行表示一个实体或记录,每一列表示数据的属性。

  4. 列(字段):列是表格中的垂直单元格,用于存储特定类型的数据。每一列都有一个名称和一个数据类型。

  5. 行(记录):行是表格中的水平单元格,表示一个实体或记录。每一行包含一组数据,每一列的值对应于该行的属性。

  6. 主键:主键是表格中唯一标识每一行的列。它保证了每一行的唯一性,并提供了一种快速访问数据的方式。

  7. 外键:外键是一个表格中引用另一个表格的列。它用于建立表格之间的关系,确保数据的一致性和完整性。

  8. 查询语言:查询语言是用于在数据库中检索和操作数据的语言。常见的查询语言包括结构化查询语言(SQL)和NoSQL数据库的查询语言。

  9. 常见的数据库类型:关系型数据库(如MySQL、Oracle、SQL Server)以表格形式存储数据;NoSQL数据库(如MongoDB、Cassandra)以键值对、文档或图形结构存储数据。

select 语句

SELECT语句是SQL中最常用的语句之一,用于从数据库中检索数据。它的基本语法如下:

SELECT 列名或表达式
FROM 表名
[WHERE 条件]
[GROUP BY 列名]
[HAVING 条件]
[ORDER BY 列名 [ASC|DESC]]

以下是对每个部分的解释:

  • SELECT: 指定要检索的列名或表达式。您可以使用通配符(*)选择所有列,或者逐个指定列名。您还可以使用算术运算、函数和其他表达式来计算新的列。
  • FROM: 指定要从中检索数据的表名。您可以指定单个表,或者使用JOIN子句连接多个表。
  • WHERE: 可选项,用于指定检索数据的条件。只有满足条件的行将被返回。
  • GROUP BY: 可选项,用于对结果集进行分组。通常与聚合函数一起使用,例如SUM、COUNT等。查询将根据指定的列进行分组,并为每个组计算一个值。
  • HAVING: 可选项,用于筛选GROUP BY后的结果集。类似于WHERE子句,但HAVING是在分组之后应用的。
  • ORDER BY: 可选项,用于按指定的列对结果集进行排序。默认情况下,使用ASC(升序)排序。添加DESC关键字可以进行降序排序。

下面是一个示例,展示了如何使用SELECT语句从"Customers"表中选择特定的列:

SELECT cust_name, cust_email
FROM Customers;

这将返回一个结果集,其中包含"Customers"表中的所有行的"cust_name"和"cust_email"列。
在这里插入图片描述

查询单个列

如果你只想查询表中的单个列,你可以使用SELECT语句,并指定要查询的列名。

SELECT 列名
FROM 表名;

让我们以查询"Customers"表的"cust_name"列为例:

SELECT cust_name
FROM Customers;

这将返回"Customers"表中所有顾客的姓名。

如果你只想查询特定条件下的列,可以添加WHERE子句来过滤结果。例如,查询"Customers"表中居住在"USA"的顾客的姓名:

SELECT cust_name
FROM Customers
WHERE cust_country = 'USA';

注意,列名不区分大小写,但是字符串值需要用单引号括起来。

查询所有的列

如果你想查询表中的所有列,可以使用通配符 “*” 来代表所有列。以下是一个示例:

SELECT *
FROM 表名;

让我们以查询"Customers"表中所有列的数据为例:

SELECT *
FROM Customers;

这将返回"Customers"表中所有行的所有列的数据。

注意,使用通配符 “*” 可以方便地查询所有列,但也可能导致返回大量的数据。在实际使用中,要根据需要仅选择需要的列,以提高查询效率和减少数据传输量。

查询不同的值:重复的值不每次都出现

如果你想要查询某一列中的不同值,而不重复显示重复值,你可以使用DISTINCT关键字。这将返回该列中的唯一值。下面是一个示例查询:

SELECT DISTINCT column_name FROM table_name;

请将column_name替换为你想要查询的列的名称,将table_name替换为相应的表名。

以下是对于不同表中不同列的示例查询和结果:

  1. 查询Customers表中不同的国家:
SELECT DISTINCT cust_country FROM Customers;

查询结果:

cust_country
------------
USA
  1. 查询Orders表中不同的客户ID:
SELECT DISTINCT cust_id FROM Orders;

查询结果:

cust_id
-----------
1000000001
1000000003
1000000004
1000000005
  1. 查询Products表中不同的产品名称:
SELECT DISTINCT prod_name FROM Products;

查询结果:

prod_name
------------------
8 inch teddy bear
12 inch teddy bear
18 inch teddy bear
Fish bean bag toy
Bird bean bag toy
Rabbit bean bag toy
Raggedy Ann
King doll
Queen doll

以上是使用DISTINCT关键字查询不同值的示例。

只返回一行或者一定数量的行

如果你只想返回一行或者固定数量的行,可以使用LIMIT关键字来限制查询结果的行数。LIMIT用法如下:

SELECT * FROM table_name LIMIT number_of_rows;

请将table_name替换为你要查询的表名,将number_of_rows替换为你想要返回的行数。

以下是对于不同表的示例查询和结果:

  1. 查询Customers表中的一行数据:
SELECT * FROM Customers LIMIT 1;

查询结果将返回Customers表中的第一行数据。

  1. 查询Orders表中的前5行数据:
SELECT * FROM Orders LIMIT 5;

查询结果将返回Orders表中的前5行数据。
在这里插入图片描述
使用LIMIT关键字可以帮助你控制查询结果的行数。

使用注释

如果你想在SQL语句中使用注释,可以在注释内容前加上双连字符(--)或使用/* */来注释多行内容。

以下是示例查询语句,其中包含注释:

-- 查询Customers表中不同的国家
SELECT DISTINCT cust_country -- DISTINCT关键字用于返回不同的国家
FROM Customers;

-- 查询Orders表中不同的客户ID
SELECT DISTINCT cust_id -- DISTINCT关键字用于返回不同的客户ID
FROM Orders;

/* 
查询Products表中不同的产品名称
这是一个多行注释示例
*/
SELECT DISTINCT prod_name -- DISTINCT关键字用于返回不同的产品名称
FROM Products;

请注意,注释在SQL语句中不会影响实际的查询逻辑或结果。它们仅供程序员添加解释、文档或注释查询目的使用。在执行以上示例查询时,注释部分将被忽略,只执行实际的查询操作。

order by 对数据进行排序

当需要按特定字段对数据进行排序时,可以使用SQL中的ORDER BY子句。ORDER BY子句允许指定一个或多个字段,根据这些字段的值对结果进行排序。排序可以是升序(从小到大)或降序(从大到小)。

以下是ORDER BY子句的语法:

SELECT 列名
FROM 表名
ORDER BY 列名 [ASC | DESC];

ORDER BY子句中,你需要指定一个或多个列名,用于进行排序。默认情况下,排序是按升序进行的,如果要进行降序排序,则需在列名后面添加关键字DESC

以下是根据示例查询展示的几种排序示例:

  1. 按照Customers表中的cust_name字段进行升序排序:
SELECT * FROM Customers ORDER BY cust_name ASC;

这将返回Customers表中按照cust_name字段值从A到Z进行排序的结果。

  1. 按照Orders表中的order_date字段进行降序排序:
SELECT * FROM Orders ORDER BY order_date DESC;

这将返回Orders表中按照order_date字段值从最近的日期到最早的日期进行排序的结果。

  1. 按照Products表中的prod_price字段进行升序排序,并且只返回前5条记录:
SELECT * FROM Products ORDER BY prod_price ASC LIMIT 5;

这将返回Products表中按照prod_price字段值从低到高进行排序的前5条记录。

请注意,ORDER BY子句通常用于在查询结果中进行排序。它适用于单个表或多个表之间的连接查询。

order by-对数据按多个列进行排序

当需要对多个列进行排序时,可以在ORDER BY子句中指定多个列名,以便按照给定的列顺序进行排序。

以下是根据示例查询展示的对多个列排序的示例:

  1. 按照Customers表中的cust_country字段进行升序排序,如果两个记录的cust_country相同,则按照cust_city字段进行升序排序:
SELECT * FROM Customers ORDER BY cust_country ASC, cust_city ASC;

这将返回Customers表中按照cust_country字段的值进行升序排序,如果cust_country相同,则按照cust_city字段的值进行升序排序。

  1. 按照OrderItems表中的order_num字段进行升序排序,如果两个记录的order_num相同,则按照item_price字段进行降序排序:
SELECT * FROM OrderItems ORDER BY order_num ASC, item_price DESC;

在这里插入图片描述

这将返回OrderItems表中按照order_num字段的值进行升序排序,如果order_num相同,则按照item_price字段的值进行降序排序。

你可以根据需要选择多个列进行排序,同时还可以选择升序(ASC)或降序(DESC)排序。

order by-按列的位置排序

当按照列的位置进行排序时,我们可以使用列的索引位置(从1开始)来替代列名进行排序。在ORDER BY子句中,可以使用列的位置替代列名。

以下是根据示例查询展示的按列位置排序的示例:

  1. 使用列位置按升序排序:
SELECT * FROM Customers ORDER BY 2 ASC;

这将返回Customers表中按第二列(cust_name列)的值进行升序排序的结果。

  1. 使用列位置按降序排序:
SELECT * FROM Orders ORDER BY 3 DESC;

这将返回Orders表中按第三列(cust_id列)的值进行降序排序的结果

where 过滤数据

使用WHERE子句可以实现数据的过滤,它允许您指定条件来筛选出满足特定条件的数据记录。

以下是使用WHERE子句进行数据过滤的示例:

  1. 在Customers表中,筛选出cust_country为"USA"的记录:
SELECT * FROM Customers WHERE cust_country = 'USA';

这将返回Customers表中cust_country为"USA"的所有记录。

  1. 在OrderItems表中,筛选出quantity大于等于100的记录:
SELECT * FROM OrderItems WHERE quantity >= 100;

这将返回OrderItems表中quantity大于等于100的所有记录。

  1. 在Products表中,筛选出prod_price小于10的记录,并且vend_id不为空的记录:
SELECT * FROM Products WHERE prod_price < 10 AND vend_id IS NOT NULL;

这将返回Products表中prod_price小于10并且vend_id不为空的所有记录。

where 子句:AND OR IN NOT IN NOT

当使用WHERE子句进行数据过滤时,可以使用以下逻辑运算符和关键字来构建条件:

  1. AND:用于将多个条件组合,只有当所有条件都为真时,才返回记录。
SELECT * FROM table_name WHERE condition1 AND condition2;

示例:

SELECT * FROM Customers WHERE cust_country = 'USA' AND cust_state = 'CA';

这将返回Customers表中cust_country为"USA"且cust_state为"CA"的记录。

  1. OR:用于将多个条件组合,只要满足其中一个条件就返回记录。
SELECT * FROM table_name WHERE condition1 OR condition2;

示例:

SELECT * FROM Customers WHERE cust_country = 'USA' OR cust_country = 'Canada';

这将返回Customers表中cust_country为"USA"或"Canada"的记录。

  1. IN:用于指定一个值列表,如果待筛选的值与列表中的任何一个匹配,则返回记录。
SELECT * FROM table_name WHERE column_name IN (value1, value2, ...);

示例:

SELECT * FROM Customers WHERE cust_country IN ('USA', 'Canada');

这将返回Customers表中cust_country为"USA"或"Canada"的记录。

  1. NOT IN:与IN相反,用于指定一个值列表,如果待筛选的值不在列表中,则返回记录。
SELECT * FROM table_name WHERE column_name NOT IN (value1, value2, ...);

示例:

SELECT * FROM Customers WHERE cust_country NOT IN ('USA', 'Canada');

这将返回Customers表中cust_country不是"USA"或"Canada"的记录。

  1. NOT:用于取反条件,返回不满足指定条件的记录。
SELECT * FROM table_name WHERE NOT condition;

示例:

SELECT * FROM Customers WHERE NOT cust_country = 'USA';

这将返回Customers表中cust_country不是"USA"的记录。

通配符过滤 like

在SQL中,可以使用LIKE操作符结合通配符来进行模糊匹配和筛选数据。LIKE操作符允许您使用通配符来代表任意字符或字符集。以下是一些常见的通配符:

  1. %:代表零个或多个字符。
SELECT * FROM table_name WHERE column_name LIKE 'pattern%';

示例:

SELECT * FROM Customers WHERE cust_name LIKE 'Fun%';

这将返回Customers表中cust_name以"Fun"开头的记录。

  1. _:代表一个单个字符。
SELECT * FROM table_name WHERE column_name LIKE 'pattern_';

示例:

SELECT * FROMCustomers WHERE cust_name LIKE '_on%';

这将返回Customers表中cust_name第二个字符为"o"且以"on"开头的记录。

  1. []:用于指定一个字符集合,匹配其中任意一个字符。
SELECT * FROM table_name WHERE column_name LIKE '[character_set]';

示例:

SELECT * FROM Customers WHERE cust_name LIKE '[JM]%';

这将返回Customers表中cust_name以"J"或"M"开头的记录。

  1. [^]:用于指定一个不在字符集合中的字符。
SELECT * FROM table_name WHERE column_name LIKE '[^character_set]';

示例:

SELECT * FROM Customers WHERE cust_name LIKE '[^A]%';

这将返回Customers表中cust_name不以"A"开头的记录。

LIKE操作符配合通配符可以让您根据模式筛选出满足特定条件的记录。

计算字段&拼接字段

在SQL中,可以使用计算字段和拼接字段来创建新的字段或将多个字段组合在一起。下面是如何在SQL中进行计算字段和拼接字段:

计算字段:
计算字段是通过对表中现有字段进行数学运算、字符操作或函数运算而创建的新字段。您可以使用算术运算符(如+,-,*,/)以及内置函数(如SUM,AVG,COUNT)来操作字段数据并生成计算结果。

示例:
假设我们有一个名为Products的表,其中包含prod_name(产品名称)和prod_price(产品价格)列。可以创建一个计算字段discounted_price,计算产品价格打折后的价格:

SELECT prod_name, prod_price, prod_price * 0.9 AS discounted_price
FROM Products;

这将返回包含产品名称、原始价格和打折后价格的结果集。计算字段discounted_price通过将prod_price与0.9相乘来计算。

拼接字段:
拼接字段是将多个字段的值合并为一个字段的操作。可以使用字符串连接函数(如CONCAT)或操作符(如||)将字段值进行拼接。

示例:
假设我们有一个名为Customers的表,其中包含cust_first_namecust_last_name列。可以创建一个拼接字段full_name,将客户的名字和姓氏拼接在一起:

SELECT cust_first_name || ' ' || cust_last_name AS full_name
FROM Customers;

这将返回包含客户全名的结果集。拼接字段通过将cust_first_name、空格字符和cust_last_name串联在一起来生成完整的姓名。

通过计算字段和拼接字段,您可以在SQL查询中创建新的字段,根据需要进行数学运算、字符操作和字符串拼接。

使用函数处理数据

在SQL中,您可以使用函数来处理数据。函数是预定义的操作,用于对数据进行转换、计算和处理。以下是一些常见的SQL函数及其用法:

  1. 字符串函数:

    • UPPER(str):将字符串转换为大写。
    • LOWER(str):将字符串转换为小写。
    • CONCAT(str1, str2):将两个字符串拼接在一起。
    • SUBSTRING(str, start, length):从字符串中提取指定范围的子字符串。
    • LENGTH(str):返回字符串的长度。
    • TRIM(str):去除字符串两端的空格。
  2. 数值函数:

    • ROUND(num, decimals):将数字四舍五入为指定小数位数。
    • ABS(num):返回数字的绝对值。
    • FLOOR(num):返回不大于指定数字的最大整数。
    • CEILING(num):返回不小于指定数字的最小整数。
  3. 聚合函数:

    • COUNT(column):计算某一列的行数。
    • SUM(column):计算某一列的总和。
    • AVG(column):计算某一列的平均值。
    • MIN(column):找出某某一列的最小值。
    • MAX(column):找出某一列的最大值。
  4. 日期和时间函数:

    • GETDATE():返回当前日期和时间。
    • DATEPART(datepart, date):返回日期的指定部分(例如年份、月份、日等)。
    • DATEADD(datepart, number, date):根据指定的日期部分增加或减少日期。
    • DATEDIFF(datepart, start_date, end_date):计算两个日期之间的差值。

示例:
假设我们有一个表Orders,其中包含order_date列(日期类型)。可以使用日期函数计算订单的年份和月份,并聚合计算每个月的订单总数:

SELECT DATEPART(YEAR, order_date) AS order_year,
       DATEPART(MONTH, order_date) AS order_month,
       COUNT (1) AS order_count
FROM Orders
GROUP BY DATEPART(YEAR, order_date), DATEPART(MONTH, order_date)
ORDER BY order_year, order_month;

这个查询会输出按年份和月份分组的订单数。结果类似于以下表格:

order_yearorder_monthorder_count
2020115
2020220
2020318

这个示例展示了如何使用日期函数 DATEPART 来提取订单日期的年份和月份,并使用聚合函数 COUNT 计算每个月的订单总数。

您可以根据您的需求使用不同的函数来处理和转换数据,这些函数在各个SQL数据库系统中基本上是通用的,但可能会有一些差异。

grop-by 创建分组

如果您想要对数据进行分组并统计每个组的聚合信息,可以使用 GROUP BY 子句。下面是一个示例:

假设我们有一个包含产品信息的表 Products,我们想要按照供应商(vend_id)对产品进行分组,并计算每个供应商的产品数量和平均价格。

SELECT vend_id, COUNT(*) AS product_count, AVG(prod_price) AS average_price
FROM Products
GROUP BY vend_id;

在这个查询中,我们使用 GROUP BY 子句将产品按照供应商进行分组。然后,使用 COUNT(*) 函数计算每个组中的产品数量,并使用 AVG(prod_price) 函数计算每个组中产品的平均价格。最后,通过 SELECT 子句选择包括供应商 ID(vend_id)、产品数量和平均价格的列。

请根据您的需求进行适当的修改,例如选择不同的分组列、应用其他聚合函数等。

我会根据您给出的代码示例,整合输出一个完整的、可以运行的代码文件,并生成对应的查询结果。下面是根据您的表结构和数据插入语句生成的代码示例:

-- 按供应商分组统计产品数量和平均价格
SELECT vend_id, COUNT(*) AS product_count, AVG(prod_price) AS average_price
FROM Products
GROUP BY vend_id;

Having 过滤分组

当我们在 SQL 查询中进行数据筛选时,可以使用 WHERE 子句来指定条件来过滤数据。WHERE 子句可以在查询中使用多个条件,使用逻辑运算符(如 AND、OR、NOT)来组合条件。

下面是一个示例,演示了如何在 SQL 查询中使用 WHERE 子句进行数据筛选:

-- 查询来自美国的客户
SELECT *
FROM Customers
WHERE cust_country = 'USA';

在这个例子中,我们使用 WHERE cust_country = 'USA' 来选择来自美国的客户。此查询将返回从 Customers 表中符合条件的所有行,即客户的国家为"USA"的行。

除了使用 WHERE 子句进行数据筛选外,我们还可以使用 GROUP BY 子句将数据按照特定的列进行分组。GROUP BY 子句将把具有相同值的行分为一组,并对每个组应用聚合函数(如 SUM、COUNT、AVG 等)。

下面是一个示例,演示了如何在 SQL 查询中使用 GROUP BY 子句进行分组:

-- 按照订单日期对订单进行分组,并计算每个分组的订单数量
SELECT order_date, COUNT(*) AS order_count
FROM Orders
GROUP BY order_date;

在这个例子中,我们使用 GROUP BY order_dateOrders 表中的订单按照日期进行分组。然后使用 COUNT(*) 函数统计每个日期分组的订单数量。最后的查询结果将返回每个日期和对应的订单数量。

此外,我们还可以使用 HAVING 子句对分组后的数据进行进一步的过滤。HAVING 子句与 WHERE 子句类似,但用于过滤分组而不是单独的行。

下面是一个示例,演示了如何在 SQL 查询中使用 HAVING 子句进行分组过滤:

-- 查询总销售量超过1000的产品
SELECT prod_id, SUM(quantity) AS total_quantity
FROM OrderItems
GROUP BY prod_id
HAVING total_quantity > 10;

在这里插入图片描述

在这个例子中,我们使用 SUM(quantity)OrderItems 表中的数量进行求和,然后使用 GROUP BY prod_id 将结果按照产品ID进行分组。接着,我们使用 HAVING total_quantity > 1000 来筛选总销售量大于1000的产品。最终的查询结果将返回符合条件的产品ID和总销售量。

这就是在 SQL 查询中使用 WHERE、GROUP BY 和 HAVING 子句进行数据筛选和分组过滤的方法。

使用子查询 & 使用子查询进行过滤

子查询是在查询语句中嵌套的另一个查询。它可以作为主查询的一部分,用于执行更复杂的操作或进行进一步的数据筛选。下面我将分别介绍使用子查询和使用子查询进行过滤的概念,并提供相应的示例代码和查询结果。

  1. 使用子查询:
    使用子查询可以将一个查询的结果嵌套到另一个查询中,以获取更复杂的结果或进行相关的数据操作。子查询可以用于选择列、计算聚合函数、进行连接操作等。

    示例代码:

    -- 找出订单总数
    SELECT COUNT(*) as total_orders
    FROM Orders;
    

    查询结果:

    +--------------+
    | total_orders |
    +--------------+
    |      5       |
    +--------------+
    
    

    在上述示例中,主查询为 SELECT COUNT(*) as total_orders FROM Orders;,它从表 Orders 中计算出订单的总数。子查询部分是 SELECT * FROM Orders;,它返回表 Orders 的所有行。

  2. 使用子查询进行过滤:
    子查询还可以用于过滤数据,即根据子查询的结果来限制主查询的结果集。子查询的结果可以与主查询的条件进行比较,以筛选出符合条件的数据。

    示例代码:

    -- 找出订购了'18 inch teddy bear'的顾客
    SELECT cust_name
    FROM Customers
    WHERE cust_id IN (
        SELECT cust_id
        FROM Orders
        WHERE order_num IN (
            SELECT order_num
            FROM OrderItems
            WHERE prod_id = 'BR03'
        )
    );
    

    查询结果:

    +-------------------+
    |    cust_name      |
    +-------------------+
    |   Village Toys    |
    | Fun4All           |
    +-------------------+
    

    上述示例中,主查询根据子查询的结果筛选出了订购了产品 ‘18 inch teddy bear’ 的顾客。子查询部分 SELECT cust_id FROM Orders WHERE order_num IN (SELECT order_num FROM OrderItems WHERE prod_id = 'BR03') 返回了订购过该产品的订单编号,然后主查询使用 WHERE cust_id IN (...) 条件获取对应的顾客名字。

以上是关于使用子查询和使用子查询进行过滤的说明和示例代码。

连接表

当我们需要从多个表中获取数据时,可以使用联结(Join)操作。联结操作将根据某些条件,将两个或多个表中的行组合在一起,形成一个新的结果集。以下是几种常见的联结操作:

  1. 内联结(Inner Join):内联结返回两个表中满足联结条件的匹配行。语法如下:
SELECT 列名
FROM1
INNER JOIN2
ON1.=2.;

示例代码:

SELECT Customers.cust_id, Customers.cust_name, Orders.order_num, Orders.order_date
FROM Customers
INNER JOIN Orders
ON Customers.cust_id = Orders.cust_id;

输出结果:

+------------+--------------+-----------+------------+
| cust_id    | cust_name    | order_num | order_date |
+------------+--------------+-----------+------------+
| 1000000001 | Village Toys | 20005     | 2020-05-01 |
| 1000000003 | Fun4All      | 20006     | 2020-01-12 |
| 1000000004 | Fun4All      | 20007     | 2020-01-30 |
| 1000000001 | Village Toys | 20008     | 2020-02-03 |
| 1000000001 | Village Toys | 20009     | 2020-02-08 |
+------------+--------------+-----------+------------+
  1. 左外联结(Left Outer Join):左外联结返回左表中的所有行,以及满足联结条件的右表中的匹配行。如果右表中没有匹配行,则用 NULL 值填充。语法如下:
SELECT 列名
FROM1
LEFT JOIN2
ON1.=2.;

示例代码:

SELECT Customers.cust_id, Customers.cust_name, Orders.order_num, Orders.order_date
FROM Customers
LEFT JOIN Orders
ON Customers.cust_id = Orders.cust_id;

输出结果:

+------------+--------------+-----------+------------+
| cust_id    | cust_name    | order_num | order_date |
+------------+--------------+-----------+------------+
| 1000000001 | Village Toys | 20005     | 2020-05-01 |
| 1000000002 | Kids Place   | NULL      | NULL       |
| 1000000003 | Fun4All      | 20006     | 2020-01-12 |
| 1000000004 | Fun4All      | 20007     | 2020-01-30 |
| 1000000005 | The Toy Store| 20008     | 2020-02-03 |
| 1000000001 | Village Toys | 20009     | 2020-02-08 |
+------------+--------------+-----------+------------+
  1. 右外联结(Right Outer Join):右外联结返回右表中的所有行,以及满足联结条件的左表中的匹配行。如果左表中没有匹配行,则用 NULL 值填充。语法如下:
SELECT 列名
FROM1
RIGHT JOIN2
ON1.=2.;

示例代码:

SELECT Customers.cust_id, Customers.cust_name, Orders.order_num, Orders.order_date
FROM Customers
RIGHT JOIN Orders
ON Customers.cust_id = Orders.cust_id;

输出结果:

+------------+--------------+-----------+------------+
| cust_id    | cust_name    | order_num | order_date |
+------------+--------------+-----------+------------+
| 1000000001 | Village Toys | 20005     | 2020-05-01 |
| 1000000003 | Fun4All      | 20006     | 2020-01-12 |
| 1000000004 | Fun4All      | 20007     | 2020-01-30 |
| 1000000005 | The Toy Store| 20008     | 2020-02-03 |
| 1000000001 | Village Toys | 20009     | 2020-02-08 |
| NULL       | NULL         | 20010     | 2020-03-15 |
+------------+--------------+-----------+------------+
  1. 全外联结:全外联结(Full Outer Join)是一种用于组合两个表中所有记录的联结操作。它返回两个表中的所有行,如果某行在其中一个表中存在但在另一个表中不存在,则用 NULL 值填充缺失的列。

在 SQL 中,我们可以使用 FULL OUTER JOINLEFT JOINRIGHT JOIN 的组合来实现全外联结。下面是一个示例的查询代码:

SELECT Customers.cust_id, Orders.order_num
FROM Customers
FULL OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id;

这个查询将返回 Customers 表和 Orders 表中所有行的 cust_idorder_num 列。左连结 (LEFT JOIN) 和右连结 (RIGHT JOIN) 组合在一起实现了全外连接的效果。

根据给定的数据库表内容,假设 Customers 表和 Orders 表的数据如下:

Customers 表

cust_idcust_name
1000000001Village Toys
1000000002Kids Place
1000000003Fun4All

Orders 表

order_numcust_id
200051000000001
200061000000003
200071000000004

运行上面的查询代码后,该查询将返回下面的结果:

cust_idorder_num
100000000120005
1000000002NULL
100000000320006
NULL20007

结果中的第一行表示 cust_id 为 “1000000001” 的客户与订单 “20005” 相关联,相应地,第三行表示 cust_id 为 “1000000003” 的客户与订单 “20006” 相关联。结果中的第二行和第四行分别表示客户和订单之间的缺失关联。

这就是一个使用全外联结的示例,它将两个表中的记录按照关联条件进行组合,并返回所有行,填充缺失的列为 NULL。

插入数据

插入数据是 SQL 中的一项基本操作,用于向表中添加新的数据行。以下是插入数据的相关用法和步骤:

  1. 了解表结构:在开始插入数据之前,你需要了解将要插入数据的表的结构,包括表名、列名和数据类型。这可以通过查看表的创建语句或表的描述来获取。

  2. 构造插入语句:根据表的结构,构造插入语句。插入语句的基本格式如下:

    INSERT INTO 表名 (列1, 列2, 列3, ...) VALUES (值1, 值2, 值3, ...)
    

    这里,“表名” 是要插入数据的表的名称。“列1, 列2, 列3, …” 是要插入数据的表的列名,如果不指定列名,插入语句将为所有列插入数据。“值1, 值2, 值3, …” 是要插入的具体值,顺序与列名对应。

  3. 执行插入语句:使用 SQL 数据库客户端或集成开发环境(IDE)连接到数据库,并执行构造好的插入语句。

  4. 验证插入结果:验证插入是否成功,可以查询表中的数据或使用其他方式进行验证。

以下是一个示例,演示如何插入数据到 “Customers” 表中:

INSERT INTO Customers (cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES ('1000000006', 'Toy World', '123 Oak Street', 'Los Angeles', 'CA', '90001', 'USA', 'Sarah Johnson', 'info@toyworld.com');

该示例在 “Customers” 表中插入了一个新的客户信息。插入语句指定了要插入的列和相应的值。

插入完整行

要插入部分行数据,可以在插入语句中指定要插入的列,并为这些列提供相应的值。以下是一个示例,演示如何插入部分行数据到 “Customers” 表中:

INSERT INTO Customers (cust_name, cust_city, cust_country)
VALUES ('ABC Company', 'New York', 'USA'),
       ('XYZ Corporation', 'Chicago', 'USA');

以上示例中,使用 INSERT INTO 语句插入了两行数据到 “Customers” 表中,只指定了要插入的列(cust_name、cust_city 和 cust_country)和相应的值,省略了其他列的值。每一行的值用逗号分隔。

你可以根据具体的需求,构造类似的插入语句,指定要插入的列和相应的值。然后执行插入语句,最后验证插入结果。

请注意,在执行插入操作之前,确保所有必需的列都有合适的值或提供了默认值,以避免插入失败或出现错误。

插入部分行

要插入部分行数据,可以在插入语句中指定要插入的列,并为这些列提供相应的值。以下是一个示例,演示如何插入部分行数据到 “Customers” 表中:

INSERT INTO Customers (cust_name, cust_city, cust_country)
VALUES ('ABC Company', 'New York', 'USA'),
       ('XYZ Corporation', 'Chicago', 'USA');

以上示例中,使用 INSERT INTO 语句插入了两行数据到 “Customers” 表中,只指定了要插入的列(cust_name、cust_city 和 cust_country)和相应的值,省略了其他列的值。每一行的值用逗号分隔。

你可以根据具体的需求,构造类似的插入语句,指定要插入的列和相应的值。然后执行插入语句,最后验证插入结果。

请注意,在执行插入操作之前,确保所有必需的列都有合适的值或提供了默认值,以避免插入失败或出现错误。

从一个表复制到另外一个表

要从一个表复制数据到另一个表,可以使用 INSERT INTO SELECT 语句。该语句将选择源表中的数据,并将其插入到目标表中。
在执行插入数据前,需要确保目标表已经创建。如果目标表不存在,可以使用 CREATE TABLE 语句先创建一个与源表结构相同的目标表。下面是具体的步骤:

创建目标表:使用与源表相同的表结构创建目标表。假设要从 “Customers” 表复制数据到一个名为 “NewCustomers” 的表,可以使用以下语句创建目标表:

CREATE TABLE NewCustomers
AS
SELECT *
FROM Customers
WHERE 1=0;
该语句使用 SELECT INTO 语法创建 “NewCustomers” 表,并从 “Customers” 表选择所有列(*)。

如何从 “Customers” 表复制数据到 “NewCustomers” 表中:

INSERT INTO NewCustomers (cust_id, cust_name, cust_city, cust_country)
SELECT cust_id, cust_name, cust_city, cust_country
FROM Customers;

以上示例中,使用 INSERT INTO SELECT 语句将 “Customers” 表中的数据复制到 “NewCustomers” 表中。通过在 INSERT INTO 子句中指定目标表的列名,在 SELECT 子句中选择源表的列名。确保源表和目标表的列顺序和数据类型匹配。

执行该语句后,源表中的数据将被复制到目标表中。

更新和删除数据

要更新和删除数据,可以使用 SQL 中的 UPDATE 和 DELETE 语句。下面我将为你详细介绍这两个操作的用法。

  1. 更新数据:
    使用 UPDATE 语句可以修改表中的数据。下面是一个示例,说明如何更新 “Customers” 表中的数据:

    UPDATE Customers
    SET cust_city = 'New York'
    WHERE cust_id = '1000000001';
    

    在上面的示例中,我们将 “Customers” 表中 cust_id 为 ‘1000000001’ 的记录的 cust_city 字段更新为 ‘New York’。通过使用 SET 子句指定需要更新的列和新值,使用 WHERE 子句指定要更新的行。

  2. 删除数据:
    使用 DELETE 语句可以从表中删除数据。下面是一个示例,演示如何删除 “Customers” 表中的数据:

    DELETE FROM Customers
    WHERE cust_id = '1000000005';
    

    在上面的示例中,我们删除了 “Customers” 表中 cust_id 为 ‘1000000005’ 的记录。使用 DELETE FROM 子句指定要删除的表,使用 WHERE 子句指定要删除的行。

请注意,执行更新和删除操作前,请确保你具有适当的权限,并仔细检查 WHERE 子句,避免不小心删除或修改了不应该操作的数据。

创建表&更新表&删除表

创建表、更新表和删除表是 SQL 中常见的操作。下面我会为你逐个解释这些概念,并提供相应的示例代码和输出结果。

创建表是指在数据库中创建一个新的表格,用于存储特定类型的数据。你已经提供了创建表的 SQL 语句,下面是一个示例代码:

CREATE TABLE Customers (
  cust_id      char(10)  NOT NULL ,
  cust_name    char(50)  NOT NULL ,
  cust_address char(50)  NULL ,
  cust_city    char(50)  NULL ,
  cust_state   char(5)   NULL ,
  cust_zip     char(10)  NULL ,
  cust_country char(50)  NULL ,
  cust_contact char(50)  NULL ,
  cust_email   char(255) NULL ,
  PRIMARY KEY (cust_id)
);

上述代码创建了一个名为 Customers 的表,该表包含了多个列(字段),如 cust_idcust_namecust_address 等。每个列都有自己的数据类型和约束条件。这里的 PRIMARY KEY (cust_id) 表示 cust_id 列是主键。

更新表涉及更改现有表的结构或数据。这可以包括添加新列、修改列定义、删除列等。下面是一个更新表结构的示例代码:

ALTER TABLE Customers
ADD COLUMN cust_phone char(15) NULL;

上述代码向 Customers 表添加了一个名为 cust_phone 的新列,数据类型为 char(15),允许为空。

删除表是指从数据库中完全移除一个存在的表。下面是一个删除表的示例代码:

DROP TABLE Customers;

上述代码将完全删除数据库中的 Customers 表,表及其所有数据将被永久删除。

请注意,在执行这些代码之前,确保仔细检查和备份数据,因为操作是不可逆的。

事务管理

一个事务是一组数据库操作,这些操作作为一个单一的逻辑单元执行。事务具有以下四个特性,通常简称为ACID特性:

  1. 原子性(Atomicity):一个事务中的所有操作要么全部成功,要么全部失败。如果任何一个操作失败,系统会回滚(撤销)已经执行的操作,将数据库恢复到事务开始之前的状态。

  2. 一致性(Consistency):事务的执行不能破坏数据库的完整性。事务在开始和结束时,数据库必须处于一致的状态。如果一个事务使得数据库从一个一致状态转移到另一个一致状态,那么这个事务被认为是一致的。

  3. 隔离性(Isolation):并发执行的事务之间应该相互隔离,一个事务的操作不应该影响其他事务的操作。每个事务都应该感觉到它在独占地访问数据库。隔离级别定义了适当的隔离程度,例如:读未提交、读提交、可重复读和串行化。

  4. 持久性(Durability):一旦事务提交,其结果应该持久保存在数据库中,即使在系统故障的情况下也不会丢失。系统会将事务的结果写入永久存储器,如磁盘。

为了管理事务,SQL提供了以下命令和概念:

  1. BEGIN TRANSACTION:开始一个事务。可以使用此命令将一组相关的SQL语句组合在一起,并将它们作为一个事务执行。

  2. COMMIT:提交事务。当事务中的所有操作都成功完成时,可以使用此命令将其提交到数据库。

  3. ROLLBACK:回滚事务。如果在事务执行期间出现错误或不满足某些条件,可以使用此命令将事务回滚到开始之前的状态。

  4. SAVEPOINT:创建一个保存点。可以将保存点设置在事务中的某个位置,以便在出现错误时回滚到该点,而不是回滚整个事务。

下面是一个示例,演示如何执行事务并回滚到保存点:

BEGIN TRANSACTION;

-- 在这里执行一些 SQL 操作

SAVEPOINT my_savepoint;

-- 在这里执行一些 SQL 操作

IF <某种条件> THEN
    ROLLBACK TO my_savepoint; -- 回滚到保存点
END IF;

-- 在这里执行一些 SQL 操作

COMMIT;

在实际使用时,确保正确使用事务和保存点来保证数据的一致性和完整性。

使用游标

当涉及到复杂查询或需要逐行处理结果集时,可以使用游标(cursor)在 SQL 中进行操作。游标是一个指向结果集的数据库对象,可以遍历结果集并访问其中的数据。下面是一个使用游标的示例。

-- 声明游标
DECLARE cur_product CURSOR FOR
SELECT prod_id, prod_name, prod_price FROM Products;

-- 打开游标
OPEN cur_product;

-- 声明变量来存储获取的字段值
DECLARE @prod_id char(10);
DECLARE @prod_name char(255);
DECLARE @prod_price decimal(8,2);

-- 获取游标中的每一行数据
FETCH NEXT FROM cur_product INTO @prod_id, @prod_name, @prod_price;

-- 循环遍历游标并处理每一行数据
WHILE @@FETCH_STATUS = 0
BEGIN
  -- 在此处进行对结果集的逐行处理,可以输出、更新或者插入数据,或进行其他操作
  PRINT 'Product ID: ' + @prod_id + ', Product Name: ' + @prod_name + ', Product Price: ' + CONVERT(varchar, @prod_price);

  -- 获取游标中的下一行数据
  FETCH NEXT FROM cur_product INTO @prod_id, @prod_name, @prod_price;
END

-- 关闭游标
CLOSE cur_product;

-- 释放游标资源
DEALLOCATE cur_product;

以上示例代码将遍历 Products 表中的每一行,并输出每个产品的 ID、名称和价格。你可以根据实际需要在循环内部进行其他操作。

请注意,游标在处理大型数据集时可能效率较低,因此在实际应用中,应该尽量避免过多使用游标。在许多情况下,可以使用 SQL 的集合操作和连接来实现相同的功能,这些方法更有效率和简洁。

总结

以上,学习了解实操过一次之后,基本上就已经算是 SQL 入门了。在没那么复杂的业务中基本已经够用,语言的本质是一种工具,高级的功能可以在做数据分析功能的过程中,再继续学习。

  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值