MySQL数据库必会技能,虚拟列的用法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL数据库必会技能,虚拟列的用法相关的知识,希望对你有一定的参考价值。
参考技术A对于想要将自动生成的数据添加到表中的任何人来说, mysql 虚拟列 是一个强大、易于使用和高级的功能。
INSERT 生成的列允许您在不使用and UPDATE 子句的情况下将自动生成的数据存储在表中。 这个有用的特性自 5.7 版 起就已成为 MySQL 的一部分,它代表了在生成数据时触发器的另一种方法。此外,生成的列可以帮助您更轻松、更高效地查询。
虚拟列 列类似于普通列,但您不能手动更改其值。这是因为表达式定义了如何根据从同一行的其他列中读取的其他值来生成生成列的值。因此,生成的列在表的域内工作,其定义不能涉及 JOIN 语句。
换句话说,您可以将生成的列视为一种视图,但仅限于列。请注意,生成的列与 SQL 触发器 不同,您只能在使用 CREATE TABLE or语句时定义它们,语法如下: ALTER TABLE
该 AS (generated_column_expression) 子句指定要添加或更新到表中的列是生成的列。定义 MySQL 将用于计算列值的 generation_expression 表达式,它不能引用另一个生成的列或除当前表的列之外的任何内容。另外,请注意生成表达式只能涉及不可变函数。例如,您不能在生成的列表达式定义中使用返回当前日期的函数,因为它是一个可变函数。
您还可以在关键字前面 AS 加上 GENERATED ALWAYS 关键字以使生成的列的性质更加明确,但这是可选的。然后,您可以指示生成列的类型是 VIRTUAL 还是 STORED 。您将在下面的章节中了解这两种类型之间的区别。默认情况下,如果没有在查询中明确指定,MySQL 会将生成的列标记为 VIRTUAL .
现在让我们看看生成的列语法在 CREATE TABLE 查询中的作用:
在此示例中,该 full_name 列将自动存储 first_name 和 last_name 列的连接。
如前所述,您可以将生成的列定义为 VIRTUAL 或 STORED。现在让我们仔细看看这两种类型。
MySQL 不存储标记为 VIRTUAL 的 虚拟列 。这意味着 MySQL 在需要时动态评估其值。 BEFORE 这通常在触发任何查询后立即发生。换句话说,虚拟生成的列不占用存储空间。
MySQL 存储任何生成的标记为 STORED 的列。这意味着每次插入或更新行时,MySQL 都会评估其值并将其存储在磁盘上。换句话说,存储列需要存储空间,就好像它是普通列一样。
现在让我们进一步了解虚拟列和存储生成列的优缺点。
优点
缺点
优点
缺点
采用生成的列有几个原因,但以下三个是最重要的。
如您所见,您可以通过将四列与以下生成的列聚合来轻松生成此数据字段:
这将产生:
在这种情况下,生成的列使您能够直接在数据库级别标准化数据字段格式。此外,存储生成的列避免了每次需要时都构造此字段的不可避免的开销。
通常,您使用网站 URL 中的资源 ID 或REST API来检索您需要的数据。但是公开暴露您的 ID 可能会带来安全问题。当您发现自己使用自动增量 ID 时尤其如此,这很容易预测并使抓取或机器人攻击更容易。
为避免这种情况,您可以考虑通过使用自动生成的、随机的、更安全的公共 ID 来隐藏您的原始 ID。您可以通过对您的 ID 进行散列处理,使用虚拟生成的列来实现这一点,如下所示:
请注意,为避免生成已知的哈希值,您可以将您的 ID 与特殊关键字连接起来。 在此处了解有关 MySQL 加密和压缩功能的更多信息。
过滤数据时,有些列比其他列更有用。此外,您通常必须更改存储在列中的值的表示形式,以使过滤更简单或更直观。您可以定义一个有用的生成列来存储以所需格式执行过滤所需的信息,而不是在每个过滤器查询中执行此操作。
例如,您可以定义一个生成的列,以便更轻松地找到篮球队中的球员,如下所示:
这样的列将产生:
如前所述,您只能在表中使用生成的列。此外,它们只能涉及不可变函数,并且MySQL 生成它们的值以响应 INSERT or UPDATE 查询。另一方面,触发器是 MySQL 自动执行的存储程序,每当与特定表关联的 或 事件发生 INSERT 时 UPDATE 。 DELETE 换句话说,触发器可以涉及多个表和所有 MySQL 函数。与生成的列相比,这使它们成为更完整的解决方案。同时,MySQL 触发器本质上使用和定义更复杂,也比生成的列慢。
MySQL必知必会1
MySQL必知必会
? 了解SQL
什么是数据库:数据库(database)保存有阻止的数据的容器,可以把数据库想象成一个文件柜。
什么是表:表(table) 某种特定类型结构的结构化清单,数据库中的表的名字是唯一的。
什么是列:列(column)表中的一个字段。所有表都是有一个或多个列组成的,理解列的最好办法是将数据库表想象为一个网格,网格中每一列存储着一条特定信息。例如,编号,地址,邮政编码。
什么是行:行(row) 表中的数据是按行存储的,所保存的每个记录存储在自己的行内,例如,每一行存储一个顾客。
什么是主键:主键(primary key ) 一列(或一组列)其值能够唯一区分表中的每一行。唯一标识表中每行的这个列称为主键。主键用来表示一个特定的行,没有主键,更新或删除特定的行很困难,因为没有安全的方法保证只涉及相关的行。
什么是SQL: SQL(发音为字母S-Q-L或sequel)是结构化查询语言(Structured Query Language)的缩写,SQL是一种专门用来与数据库通信的语言。
检索数据
SELECT语句:
检索单个列:SELECT prod_name FROM products;
分析:上述语句利用SELECT语句从products表中检索一个名为prod_name的列。所需的列名在SELECT关键字之后给出,FROM关键字指出从其中检索数据的表名。
检索多个列:SELECT prod_id,prod_name,prod_price FROM products;
分析:指定了3个列名,列名之间用逗号分隔,最后一个列名不加逗号
检索所有列: SELECT * FROM products;
分析:如果给定了一个通配符(*),则返回表中的所有列。列的顺序一般是列在表中定义出现的顺序。但有时候并不是这样的,表的模式的变化(如添加或删除列),可能会导致顺序变化
检索不同的行:SELECT DISTINCT vend_id FROM products ;
分析:SELECT DISTINCT vend_id告诉MySQL只返回不同的vend_id行,如果使用DISTINCT关键字,必须放在列名的最前面
限制结果: SELECT pro_name FROM products LIMIT 5;
分析: 此语句使用SELECT语句检索单个列,LIMIT 5指示MySQL返回不多于5行
为了得到下一个5行,可指定要检索的开始行和行数: SELECT pro_name FROM products LIMIT 5 ,5
分析:LIMIT 5 , 5指示MySQL返回从行5开始的5行。第一个数为开始位置,第二个数为要检索的行数。
注意:检索从第0行开始
使用完全限定的表名:**完全限定(同时使用表名和列名)SELECT products.prod_name FROM products;
? 排序检索数据
子句: SQL语句由子句构成,有些子句是必须的,而有的是可选的,
ORDER BY: SELECT prod_name FROM products ORDER BY prod_name
分析: 选择prodects的prod_name列,对prod_name列按照字母升序
多个列排序: SELECT prod_id,pro_price,prod_name FROM products ORDER BY prod_price,prod_name;
分析: 仅在多个行具有相同的prod_price值时才对产品按prod_name进行排序。如果prod_price列中所有的值是唯一的,则不会按prod_name排序
指定排序方向: SELECT prod_id,prod_price,prod_name FROM products ORDER BY prod_price DESC;
分析:以价格降序排序产品
多个列排序: SELECT prod_id,prod_price,prod_name FROM products ORDER BY prod_price DESC,prod_name;
分析: DESC 关键字只应用到直接位于其前面的列名,prod_price列指定DESC,对prod_name列不指定。因此,prod_price列以降序排序,而prod_name仍然按标准的升序排序
如果想在多个列进行降序排序,必须对每个列指定DESC关键字
升序:ASC,默认值
? 过滤数据
只检索所需数据需要指定搜索条件,搜索条件也称为过滤条件
在SELECT语句中,数据根据WHERE子句中指定的搜索条件进行过滤,WHERE子句在表名(FROM子句)之后给出
输入: SELECT prod_name,prod_price FROM products WHERE prod_price = 2.50;
分析: 这条语句从products表中检索两个列,但不返回所有行,只返回prod_price值为2.5的行
WHERE子句操作符
操作符 | 说明 |
= | 等于 |
<> | 不等于 |
!= | 不等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
BETWEEN | 在指定的两个值之间 |
检查单个值
输入:SELECT prod_name,prod_price FROM products WHERE prod_name = ‘fuses‘
分析: 检查WHERE prod_name=‘fuses‘语句,他返回prod_name的值为Fuses的一行。MySQL在执行匹配时默认不区分大小写
范围值检查
输入: SELECT prod_name,prod_price FROM products WHERE prod_price BETWEEN 5 AND 10;
分析: 在使用BETWEEN时,必须指定两个值;所需范围的低端值和高端值,这两个值必须用AND关键字分隔,BETWEEN匹配范围中所有的值,包括指定的开始和结束值。
空值检查
在创建表时,表设计人员可以指定其中的列是否可以不包含值,一个列不包含值时,称其为包含空值NULL
输入: SELECT prod_name FROM products WHERE prod_price IS NULL;
分析: 这条语句返回没有价格的所有产品
? 数据过滤
AND操作符
为了通过不止一个列进行过滤,可以使用AND操作符给WHERE子句附加条件。下面的代码给出了一个例子:
输入: SELECT prod_id,prod_price,prod_name FROM products WHERE vend_id = 1003 AND prod_price <= 10;
分析:此sql语句检索由供应商1003制造且价格小于等于10美元的所有产品的名称和价格。
AND:用在WHERE子句中的关键字,用来指示检索满足所有给定条件的行
上述例子中使用了只包含一个关键字AND的语句。把两个过滤条件组合在一起。还可以添加多个过滤条件,每添加一条就要使用一个AND
OR操作符
OR操作符与AND操作符不同,他指示MySQL检索任一条件的行
输入: SELECT prod_name,prod_price FROM products WHERE vend_id = 1002 OR vend_id = 1003;
分析: 此SQL语句检索由任一指定供应商的所有产品的产品名和价格。OR操作符告诉DBMS匹配任一条件而不是同时匹配两个条件。
计算次序
输入: SELECT prod_name,prod_price FROM products WHERE( vend_id=1002 OR vend_id =1003) AND prod_price >=10;
分析: 圆括号具有敲AND或OR操作符高的计算次序,DBMS首先过滤圆括号内的OR条件。
IN操作符
圆括号在WHERE子句中还有另外一种用法。IN操作符用来指定条件范围,范围中的每个条件都可以进行匹配。IN取合法值的由逗号分隔的清单全都在圆括号中。
输入: SELECT prod_name,prod_price FROM products WHERE vend_id IN(1002,1003) ORDER BY prod_name;
分析: 此SELECT语句检索供应商1002和1003制造的所有产品。操作符后跟由逗号分隔的合法值清单,整个清单必须在圆括号中
IN操作符与OR具有相同的功能
NOT操作符
WHERE子句中的NOT操作符有且只有一个功能,那就是否定他之后所跟的任何条件
NOT WHERE子句中用来否定后跟条件的关键字。
输入: SELECT prod_name,prod_price FROM products WHERE vend_id NOT IN(1002,1003) ORDER BY prod_name;
分析: 这里的NOT否定跟在他之后的条件,因此MySQL不是匹配1002和1003的vend_id,而是匹配1002和1003之外的供应商的
? 用通配符进行过滤
百分号(%)通配符
最常用的通配符是百分号(%)。在搜索串中,%表示任何字符出现的任意次数。例如,为了找出所有以词jet开头的产品,可以使用一下SELECT语句:
输入: SELECT prod_id,prod_name FROM products WHERE prod_name LIKE ‘jet%‘;
分析: 此例子使用了搜索模式‘jet%‘,在执行这条子句时,将检索任意以jet起头的词。%告诉MySQL接受jet之后的任意字符,不管他有多少字符
通配符可在搜索模式中任意位置使用,并且可以使用多个通配符,下面的例子使用两个通配符,他们位于模式的两端:
输入: SELECT prod_id,prod_name FROM products WHERE prod_name LIKE ‘%anvil%‘;
分析: 搜索模式‘%anvil%‘ 表示匹配任何位置包含文本anvil的值,不论他之前或之后出现什么字符
**下划线(_)通配符**
另一个有用的通配符是下划线(_).下划线的用途与%一样,但下划线只匹配单个字符而不是多个字符
输入: SELECT prod_id,prod_name FROM products WHERE prod_name LIKE ‘_ ton anvil‘;
分析: 与%能匹配0个字符不一样,_总是匹配一个字符,不能多不能少
? 用正则表达式进行搜索
使用MySQL正则表达式
正则表达式的作用是匹配文本,将一个模式(正则表达式)与一个文本串进行比较,MySQL用WHERE子句对正则表达式提供了初步的支持,允许你指定正则表达式过滤SELECT检索出的数据
基本字符匹配
输入:SELECT prod_name FROM products WHERE prod_name REGEXP ‘1000‘ ORDER BY prod_name;
分析: 除了关键字LIKE被REGEXP替代外,这条语句非常像使用LIKE语句,他告诉MySQL:REGEXP后所跟的东西作为正则表达式(与文字正文1000匹配的一个正则表达式)处理
输入: SELECT prod_name FROM products WHERE prod_name REGEXP ‘.000‘ ORDER BY prod_name;
分析: 这里使用正则表达式.000 。.是正则表达式语言中一个特殊的 字符,他表示匹配任意一个字符。
示例:
mysql> SELECT NAME FROM account WHERE NAME REGEXP '.s' ORDER BY NAME;
+------+
| NAME |
+------+
| test |
| tsdf |
+------+
进行OR匹配
输入: SELECT prod_name FROM products WHERE prod_name REGEXP ‘1000|2000‘ ORDER BY prod_name;
分析: 语句中使用正则表达式1000|2000为正则表达式的OR操作符,他表示匹配其中之一,相当于OR语句。
匹配几个字符之一
匹配任何单一字符,但是,如果你只想匹配特定的字符,可以通过指定一组用[和]括起来的字符来完成
输入: SELECT prod_name FROM products WHERE prod_name REGEXP ‘[123] Ton‘ ORDER BY prod_name;
分析: 这里,使用正则表达式[123] Ton。[123]定义一组字符,他的意思是匹配1或2或3,因此,1 ton 2 ton都可以匹配且返回(没有3 ton)
示例:
mysql> SELECT NAME FROM account WHERE NAME REGEXP '[at]est' ORDER BY NAME;
+------+
| NAME |
+------+
| aest |
| test |
+------+
匹配范围
集合可以用来定义要匹配的一个或多个字符,
输入: SELECT prod_name FROM products WHERE prod_name REGEXP ‘[1-5]‘ Ton ORDER BY pord_name;
分析: 这里使用正则表达式[1-5] Ton [1-5]定义了一个范围,这个表达式的意思是匹配1到5
示例:
mysql> SELECT NAME FROM account WHERE NAME REGEXP '[a-z]cc' ORDER BY NAME;
+------+
| NAME |
+------+
| ccc |
| ccc |
+------+
匹配特殊字符
如何匹配 .、|、-等特殊字符
SELECT vend_name FROM vendors WHERE vend_name REGEXP ' \\.' ORDER BY vend_name;
分析:
\\.匹配.,这种处理方式称之为转义
匹配多个实例
重复元字符
元字符 | 说明 |
---|---|
* | 0个或者多个匹配 |
+ | 1个或多个匹配(等于1,) |
? | 0个或1个匹配(等于0,1) |
n | 指定数目的匹配 |
n, | 不少于指定数目的匹配 |
n,m | 匹配数目的范围(m不超过255) |
输入:
SELECT prod_name FROM products WHERE prod_name REGEXP '\\([0-9] sticks?)' ORDER BY prod_name;
分析: sticks? 匹配stick和sticks,?表示0个或1个匹配
输入:
SELECT prod_name FROM products WHERE prod_name REGEXP '[[:digit:]]4' ORDER BY prod_name;
分析: [:digit:]匹配任意数字 ,4:确切的要求他前面的字符(任意数字),出现4次,匹配prod_name文本中包含4个任意连在一起的数字
定位符
目前为止的所有例子都是匹配一个串中任意位置的文本,为了匹配特定位置的文本,需要使用定位符
元字符 | 说明 |
---|---|
^ | 文本的开始 |
$ | 文本的结尾 |
[[:<:]] | 词的开始 |
[[:>:"]] | 词的结尾 |
示例
mysql> SELECT NAME FROM account WHERE NAME REGEXP '[[:<:]]t' ORDER BY NAME;
+------+
| NAME |
+------+
| t57L |
| test |
| tsdf |
? 创建计算字段
拼接字段
vendors表包含供应商和位置信息。假如要生成一个供应商报表,需要在供应商的名字中按照name(location)这样的格式列出供应商的位置
解决办法是把两个列拼接起来,在MySQL的SELECT语句中,可以使用Concat()函数拼接两个列
输入: SELECT Concat(vend_name,‘(‘,vend_country,‘)‘) FROM vendors ORDER BY vend_name;
分析: Concat()拼接串,既把多个串连接起来形成一个较长的串
示例:
mysql> SELECT CONCAT(RTRIM(NAME),'(',RTRIM(money),')') FROM account ORDER BY NAME;
+------------------------------------------+
| CONCAT(RTRIM(NAME),'(',RTRIM(money),')') |
+------------------------------------------+
| aaa(500) |
| NULL |
| bbb(1500) |
| ccc(1000) |
| ccc(1000) |
| ddd(13240) |
| ddd(13240) |
| t57L(1452) |
| test(66666) |
| tsdf(14520) |
+------------------------------------------+
Trim函数:去除空格
使用别名
从前面的输出中可以看到,SELECT语句拼接地址字段工作得很好,但此新计算列的名字是什么呢?实际上他没有名字,他只是一个值,如果仅在SQL查询工具查看一下结果,这样没有什么不好,但是,一个未命名的列不能用于客户机应用中,因为客户机没有办法引用他。
解决办法是,使用别名(alias),别名是一个字段或者的替换名
输入: SELECT CONCAT(RTRIM(NAME), ‘(‘,RTRIM(money),‘)‘) AS vend_title FROM account ORDER BY NAME;
分析: 他指示SQL创建一个包含指定计算的名为vend_title的计算字段
执行算数计算
输入:
SELECT prod_id,
quantity,
item_price,
quantity*item_price AS expanded_price
FROM orderitems
WHERE order_num = 20005;
以上是关于MySQL数据库必会技能,虚拟列的用法的主要内容,如果未能解决你的问题,请参考以下文章