mysql源码 select分析_MySQL解析器源码分析--对select语句中子查询处理逻辑的分析(二)...

(接上文)

下面以一个简单的SQL作为例子来讲解。

例如: Select * from tt where tt.id in (select id from tt1) union select * from tt1;

SQL在经过解析后的类间关系如下图:

3d06c4ce62ad58659780b4ba36a0ca28.gif

MySQL解析器相关处理逻辑

MySQL解析器在分析到SQL存在union或者select子句,from子句,where子句中的subselect时,都会调用mysql_new_select函数维护上述所讲的数据结构,区别是union在调用mysql_new_select时传第二个参数move_down=0;subselect在调用mysql_new_select时传第二个参数move_down=1。

mysql_new_select函数具体解释如下:

Code:

bool mysql_new_select(LEX *lex, bool move_down)

{

SELECT_LEX *select_lex;

THD *thd= lex->thd;

DBUG_ENTER("mysql_new_select");

//为子查询新建一个SELECT_LEX即st_select_lex,这个st_select_lex可能对应遇到的select子句,from子句,

//where子句中的subselect或者union关系中的select子句; if (!(select_lex= new (thd->mem_root) SELECT_LEX()))

DBUG_RETURN(1);

select_lex->select_number= ++thd->select_number;

select_lex->parent_lex= lex; /* Used in init_query. */

select_lex->init_query();

select_lex->init_select();

lex->nest_level++;

if (lex->nest_level > (int) MAX_SELECT_NESTING)

{

my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT,MYF(0),MAX_SELECT_NESTING);

DBUG_RETURN(1);

}

select_lex->nest_level= lex->nest_level;

if (thd->stmt_arena->is_stmt_prepare())

select_lex->uncacheable|= UNCACHEABLE_PREPARE;

//如果move_down=1,即是为select子句,from子句,where子句中的subselect创建相应数据结构时

if (move_down)

{

SELECT_LEX_UNIT *unit;

lex->subqueries= TRUE;

//新建一个SELECT_LEX_UNIT即st_select_lex_unit

if (!(unit= new (thd->mem_root) SELECT_LEX_UNIT()))

DBUG_RETURN(1);

unit->init_query();

unit->init_select();

unit->thd= thd;

//将此SELECT_LEX_UNIT挂在上一级select语句对应SELECT_LEX的下,即此SELECT_LEX的slave指针指向此SELECT_LEX_UNIT

unit->include_down(lex->current_select);

unit->link_next= 0;

unit->link_prev= 0;

unit->return_to= lex->current_select;

//同时将这个subselect对应的SELECT_LEX挂在刚建的这个SELECT_LEX_UNIT下,这里MySQL对于select子句,from子句,where子句

//中可能出现的subselect,都会先新建一个SELECT_LEX_UNIT挂在上一级select语句对应的SELECT_LEX下,

//同时建一个subselect对应的SELECT_LEX挂在SELECT_LEX_UNIT下。

//这样如果这个subselect的右边又出现了一个subselect和它进行union操作,可以将右边的这个subselect对应的

//SELECT_LEX放在上一级的SELECT_LEX_UNIT表达这个union关系。 select_lex->include_down(unit);

select_lex->context.outer_context= &select_lex->outer_select()->context;

}

//如果move_down=0;意味着对应处理的是union关系

else

{

if (lex->current_select->order_list.first && !lex->current_select->braces)

{

my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");

DBUG_RETURN(1);

}

//将要处理这个新的参与union中的select子句对应的SELECT_LEX加入union链表中,union操作符左边这个select子句对应的

//SELECT_LEX已经在这个链表中 select_lex->include_neighbour(lex->current_select);

SELECT_LEX_UNIT *unit= select_lex->master_unit();

if (!unit->fake_select_lex && unit->add_fake_select_lex(lex->thd))

DBUG_RETURN(1);

select_lex->context.outer_context=

unit->first_select()->context.outer_context;

}

select_lex->master_unit()->global_parameters= select_lex;

select_lex->include_global((st_select_lex_node**)&lex->all_selects_list);

lex->current_select= select_lex;

select_lex->context.resolve_in_select_list= TRUE;

DBUG_RETURN(0);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL数据库SELECT是用于从一个或多个表检索数据的关键字。SELECT查询表达式的基本语法如下: ```sql SELECT column1, column2, ... FROM table_name WHERE condition; ``` 其,column1、column2等为要检索的列名,可以使用通配符*代替所有列。table_name为要检索的表名,condition为可选的筛选条件。 在SELECT查询表达式,可以使用多种表达式来生成结果集。以下是一些常用的SELECT表达式: 1. 聚合函数:用于对结果集进行统计计算,例如SUM、COUNT、AVG、MAX、MIN等。 ```sql SELECT SUM(column_name) FROM table_name; ``` 2. 别名:用于为查询结果的列或表指定别名,以便更好的阅读和理解查询结果。 ```sql SELECT column_name AS alias_name FROM table_name; ``` 3. 子查询:嵌套在SELECT语句的查询语句,用于从子查询获取数据,然后在主查询使用它。 ```sql SELECT column_name FROM table_name WHERE column_name IN (SELECT column_name FROM table_name WHERE condition); ``` 4. 连接:用于将两个或多个表的数据合并到一个结果集,包括INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL OUTER JOIN等。 ```sql SELECT column_name FROM table1 INNER JOIN table2 ON table1.column_name = table2.column_name; ``` 5. 字符串函数:用于处理字符串数据,例如CONCAT、LENGTH、SUBSTRING、UPPER、LOWER等。 ```sql SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM table_name; ``` 6. 条件表达式:用于根据条件过滤结果集,例如IF、CASE等。 ```sql SELECT column_name, IF(column_name > 10, '大于10', '小于等于10') AS result FROM table_name; ``` 以上是MySQL数据库常用的SELECT查询表达式,可以根据实际需求选择使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值