查询数据
使用 SELECT 语句查询数据表中的一列或多列数据、使用集合函数显示查询结果、连接查询、子查询以及使用正则表达式进行查询等
基本查询语句
SELECT语句的基本格式是∶
SELECT
{* | <字段列表> }
[
FROM<表1>,<表2>..
[WHERE <表达式>
[GROUP BY <group by definition>]
[HAVING <expresslon>[{<operator><expression>}...]]
[ORDER BY <order by definition>]
[LIMIT [<offset>,] <row count>]
]
SELECT [字段1,字段2,...,字段n]
FROM [表或视图]
WHERE [查询条件];
- { * | <字段列表>}包含星号通配符选择字段列表,表示查询的字段,其中字段列至少包
含一个字段名称,如果要查询多个字段,多个字段之间用逗号隔开,最后一个字段后 不要加逗号。 - FROM <表1>,<表2>…,表1和表2表示查询数据的来源,可以是单个或者多个。
- WHERE 子句是可选项,如果选择该项,将限定查询行必须满足的查询条件。
- GROUP BY<字段>,该子句告诉 MySQL如何显示查询出来的数据,并按照指定的字
段分组。 - [ ORDER BY <字段> ],该子句告诉MySQL按什么样的顺序显示查询出来的数据,可
以进行的排序有∶升序(ASC)、降序(DESC)。 - [ LIMIT[ < offset >,]< row count>],该子句告诉 MySQL 每次显示查询出来的数据条数。
CREATE TABLE fruits
(
f_id char(10) NOT NULL,
s_id int NOT NuLL,
f_name char(255) NOT NULL,
f_price decimal(8,2) NOT NULL,
PRIMARY KEY(f_id)
);
INSERT into fruits(f_id,s_id,f_name,f_price)
VALUES('al',101,'apple',5.2),
('b1',101,'blackberry',10.2),
('bs1',102,'orange',11.2),
('bs2',105,'melon',8.2),
('tl',102,'banana',10.3),
('t2',102,'grape',5.3),
('o2',103,'coconut',9.2),
('c0',101,'cherry',3.2),
('a2',103,'apricot',2.2),
('l2',104,'lemon',6.4),
('b2',104,'berry',7.6),
('m1',106,'mango',15.7),
('m2',105,'xbabay',2.6),
('t4',107,'xbababa',3.6),
('m3',105,'xxtt',11.6),
('b5',107,'xxx',3.6);
单表查询
单表查询中的各种基本的查询方式,主要有∶查询所有字段、查询指定字段、查询指定记录、查询空值、多条件的查询、对查询结果进行排序等。
查询所有字段
在SELECT语句中使用星号(*)通配符查询所有字段
SELECT *FROM 表名;
查询指定字段
SELECT 字段名1, 字段名2, ...,字段名n FROM 表名;
查询指定记录
SELECT 字段名1, 字段名2, ... , 字段名n
FROM 表名
WHERE 查询条件
带IN关键词的查询
【例】查询s_id为101和102的记录,SQL语句如下∶
SELECT s_id, f_name, f_price FROM fruits
WHERE s_id IN (101,102)
ORDER BY f_name;
相反的,可以使用关键字 NOT来检索不在条件范围内的记录 【例】查询所有s_id不等于101也不等于102的记录,SQL语句如下∶
SELECT s_id,f_name,f_price FROM fruits
WHERE s_id NOT IN (101,102)
ORDER BY f_name;
带 BETWEEN AND的范围查询
BETWEEN AND用来查询某个范围内的值,该操作符需要两个参数,即范围的开始值和 结束值,如果字段值满足指定的范围查询条件,则这些记录被返回。
带LIKE 的字符匹配查询
在前面的检索操作中,讲述了如何查询多个字段的记录,如何进行比较查询或者是查询一 个条件范围内的记录,如果要查找所有的包含字符"ge"的水果名称,该如何查找呢?简单的 比较操作在这里已经行不通了,在这里,需要使用通配符进行匹配查找,通过创建查找模式对 表中的数据进行比较。执行这个任务的关键字是LIKE。 通配符是一种在 SQL 的WHERE 条件子句中拥有特殊意思的字符,SQL 语句中支持多种 通配符,可以和 LIKE一起使用的通配符有"%" 和 “_”。
1.百分号通配符’%'匹配任意长度的字符,甚至包括零字符
【例】查找所有以 'b’字母开头的水果,SQL语句如下∶
SELECT f_id,f_name
FROM fruits
WHERE f_name LIKE 'b%';
【例】查询以‘b’开头,并以‘y’结尾的水果的名称,SQL语句如下
SELECT f_name FROM fruits WHERE f_name LIKE 'b%y';
2.下划线通配符_',一次只能匹配任意一个字符
【例】在fruits表中,查询以字母’y’结尾,且’y’前面只有4个字母的记录,SQL 语句如下
SELECT f_id,f_name FROM fruits where f_name LIKE '____y';
查询空值
在 SELECT语句中使用IS NULL子句,可以查询某字段内容为空的记录。与IS NULL 相反的是NOT IS NULL,该关键字查找字段不为空的记录。
带AND的多条件查询
使用 AND连接两个甚至多个查询条件,多个条件表达式之间用 AND 分开。
带OR的多条件查询
OR也可以连接两个甚至多个查询条件,多个条件表达式之间用OR分开。
查询结果不重复
在 SELECT 语句中,可以使用 DISTINCT关键字指示 MySQL消除重复的记录值。语法格式为∶
SELECT DISTINCT 字段名 FROM 表名
【例】查询 fruits表中s_id字段的值,返回s_id字段值且不得重复,SQL语句如下∶
SELECT DISTINCT s_id FROM frults;
对查询结果排序
通过在SELECT语句中使用 ORDER BY 子句,对查询的结果进行排序。 【例】查询 fruits 表的f_name 字段值,并对其进行排序,SQL语句如下∶
SELECT f_name FROM fruits ORDER BY f_name;
【例】查询fruits表中的f_name和f_price字段,先按f_name排序,再按f_price排序, SQL语句如下
SELECT f_name,f_price FROM fruits ORDER BY f_name,f_price;
通过关键字DESC实现降序排列
SELECT f_name,f_price FROM fruits ORDER BY f_price DESC;
分组查询
分组查询是对数据按照某个或多个字段进行分组,MySQL 中使用 GROUP BY 关键字对 数据进行分组,基本语法形式为∶
[GROUP BY 字段] [HAVING <条件表达式>]
字段值为进行分组时所依据的列名称;"HAVING<条件表达式>"指定满足表达式限定条件的结果将被显示。 GROUPBY关键字通常和集合函数一起使用,例如∶MAX()、MIN()、COUNT()、SUM()、AVG()。例如,要返回每个水果供应商提供的水果种类,这时就要在分组过程中用到 COUNT()函数,把数据分为多个逻辑组,并对每个组进行集合计算。
【例】根据s_id对 fruits表中的数据进行分组,SQL 语句如下∶
SELECT s_id,COUNT(*) AS Total FROM fruits GROUP BY s_id;
【例】根据s_id 对 fruits 表中的数据进行分组,将每个供应商的水果名称显示出来, SQL 语句如下∶
SELECT s_id,GROUP_CONCAT(f_name) AS Names FROM fruits GROUP BY s_id;
GROUP BY可以和HAVING一起限定显示记录所需满足的条件,只有满足条件的分组才会被显示。 【例】根据s id 对 fruits表中的数据进行分组,并显示水果种类大于1的分组信息, SQL语句如下∶
SELECT s_id,GROUP_CONCAT(f_name) AS Names
FROM fruits
GROUP BY s_id HAVING COUNT(f_name) > 1;
使用WITH ROLLUP 关键字之后,在所有查询出的分组记录之后增加一条记录,该记录计算查询出的所有记录的总和,即统计记录数量。 【例】根据s_id对 fruits 表中的数据进行分组,并显示记录数量,SQL 语句如下∶
SELECT s_id,COUNT(*) AS Total
FROM fruits GROUP BY s_id WITH ROLLUP;
ORDER BY用来对查询的记录排序,如果和 GROUP BY一起使用可以完成对分组的排序。 使用 LIMIT限制查询结果的数量
使用 LIMIT限制查询结果的数量
SELECT 返回所有匹配的行,有可能是表中所有的行,如仅仅需要返回第一行或者前几行,使用LIMIT关键字,基本语法格式如下∶
LIMIT [位置偏移量,] 行数
- 第一个参数"位置偏移量"指示 MySQL 从哪一行开始显示,是一个可选参数,如果不指定"位置偏移量",将会从表中的第一条记录开始(第一条记录的位置偏移量是0第二条记录的位置偏移量是1….依次类推)
- 第二个参数"行数"指示返回的记录条数。
【例】显示 fruits表查询结果的前4行,SQL语句如下∶
SELECT * FROM fruits LIMIT 4;
【例】在fruits表中,使用LIMIT子句,返回从第5个记录开始的,行数长度为3的 记录,SQL语句如下∶
SELECT *FROM fruits LIMIT 4,3;
使用聚合函数查询
有时候并不需要返回实际表中的数据,而只是对数据进行总结。MySQL 提供一些查询功能,可以对获取的数据进行分析和报告。这些函数的功能有∶计算数据表中记录行数的总数、计算某个字段列下数据的总和,以及计算表中某个字段下的最大值、最小值或者平均值。本节将介绍这些函数以及如何使用它们。这些聚合函数的名称和作用如表7.2 所示。
COUNT()函数
COUNTO)函数统计数据表中包含的记录行的总数,或者根据查询结果返回列中包含的数 据行数。其使用方法有两种∶
- COUNT(*)计算表中总的行数,不管某列有数值或者为空值。
- COUNT(字段名)计算指定列下总的行数,计算时将忽略空值的行。
【例】查询 fruits表中总的行数,SQL语句如下∶
SELECT COUNT(*) AS f_id FROM fruits;
SUM()函数
SUM()是一个求总和的函数,返回指定列值的总和。 【例】在fruits表中查询103号订单一共购买的水果总金额,SQL语句如下∶
SELECT SUM(f_price) AS price_total FROM fruits WHERE s_id = 103;
SUM()可以与 GROUP BY一起使用,来计算每个分组的总和。
SELECT s_id, SUM(f_price) AS price_total FROM fruits GROUP BY s_id;
AVG()函数
AVG()函数通过计算返回的行数和每一行数据的和,求得指定列数据的平均值。 【例】在fruits表中查询103号订单一共购买的水果总金额,SQL语句如下∶
SELECT AVG(f_price) AS price_total FROM fruits WHERE s_id = 103;
SELECT s_id, AVG(f_price) AS price_total FROM fruits GROUP BY s_id;
MAX()函数
MAX()返回指定列中的最大值。用法同上
MIN()函数
MIN()返回查询列中的最小值。用法同上
连接查询
连接是关系数据库模型的主要特点。连接查询是关系数据库中最主要的查询,主要包括内 连接、外连接等。 通过连接运算符可以实现多个表查询。在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中。当查询数据时,通过连接操作查询出存放在多个表中的不同实体的信息。当两个或多个表中存在相同意义的字段时,便可以通过这些字段对不同的表进行连接查询。本节将介绍多表之间的内连接查询、外连接查询以及复合条件连接查询。
内连接查询
内连接(INNER JOIN)使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行,组合成新记录,也就是说,在内连接查询中,只有满足条件的记录才能出现在结果关系中. 创建表 suppliers
CREATE table suppliers
(
s_id int NOT NULL AUTO_INCREMENT,
s_name char(50) NOT NULL,
s_city char(50) NULL,
s_zip char(50) NULL,
s_call char(50) NOT NULL,
PRIMARY KEY (s_id)
);
插入数据
INSERT INTO suppliers(s_id, s_name, s_city, s_zip, s_call)
VALUES(101,'FastFruit Inc.','Tianjin','300000','48075'),
(102,'LT Supplies','Chongqing','400000','44333'),
(103,'ACME','Shanghai','200000','90046'),
(104,'FNK Inc.','Zhongshan','528437','11111'),
(105,'Good set','Taiyuang','030000','22222'),
(106,'Just Eat Ours','Beijing','010','45678'),
(107,'DK Inc.','Zhengzhou','450000','33332');
【例】在 fruits 表和 suppliers 表之间使用内连接查询。 接下来从 fruits 表中查询f_name、f_price字段,从 suppliers 表中查询s_id、s_name,SQL语句如下∶
select suppliers.s_id, s_name, f_name, f_price
from suppliers, fruits
where suppliers.s_id = fruits.s_id;
【例】在 fruits 表和 suppliers表之间,使用INNER JOIN 语法进行内连接查询,SQL 语句如下∶
select suppliers.s_id, s_name, f_name, f_price
from suppliers INNER JOIN fruits
on suppliers.s_id = fruits.s_id;
结果相同
外连接查询
外连接查询将查询多个表中相关联的行,内连接时,返回查询结果集合中的仅是符合 查询条件和连接条件的行。但有时候需要包含没有关联的行中数据,即返回查询结果集合 中的不仅包含符合连接条件的行,而且还包括左表(左外连接或左连接)、右表(右外连 接或右连接)或两个连接表(全外连接)中的所有数据行。外连接分为左外连接或左连接 和右外连接或右连接∶
- LEFTJOIN(左连接)∶返回包括左表中的所有记录和右表中连接字段相等的记录。
- RIGHTJOIN(右连接)∶返回包括右表中的所有记录和左表中连接字段相等的记录。
1.LEFT JOIN(左连接)
左连接的结果包括LEFT OUTER子句中指定的左表的所有行,而不仅仅是连接列所匹配 的行。如果左表的某行在右表中没有匹配行,则在相关联的结果行中,右表的所有选择列表列 均为空值。
CREATE TABLE customers
(
c_id int NOT NULL AUTO_INCREMENT,
c_name char(50) NOT NULL,
c_address char(50) NULL,
c_city char(50) NULL,
c_zip char(10) NULL,
c_contact char(50) NULL,
c_email char(255) NULL,
PRIMARY KEY (c_id)
);
INSERT INTO customers(c_id,c_name,c_address,c_city,c_zip, c_contact,c_email)
VALUES(10001,'RedHook','200 Street','Tianjin','300000','LiMing','LMing@163.com'),
(10002,'stars','333 Fromage Lane','Dalian','116000','Zhangbo','Jerryehotmail.com'),
(10003,'Netbhood','1 Sunny Place','Qingdao','266000','LuoCong',NULL),
(10004,'JorTo','829 Riverside Drive','Haikou','570000','YangShan','samehotmai1.com');
创建表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)
);
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);
【例】在customers 表和 orders 表中,查询所有客户,包括没有订单的客户,SQL 语句如下∶
SELECT customers.c_id,orders.o_num
FROM customers LEFT OUTER JOIN orders
ON customers.c_id = orders.c_id;
2.RIGHT JOIN(右连接)
右连接是左连接的反向连接,将返回右表的所有行。如果右表的某行在左表中没有匹配行, 左表将返回空值。
【例】在 customers 表和 orders 表中,查询所有订单,包括没有客户的订单,SOL 语 句如下∶
SELECT customers.c_id,orders.o_num
FROM customers RIGHT OUTER JOIN orders
ON customers.c_id = orders.c_id;
复合条件连接查询
复合条件连接查询是在连接查询的过程中,通过添加过滤条件,限制查询的结果,使查询 的结果更加准确
【例】在 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;
子查询
带 ANY、SOME关键字的子查询
ANY 和 SOME关键字是同义词,表示满足其中任一条件,它们允许创建一个表达式对子查询的返回值列表进行比较,只要满足内层子查询中的任何一个比较条件,就返回一个结果作为外层查询的条件。 下面定义两个表tbl1和 tbl2∶
CREATE table tbl1 (num1 INT NOT NULL);
CREATE table tbl2 (num2 INT NOT NULL);
分别向两个表中插入数据∶
INSERT INTO tbl1 values (1),(5) ,(13),(27);
INSERT INTO tbl2 values (6),(14),(11),(20);
【例】返回 tbl2表的所有 num2列,然后将tbl1中的 num1 的值与之进行比较,只要大于num2的任何1个值,即为符合查询条件的结果。
SELECT num1 FROM tbl1 wHERE num1 > ANY(SELECT num2 FROM tbl2);
返回的是tbl2 表的所有 num2列结果(6,14,11,20),然后将tbl1中的 numl列的值与之进行比较,只要大于 num2列的任意一个数即为符合条件的结果。
带ALL关键字的子查询
ALL关键字与ANY和 SOME不同,使用ALL时需要同时满足所有内层查询的条件。例如,修改前面的例子,用 ALL关键字替换 ANY。 ALL 关键字接在一个比较操作符的后面,表示与子查询返回的所有值比较为 TRUE,则返回TRUE。
【例】返回tbl1表中比 tbl2表 num2 列所有值都大的值,SQL语句如下∶
SELECT num1 FROM tbl1 WHERE num1 >ALL(SELECT num2 FROM tbl2);
返回的是 tbl2 的所有num2 列结果(6,14,11,20),然后将 tbll 中的 num1列的值与之进行比较,大于所有 num2列值的 num1值只有27,因此返回结果为27。
带EXISTS关键字的子查询
EXISTS关键字后面的参数是一个任意的子查询,系统对子查询进行运算以判断它是否返回行,如果至少返回一行,那么 EXISTS 的结果为 true,此时外层查询语句将进行查询;如果子查询没有返回任何行,那么EXISTS返回的结果是 false,此时外层语句将不进行查询。
【例】查询 suppliers 表中是否存在s_id=107的供应商,如果存在,则查询 fruits 表中的记录,SQL语句如下∶
SELECT * FROM fruits
WHERE EXISTS
(SELECT s_name FROM suppliers WHERE s_id = 107);
EXISTS关键字可以和条件表达式一起使用。 【例】查询 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);
NOT EXISTS 与 EXISTS使用方法相同,返回的结果相反。
带 IN 关键字的子查询
IN 关键字进行子查询时,内层查询语句仅仅返回一个数据列,这个数据列里的值将提供给外层查询语句进行比较操作。
创建数据表 orderitems
CREATE TABLE orderitems
(
o_num int NOT NULL,
o_item int NOT NULL,
f_id char(10) NOT NULL,
quantity int NOT NULL,
item_price decimal(8,2) NOT NULL,
PRIMARY KEY (o_num,o_item)
);
插入演示数据。SQL 语句如下∶
INSERT INTO orderitems(o_num,o_item,f_id,quantity,item_price) VALUES
(30001,1,'a1',10,5.2),
(30001,2,'b2',3,7.6),
(30001,3,'bs1',5,11.2),
(30001,4,'bs2',15,9.2),
(30002,1,'b3',2,20.0),
(30003,1,'c0',100,10),
(30004,1,'o2',50,2.50),
(30005,1,'c0',5,10),
(30005,2,'b1',10,8.99),
(30005,3,'a2',10,2.2),
(30005,4,'ml',5,14.99);
【例】在 orderitems表中查询询f_id为c0的订单号,并根据订单号查询具有订单号的客户c_id,SQL语句如下∶
SELECT c_id FROM orders WHERE o_num IN
(SELECT o_num FROM orderitems WHERE f_id = 'c0');
子查询
SELECT o_num FROM orderitems WHERE f_id = 'c0';
外部查询
SELECT c_id FROM orders WHERE o_num IN (30003,30005);
NOT IN 关键字,其作用与IN 正好相反。
带比较运算符的子查询
在前面介绍的带 ANY、ALL 关键字的子查询时使用了">“比较运算符,子查询时还可以使用其他的比较运算符,如”<“、”<=“、”=“、”>=“和”!="等。
合并查询结果
利用UNION关键字,可以给出多条 SELECT语句,并将它们的结果组合成单个结果集。 合并时,两个表对应的列数和数据类型必须相同。各个 SELECT 语句之间使用 UNION 或 UNION ALL关键字分隔。UNION不使用关键字ALL,执行的时候删除重复的记录,所有返 回的行都是唯一的;使用关键字 ALL的作用是不删除重复行也不对结果进行自动排序。基本 语法格式如下∶
SELECT column, ... FROM table1
UNION [ALL]
SELECT column, ...FROM table2
【例】查询所有价格小于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);
为表和字段取别名
为表取别名
当表名字很长或者执行一些特殊查询时,为了方便操作或者需要多次使用相同的表时, 可以为表指定别名,用这个别名替代表原来的名称。为表取别名的基本语法格式为∶
表名 [AS] 表别名
- "表名"为数据库中存储的数据表的名称
- "表别名"为查询时指定的表的新名称,AS关键字为可选参数。
【例】为 orders 表取别名o,查询30001订单的下单日期,SQL语句如下∶
SELECT *FROM orders AS o
WHERE o.o_num = 30001;
为字段取别名
MySQL可以指定列别名,替换字段或表达式。为字段取别名的基本语法格式为∶
列名 [AS] 列别名
- "列名"为表中字段定义的名称
- "列别名"为字段新的名称,AS关键字为可选参数。
【例】查询 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;
使用正则表达式查询
查询以特定字符或字符串开头的记录
字符’A’匹配以特定字符或者字符串开头的文本。 【例】在fruits表中,查询f_name字段以字母’b’开头的记录,SQL语句如下∶
SELECT * FROM fruits WHERE f_name REGEXP '^b';
查询以特定字符或字符串结尾的记录
字符’$'匹配以特定字符或者字符串结尾的文本。 【例】在fruits表中,查询f_name字段以字母’y’结尾的记录,SQL语句如下;
SELECT * FROM fruits WHERE f_name REGEXP 'y$';
用符号"."来替代字符串中的任意一个字符
字符’.'匹配任意一个字符。 【例】在fruits表中,查询f name 字段值包含字母’a’与’g’且两个字母之间只有一个字母的记录,SQL 语句如下,
SELECT* FROM fruits WHERE f_name REGEXP 'a.g';
使用"*“和”+"来匹配多个字符
星号’ * ‘匹配前面的字符任意多次,包括0次。加号’+'匹配前面的字符至少一次。 【例】在fruits表中,查询f_name 字段值以字母’b’开头,且’b’后面出现字母’a’的记录,SQL语句如下∶
SELECT * FROM fruits WHERE f_name REGEXP '^ba*';
匹配指定字符串
正则表达式可以匹配指定字符串,只要这个字符串在查询文本中即可,如要匹配多个字符串,多个字符串之间使用分隔符|'隔开。 【例】在fruits表中,查询f_name字段值包含字符串"on"的记录,SQL语句如下∶
SELECT * FROM fruits WHERE f_name REGEXP 'on';
匹配指定字符中的任意一个
方括号"[]"指定一个字符集合,只匹配其中任何一个字符,即为所查找的文本。 【例】在 fruits表中,查找f_name字段中包含字母’o’或者’t’的记录,SQL语句 如下∶
SELECT * FROM fruits WHERE f_name REGEXP '[ot]';
查询结可以看到,所有返回的记录的f_name 字段的值中都包含有字母o或者t,或者两个都有。
匹配指定字符以外的字符
"[ ^字符集合 ]"匹配不在指定集合中的任何字符。 【例】在fruits 表中,查询fid字段包含字母a~ e和数字1 ~2以外的字符的记录,SQL语句如下∶
SELECT * FROM fruits WHERE f_id REGEXP '[^a-e1-2]';
|