DQL

数据查询语言,用来查询经过条件筛选的记录。

SELECT

SELECT语句用于读取和处理现有数据。

选择查询读取和处理hubble中的数据。它们比简单的SELECT子句更通用:它们可以使用集合操作对一个或多个选择子句进行分组,并且可以请求特定的排序或行限制。

可能会发生选择查询:

  • 括号之间作为子查询。
  • 作为将表格数据作为输入的其他语句的操作数,例如INSERTUPSERTCREATE TABLE AS等。

所需权限

要求用户拥有表的SELECT权限。

语法图

SelectStmt
SelectStmtFromTableSelectStmtFromDualTable
SelectConditionStmt
OrderByOptionalSelectStmtLimitSelectLockOpt
FromDual
FROMDUAL
WhereClauseOptional
WhereClause
SelectStmtGroup
GroupByClause
HavingClause
HAVINGExpression
OrderByOptional
OrderBy
SelectStmtLimit
LIMITLimitOptionLIMITLimitOptionOFFSETLimitOption
SelectLockOpt
FORUPDATEOFTableList
TableList
TableName,
WindowClauseOptional
WindowDefinition

参数介绍

参数简介
DISTINCT指定时DISTINCT,将消除重复行
ALL默认情况下或ALL指定时,返回所有选定的行
ORDER BY用于排序的函数,一般情况下默认升序
GROUP BY在一列或多列上对结果进行分组
HAVING它必须是使用聚合函数
windowDefinition窗口定义列表
limit用于分页的关键字,后面跟数字

条款

TABLE条款

TableStmt
TABLEtab_ref

子句从指定的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
  • LIMIT分页查询
select * from accounts 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,它支持以下通配符运算符:

  • %匹配 0个或多个字符。
  • _恰好匹配 1 个字符。
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: 合并两个查询

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: 检索两个查询的交集

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:从另一个查询中排除一个查询的结果

EXCEPT选择存在于第一个查询操作数中但不存在于第二个查询操作数中的值。

select cust_no from cust_info
except
select cust_no from cust_infobak;
  cust_no
------------
  14435550

SELECT FOR UPDATE

用于并发控制的行级锁定SELECT FOR UPDATE

SELECT FOR UPDATE语句用于通过控制对表的一行或多行的并发访问来对事务进行排序。

它通过锁定选择查询返回的行来工作,这样试图访问这些行的其他事务被迫等待锁定这些行的事务完成。这些其他事务根据尝试读取锁定行的值的时间有效地放入队列。

因为这种排队发生在读取操作期间,所以如果多个并发执行的事务尝试访问相同的数据,会阻止该选择的结果,hubble还可以防止可能发生的事务重试

使用SELECT FOR UPDATE导致竞争操作的吞吐量增加和尾部延迟减少。

所需权限

用户必须对用作操作数的表具有SELECTUPDATE权限

语法图

ForUpdateStmt
FORUPDATEoftablename

有关完整的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