数据查询语言,用来查询经过条件筛选的记录。
SELECT
语句用于读取和处理现有数据。
选择查询读取和处理Hubble中的数据。它们比简单的SELECT
子句更通用:它们可以使用集合操作对一个或多个选择子句进行分组,并且可以请求特定的排序或行限制。
可能会发生选择查询:
INSERT
、UPSERT
、 CREATE TABLE AS
等。要求用户拥有表的SELECT
权限。
- SelectStmt
- SelectConditionStmt
- FromDual
- WhereClauseOptional
- SelectStmtGroup
- HavingClause
- OrderByOptional
- SelectStmtLimit
- SelectLockOpt
- TableList
- WindowClauseOptional
参数 | 简介 |
---|---|
DISTINCT | 指定时DISTINCT ,将消除重复行 |
ALL | 默认情况下或ALL 指定时,返回所有选定的行 |
ORDER BY | 用于排序的函数,一般情况下默认升序 |
GROUP BY | 在一列或多列上对结果进行分组 |
HAVING | 它必须是使用聚合函数 |
windowDefinition | 窗口定义列表 |
limit | 用于分页的关键字,后面跟数字 |
TABLE条款
- TableStmt
子句从指定的TABLE
表中读取表格数据。
TABLE x
相当于SELECT * FROM x
。
SELECT条款
有关详细信息,请参阅下文select
示例语句。
create table accounts (
id int primary key,
name varchar(20) not null,
balance DECIMAL(10,2),
flag string,
is_disabled string,
is_status string,
index(name)
);
insert into accounts values (11,'mike',1000,'false','1','1');
insert into accounts values (12,'jack',2000,'true','0','1');
insert into accounts values (13,'allen',5555.3,'false','1','0');
insert into accounts values (14,'oslwn',6321,'true','0','0');
insert into accounts values (15,'ding',6984,'true','1','1');
insert into accounts values (16,'mark',9840.5,'true','0','0');
insert into accounts values (17,'jamms',6530.2,'false','0','0');
insert into accounts values (18,'haden',1520,'true','1','1');
show create table accounts;
table_name | create_statement
-------------+-------------------------------------------------------------------------
accounts | CREATE TABLE public.accounts (
| id INT8 NOT NULL,
| name VARCHAR(20) NULL,
| balance DECIMAL(10,2) NULL,
| flag STRING NULL,
| is_disabled STRING NULL,
| is_status STRING NULL,
| CONSTRAINT "primary" PRIMARY KEY (id ASC),
| FAMILY "primary" (id, name, balance, flag, is_disabled, is_status)
select * from accounts;
id | name | balance | flag | is_disabled | is_status
-----+-------+---------+-------+-------------+------------
11 | mike | 1000.00 | false | 1 | 1
12 | jack | 2000.00 | true | 0 | 1
13 | allen | 5555.30 | false | 1 | 0
14 | oslwn | 6321.00 | true | 0 | 0
15 | ding | 6984.00 | true | 1 | 1
16 | mark | 9840.50 | true | 0 | 0
17 | jamms | 6530.20 | false | 0 | 0
18 | haden | 1520.00 | true | 1 | 1
select name from accounts;
name
---------
mike
jack
allen
oslwn
ding
mark
jamms
haden
select * from accounts where name='mark';
id | name | balance | flag | is_disabled | is_status
-----+------+---------+------+-------------+------------
16 | mark | 9840.50 | true | 0 | 0
select * from accounts where name='mark' or is_disabled='0';
id | name | balance | flag | is_disabled | is_status
-----+-------+---------+-------+-------------+------------
12 | jack | 2000.00 | true | 0 | 1
14 | oslwn | 6321.00 | true | 0 | 0
16 | mark | 9840.50 | true | 0 | 0
17 | jamms | 6530.20 | false | 0 | 0
select name from accounts where balance in ('1000', '6530.20');
id | name | balance | flag | is_disabled | is_status
-----+-------+---------+-------+-------------+------------
11 | mike | 1000.00 | false | 1 | 1
17 | jamms | 6530.20 | false | 0 | 0
DISTINCT
查询select distinct name from accounts;
name
---------
mike
jack
allen
oslwn
ding
mark
jamms
haden
ALL
查询(默认情况下也是返回所有)select all * from accounts;
id | name | balance | flag | is_disabled | is_status
-----+-------+---------+-------+-------------+------------
11 | mike | 1000.00 | false | 1 | 1
12 | jack | 2000.00 | true | 0 | 1
13 | allen | 5555.30 | false | 1 | 0
14 | oslwn | 6321.00 | true | 0 | 0
15 | ding | 6984.00 | true | 1 | 1
16 | mark | 9840.50 | true | 0 | 0
17 | jamms | 6530.20 | false | 0 | 0
18 | haden | 1520.00 | true | 1 | 1
GROUP BY
聚合函数查询select name, sum(balance) from accounts group by name;
name | sum
--------+----------
mike | 1000.00
jack | 2000.00
allen | 5555.30
oslwn | 6321.00
ding | 6984.00
mark | 9840.50
jamms | 6530.20
haden | 1520.00
HAVING
分组过滤查询(通常用于分组后数据的过滤)select is_status, sum(balance) from accounts group by is_status having is_status='0';
is_status | sum
------------+-----------
0 | 28247.00
select * from accounts offset 0 limit 3;
id | name | balance | flag | is_disabled | is_status
-----+-------+---------+-------+-------------+------------
11 | mike | 1000.00 | false | 1 | 1
12 | jack | 2000.00 | true | 0 | 1
13 | allen | 5555.30 | false | 1 | 0
AS
select id as cust_id,name as cust_name from accounts limit 3;
cust_id | cust_name
----------+------------
11 | mike
12 | jack
13 | allen
使用搜索列中的部分字符串匹配LIKE
,它支持以下通配符运算符:
select * from accounts where name like 'm%';
id | name | balance | flag | is_disabled | is_status
-----+------+---------+-------+-------------+------------
11 | mike | 1000.00 | false | 1 | 1
16 | mark | 9840.50 | true | 0 | 0
(2 rows)
AS
select name as cust_name,sum(balance) as aml from accounts group by cust_name;
cust_name | aml
------------+----------
mike | 1000.00
jack | 2000.00
allen | 5555.30
oslwn | 6321.00
ding | 6984.00
mark | 9840.50
jamms | 6530.20
haden | 1520.00
SQL允许您比较多个选择子句的结果。您可以将每个集合运算符视为表示布尔运算符:
UNION=OR
INTERSECT=AND
EXCEPT=NOT
默认情况下,这些比较中的每一个仅显示每个值的一个副本(类似于SELECT DISTINCT
)。
建表及其数据准备:
create table cust_infobak(
cust_no string primary key,
cust_name varchar(30) not null,
cust_card_no varchar(18),
cust_phoneno decimal(15),
cust_address varchar(30),
cust_type varchar(10),
index(cust_card_no)
);
insert into cust_infobak values('14435551','张贺','431256197306265320',15534343555,'山西临汾','质押');
insert into cust_infobak values('14435552','刘明','371452199303034312',18967756743,'陕西延安','信用');
insert into cust_infobak values('14435553','李华','52112119860621421X',15833355455,'湖北武汉','抵押');
insert into cust_infobak values('14435554','郑青','213456199102275341',13054546567,'江西南昌','质押');
create table cust_info(
cust_no string primary key,
cust_name varchar(30) not null,
cust_card_no varchar(18),
cust_phoneno decimal(15),
cust_address varchar(30),
cust_type varchar(10),
index(cust_card_no)
);
insert into cust_info values('14435550','王吉','12022519960321531X',15122511874,'天津武清','抵押');
insert into cust_info values('14435551','张贺','431256197306265320',15534343555,'山西临汾','质押');
insert into cust_info values('14435552','刘明','371452199303034312',18967756743,'陕西延安','信用');
UNION
将两个查询的结果合并为一个结果。
select * from cust_info
union
select * from cust_infobak;
cust_no | cust_name | cust_card_no | cust_phoneno | cust_address | cust_type
-----------+-----------+--------------------+--------------+--------------+------------
14435551 | 张贺 | 431256197306265320 | 15534343555 | 山西临汾 | 质押
14435552 | 刘明 | 371452199303034312 | 18967756743 | 陕西延安 | 信用
14435550 | 王吉 | 12022519960321531X | 15122511874 | 天津武清 | 抵押
14435553 | 李华 | 52112119860621421X | 15833355455 | 湖北武汉 | 抵押
14435554 | 郑青 | 213456199102275341 | 13054546567 | 江西南昌 | 质押
要显示重复的行,您可以使用UNION ALL
select * from cust_info
union all
select * from cust_infobak;
cust_no | cust_name | cust_card_no | cust_phoneno | cust_address | cust_type
-----------+-----------+--------------------+--------------+--------------+------------
14435550 | 王吉 | 12022519960321531X | 15122511874 | 天津武清 | 抵押
14435551 | 张贺 | 431256197306265320 | 15534343555 | 山西临汾 | 质押
14435552 | 刘明 | 371452199303034312 | 18967756743 | 陕西延安 | 信用
14435551 | 张贺 | 431256197306265320 | 15534343555 | 山西临汾 | 质押
14435552 | 刘明 | 371452199303034312 | 18967756743 | 陕西延安 | 信用
14435553 | 李华 | 52112119860621421X | 15833355455 | 湖北武汉 | 抵押
14435554 | 郑青 | 213456199102275341 | 13054546567 | 江西南昌 | 质押
INTERSECT
仅选择两个查询操作数中都存在的值。
select * from cust_info
intersect
select * from cust_infobak;
cust_no | cust_name | cust_card_no | cust_phoneno | cust_address | cust_type
-----------+-----------+--------------------+--------------+--------------+------------
14435551 | 张贺 | 431256197306265320 | 15534343555 | 山西临汾 | 质押
14435552 | 刘明 | 371452199303034312 | 18967756743 | 陕西延安 | 信用
EXCEPT
选择存在于第一个查询操作数中但不存在于第二个查询操作数中的值。
select cust_no from cust_info
except
select cust_no from cust_infobak;
cust_no
------------
14435550
用于并发控制的行级锁定SELECT FOR UPDATE
该SELECT FOR UPDATE
语句用于通过控制对表的一行或多行的并发访问来对事务进行排序。
它通过锁定选择查询返回的行来工作,这样试图访问这些行的其他事务被迫等待锁定这些行的事务完成。这些其他事务根据尝试读取锁定行的值的时间有效地放入队列。
因为这种排队发生在读取操作期间,所以如果多个并发执行的事务尝试访问相同的数据,会阻止该选择的结果,Hubble还可以防止可能发生的事务重试
使用SELECT FOR UPDATE
导致竞争操作的吞吐量增加和尾部延迟减少。
用户必须对用作操作数的表具有SELECT
和UPDATE
权限
- ForUpdateStmt
有关完整的SELECT
语句语法文档,请参阅选择查询
参数 | 简介 |
---|---|
FOR UPDATE | 锁定SELECT 语句返回的行,以便尝试访问这些行的其他事务必须等待事务完成 |
此示例用于SELECT FOR UPDATE
锁定事务中的一行,强制其他想要更新同一行的事务等待第一个事务完成。想要更新同一行的其他事务根据它们第一次尝试读取该行的值的时间被有效地放入队列中。
首先,连接到正在运行的集群(称为终端 1),并创建一个表插入一些行
create table test (a int primary key, b int);
insert into test (a, b) values (1, 3), (20,0), (2, 6);
接下来,启动一个事务并锁定要操作的行:
begin;
select * from test where a = 1 for update;
在客户端中按两次 Enter以发送到目前为止的输入以进行评估。这将导致以下输出:
a | b
+---+----+
1 | 3
现在打开另一个终端并从第二个客户端连接到数据库(称为终端 2),开始一个事务并尝试锁定同一行以获取我们在终端 1中打开的事务已经访问的更新
begin;
select * from test where a = 1 for update;
按两次 Enter以发送到目前为止的输入以进行评估。因为终端1经锁定了这一行,所以SELECT FOR UPDATE
来自终端2的语句将显示为“等待”。
回到终端 1,更新行并提交事务:
update test set b = b + 7 where a = 1;
commit;
现在终端 1中的交易已经提交,终端 2中的交易将被“解锁”,生成以下输出
a | b
+---+----+
1 | 10
终端 2中的事务现在可以接收输入,因此再次更新有问题的行
update test set b = b + 3 where a = 1;
commit;
终端2中的交易留下的值
a | b
+---+----+
1 | 13