在MySql下,怎么用SQL语句sql 遍历表一个树结构

无限级分类[预排序遍历树算法]-Php常用代码-Php教程-壹聚教程网无限级分类[预排序遍历树算法]无限级分类[预排序遍历树算法] 预排序遍历树算法
现在让我们看一看另外一种不使用递归计算,更加快速的方法,这就是预排序遍历树算法(modified preorder tree traversal algorithm)
这种方法大家可能接触的比较少,初次使用也不像上面的方法容易理解,但是由于这种方法不使用递归查询算法,有更高的查询效率。
我们首先将多级数据按照下面的方式画在纸上,在根节点Food的左侧写上 1 然后沿着这个树继续向下 在 Fruit 的左侧写上 2 然后继续前进,沿着整个树的边缘给每一个节点都标上左侧和右侧的数字。最后一个数字是标在Food 右侧的 18。 在下面的这张图中你可以看到整个标好了数字的多级结构。(没有看懂?用你的手指指着数字从1数到18就明白怎么回事了。还不明白,再数一遍,注意移动你的手指)。
这些数字标明了各个节点之间的关系,&Red&的号是3和6,它是 &Food& 1-18 的子孙节点。 同样,我们可以看到 所有左值大于2和右值小于11的节点 都是&Fruit& 2-11 的子孙节点
以下是代码:&&&&&&&&&&&&&&&&&&&&&&&&& 1 Food 18
&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&&&&&&&& +------------------------------+
&&&&&&&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&&&&&& 2 Fruit 11&&&&&&&&&&&&&&&&&&&& 12 Meat 17
&&&&&&&&&&& |&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |
&&& +-------------+&&&&&&&&&&&&&&&& +------------+
&&& |&&&&&&&&&&&& |&&&&&&&&&&&&&&&& |&&&&&&&&&&& |
3 Red 6&&&&& 7 Yellow 10&&&&&& 13 Beef 14&& 15 Pork 16
&&& |&&&&&&&&&&&& |
4 Cherry 5&&& 8 Banana 9
复制代码这样整个树状结构可以通过左右值来存储到数据库中。继续之前,我们看一看下面整理过的数据表。
以下是代码: +----------+------------+-----+-----+
|& parent& |&&& name&&& | lft | rgt |
+----------+------------+-----+-----+
|&&&&&&&&& |&&& Food&&& | 1&& | 18& |
|&& Food&& |&& Fruit&&& | 2&& | 11& |
|&& Fruit& |&&& Red&&&& | 3&& |& 6& |
|&& Red&&& |&&& Cherry& | 4&& |& 5& |
|&& Fruit& |&&& Yellow& | 7&& | 10& |
|&& Yellow |&&& Banana& | 8&& |& 9& |
|&& Food&& |&&& Meat&&& | 12& | 17& |
|&& Meat&& |&&& Beef&&& | 13& | 14& |
|&& Meat&& |&&& Pork&&& | 15& | 16& |
+----------+------------+-----+-----+
复制代码注意:由于&left&和&right&在 SQL中有特殊的意义,所以我们需要用&lft&和&rgt&来表示左右字段。 另外这种结构中不再需要&parent&字段来表示树状结构。也就是 说下面这样的表结构就足够了。
以下是代码: +------------+-----+-----+
|&&& name&&& | lft | rgt |
+------------+-----+-----+
|&&& Food&&& | 1&& | 18& |
|&&& Fruit&& | 2&& | 11& |
|&&& Red&&&& | 3&& |& 6& |
|&&& Cherry& | 4&& |& 5& |
|&&& Yellow& | 7&& | 10& |
|&&& Banana& | 8&& |& 9& |
|&&& Meat&&& | 12& | 17& |
|&&& Beef&&& | 13& | 14& |
|&&& Pork&&& | 15& | 16& |
+------------+-----+-----+
复制代码好了我们现在可以从数据库中获取数据了,例如我们需要得到&Fruit&项下的所有所有节点就可以这样写查询语句: SELECT * FROM tree WHERE lft BETWEEN 2 AND 11;
复制代码这个查询得到了以下的结果。
以下是代码: +------------+-----+-----+
|&&& name&&& | lft | rgt |
+------------+-----+-----+
|&&& Fruit&& | 2&& | 11& |
|&&& Red&&&& | 3&& |& 6& |
|&&& Cherry& | 4&& |& 5& |
|&&& Yellow& | 7&& | 10& |
|&&& Banana& | 8&& |& 9& |
+------------+-----+-----+
复制代码看到了吧,只要一个查询就可以得到所有这些节点。为了能够像上面的递归函数那样显示整个树状结构,我们还需要对这样的查询进行排序。用节点的左值进行排序: SELECT * FROM tree WHERE lft BETWEEN 2 AND 11 ORDER BY lft ASC;
复制代码剩下的问题如何显示层级的缩进了。
以下是代码:
function display_tree($root) {
&&& // 得到根节点的左右值
&&& $result = mysql_query(&
&&&&&&& SELECT lft, rgt
&&&&&&& FROM tree
&&&&&&& WHERE name = '& . $root . &'
&&&&&&& ;&
&&& $row = mysql_fetch_array($result);
&&& // 准备一个空的右值堆栈
&&& $right = array();
&&& // 获得根基点的所有子孙节点
&&& $result = mysql_query(&
&&&&&&& SELECT name, lft, rgt
&&&&&&& FROM tree
&&&&&&& WHERE lft BETWEEN '& . $row['lft'] . &' AND '& . $row['rgt'] .&'
&&&&&&& ORDER BY lft ASC
&&&&&&& ;&
&&& // 显示每一行
&&& while ($row = mysql_fetch_array($result)) {
&&&&&&& // only check stack if there is one
&&&&&&& if (count($right) & 0) {
&&&&&&&&&&& // 检查我们是否应该将节点移出堆栈
&&&&&&&&&&& while ($right[count($right) - 1] & $row['rgt']) {
&&&&&&&&&&&&&&& array_pop($right);
&&&&&&&&&&& }
&&&&&&& // 缩进显示节点的名称
&&&&&&& echo str_repeat('& ',count($right)) . $row['name'] . &n&;
&&&&&&& // 将这个节点加入到堆栈中
&&&&&&& $right[] = $row['rgt'];
复制代码如果你运行一下以上的函数就会得到和递归函数一样的结果。只是我们的这个新的函数可能会更快一些,因为只有2次数据库查询。
要获知一个节点的路径就更简单了,如果我们想知道Cherry 的路径就利用它的左右值4和5来做一个查询。 SELECT name FROM tree WHERE lft & 4 AND rgt &; 5 ORDER BY lft ASC;
复制代码这样就会得到以下的结果:
以下是代码: +------------+
|&&& name&&& |
+------------+
|&&& Food&&& |
|&&& Fruit&& |
|&&& Red&&&& |
+------------+
复制代码那么某个节点到底有多少子孙节点呢?很简单,子孙总数=(右值-左值-1)/2 descendants = (right & left - 1) / 2
复制代码不相信?自己算一算啦。
用这个简单的公式,我们可以很快的算出&Fruit 2-11&节点有4个子孙节点,而&Banana 8-9&节点没有子孙节点,也就是说它不是一个父节点了。
很神奇吧?虽然我已经多次用过这个方法,但是每次这样做的时候还是感到很神奇。
这的确是个很好的办法,但是有什么办法能够帮我们建立这样有左右值的数据表呢?这里再介绍一个函数给大家,这个函数可以将name和parent结构的表自动转换成带有左右值的数据表。
以下是代码:
function rebuild_tree($parent, $left) {
&&& // the right value of this node is the left value + 1
&&& $right = $left+1;
&&& // get all children of this node
&&& $result = mysql_query(&
&&&&&&& SELECT name
&&&&&&& FROM tree
&&&&&&& WHERE parent = '& . $parent . &'
&&&&&&& ;&
&&& while ($row = mysql_fetch_array($result)) {
&&&&&&& // recursive execution of this function for each
&&&&&&& // child of this node
&&&&&&& // $right is the current right value, which is
&&&&&&& // incremented by the rebuild_tree function
&&&&&&& $right = rebuild_tree($row['name'], $right);
&&& // we've got the left value, and now that we've processed
&&& // the children of this node we also know the right value
&&& mysql_query(&
&&&&&&& UPDATE tree
&&&&&&& SET
&&&&&&&&&&& lft = '& . $left . &',
&&&&&&&&&&& rgt= '& . $right . &'
&&&&&&& WHERE name = '& . $parent . &'
&&&&&&& ;&
&&& // return the right value of this node + 1
&&& return $right + 1;
复制代码当然这个函数是一个递归函数,我们需要从根节点开始运行这个函数来重建一个带有左右值的树 rebuild_tree('Food',1);
复制代码这个函数看上去有些复杂,但是它的作用和手工对表进行编号一样,就是将立体多层结构的转换成一个带有左右值的数据表。
那么对于这样的结构我们该如何增加,更新和删除一个节点呢?
增加一个节点一般有两种方法:
第一种,保留原有的name 和parent结构,用老方法向数据中添加数据,每增加一条数据以后使用rebuild_tree函数对整个结构重新进行一次编号。
第二种,效率更高的办法是改变所有位于新节点右侧的数值。举例来说:我们想增加一种新的水果&Strawberry&(草莓)它将成为&Red&节点的最后一个子节点。首先我们需要为它腾出一些空间。&Red&的右值应当从6改成8,&Yellow 7-10 &的左右值则应当改成 9-12。 依次类推我们可以得知,如果要给新的值腾出空间需要给所有左右值大于5的节点 (5 是&Red&最后一个子节点的右值) 加上2。 所以我们这样进行数据库操作: UPDATE tree SET rgt = rgt + 2 WHERE rgt & 5;
UPDATE tree SET lft = lft + 2 WHERE lft & 5;
复制代码这样就为新插入的值腾出了空间,现在可以在腾出的空间里建立一个新的数据节点了, 它的左右值分别是6和7 INSERT INTO tree SET lft=6, rgt=7, name='Strawberry';
复制代码再做一次查询看看吧!怎么样?很快吧。
好了,现在你可以用两种不同的方法设计你的多级数据库结构了,采用何种方式完全取决于你个人的判断,但是对于层次多数量大的结构我更喜欢第二种方法。如果查询量较小但是需要频繁添加和更新的数据,则第一种方法更为简便。
另外,如果数据库支持的话 你还可以将rebuild_tree()和 腾出空间的操作写成数据库端的触发器函数, 在插入和更新的时候自动执行, 这样可以得到更好的运行效率, 而且你添加新节点的SQL语句会变得更加简单。上一页: &&&&&下一页:相关内容MYSQL数据库,如何用一条实现效率高的多结果查询。 就是要一条综合语句执行的时间比分开执行效率高。_百度知道
MYSQL数据库,如何用一条实现效率高的多结果查询。 就是要一条综合语句执行的时间比分开执行效率高。
已知的两种方法都不过关,例如:1. SELECT * FROM `vendor` where product=1 union SELECT * FROM `vendor` where product=22. SELECT * FROM `vendor` where product in (1,2)上述语句的执行时间和分别执行两个product分别查询的时间总和一样,请问高手,有没有什么办法能够少于分别查询的时间。如果mysql实现不了,其他的什么数据库能最高效得做到这一点?
数据库大概有200万条数据,而所需要的一次能查1000条不同属性的语句。用union连接1000条语句,大概运行119秒左右,如果用in,时间也差不多。比1000条语句一个一个连发的总时间还慢一点。电脑算中等配置。现在需要的就是能够大幅度提高效率的方法,最少也不能慢过1000条语句分散发。如果mysql实现不了,其他方法也可以考虑。用netbean的java语言连接数据库。上述例子的vendor表建立为, id
提问者采纳
zwb12340 说的就是错的首先来说一下你的这两种写法1.这一个比较快,其实这是把两个SQL 拼接成1个SQL,但是在拼接的时候使用了UNION ,这个过程会排序去重复,这一点上会影响性能。可以把UNION 改成UNION ALL,UNION ALL不会排序去重,可能效率会更好一点2.这一个不会太快,因为使用in的话,默认是不使用索引的,那么这一个过程会全表扫描,那么就很慢了(我这里说的索引是默认的B+树索引,是自动屏蔽的,如果是BITMAP索引的话,是会使用的),对于你这个问题的解决,我给以下几个意见1.首先把UNION改成UNION ALL试一试,看效率怎么样2.检查是否在product上有没有索引,尽量建一个索引3.如果以上两个改进之后,还没效果的话,可以在这个表上,基于product建立分区表,使用分区表的话,那么效果会比较明显
确实比 union 要快一些, 但是时间上只是减少了零头,还没有达到本质上的改变。
朋友,楼下的这个 退伍的工科平民 所说的绝对是错误的。我不误导你。1. 他说的第二种方法比第一种要快,还说 product=1 or product=2 这种是绝对使用索引的,这简直是太可笑了。数据库除非使用的索引是BITMAP索引,不然使用OR和IN都是非常消耗性能的,在数据库SQL调优中,从来都是要对这种语句进行调优的。这一点你可以百度查一下的,OR和IN在使用过程中,会使用INDEX,但是会concat方式来做,效率非常慢,而且值得一说的是:在数据库里面,IN和OR是等效的,如果你会查执行计划的话,就会发现,使用OR和使用IN的执行计划是完全一致的2. 你下面说的这个排序是通过ID来的,这个是肯定的,在设计中,不可能用名称来做排序。3.你说UNION ALL比UNION快一点,但只是快了一点零头,那是因为这里快的仅仅是在数据选择出来之后,是否有再加工的这个过程,UNION ALL去除了再加工的过程,所以快一点,但不是很快,因为你本身在查询中的消耗是最大的。还是那个意见,对product建索引,如果实在不行就建成分区表(partition table)
其他类似问题
按默认排序
其他4条回答
楼上说反了吧?第一种效率高点。1. SELECT * FROM `vendor` where product=1 union SELECT * FROM `vendor` where product=22. SELECT * FROM `vendor` where product in (1,2)上述语句的执行时间和分别执行两个product分别查询的时间总和一样。不对,这两个执行查询时间不一样。当然,索引情况下,差别不大。非索引情况下,union的时间会比in的方式时间少。 一般不采用in。执行查询的时间,不仅跟数据量有关,也跟数据结构有关。一般推荐使用union。in是需要一个一个对比的判断,union不需要这个判断,union直接把结果集放在一起。所以快一点。
1.第一个写法太烂了,在一个表中不需要这样;2,第二个写法效率已经很高了;3;将product建立索引,将提高查询效率很多4.不是查询数据需要尽量不要select *5.检测查询效率,数据库要有足够的记录数,少了没有效果,怎么写,查询时间几乎都是一样
建索引!没有索引,任何数据库都会做全表扫描,就是遍历200万条数据,否则数据库系统不能肯定是不是有符合要求的数据漏掉。2的20次方是100万,如果是折半查找,21次查找操作就可以找到你要的单个数据。而写法1和写法2的效率相差就是2倍不到,所以建好索引效率查上千倍。不要纠缠在哪种写法上!写法2绝对比写法1要快。in是不是不用索引我不知道,不同数据库可能不一样。我就不明白为什么不用 product=1 or product=2 呢?这个肯定会用索引的,如果有索引的话。不管 in 还是 product=1 or product=2 都是在一次全表扫描中就可以直接实现了的。而用union、union all,即便利用到第一次全表扫描的执行结果,还是:全表扫描-》排序-》再查找,就是说如果没有索引,1次全表扫描肯定是逃不掉的。
您好,我才学了数据库没多久。请问一下,之前的货物有很多维的属性,每种属性间有优先值。我最后把这些属性转化成了全排序,并用数字来代表每一种具体货物,这些数字只表示名称。我的意思说,查找的时候不可能根据货物名称来决定排序,只能根据他们的id有一个卖方的偏好续。具体实验的时候200万条数据是随机生成的数字。
&有很多维的属性,每种属性间有优先值……把这些属性转化成了全排序……&? 你做的不是数据仓库吧?不好意思,看不太懂你的意思,能举个例子么?如果你的意思是复合主键,比如三个属性确定一个产品: product_attr1、 product_attr2、product_attr3 ,那么也一样呀:SELECT * FROM `vendor` where( product_attr1=11 and product_attr2=12 and product_attr3=13 ) or ( product_attr1=21 and product_attr2=22 and product_attr3=23 ) 同样的,记得先对
product_attr1、 product_attr2、product_attr3
建复合索引。CREATE INDEX ind_vendor_product
ON vendor (product_attr1, product_attr2 , product_attr3);
我认为你应该为其列创建一个索引(如果该列的值是唯一的那么创建聚集索引否则非聚集索引(unclustered))这样速度更高些同事也不能用*号 最好采取所需要查询的信息列名
mysql数据库的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁MySQL源代码:从SQL语句到MySQL内部对象
<div class="gray post" title="T10:40:54+-11-2 &|& 10:40分类:,&&|&&标签:、、&&|&&
自从有了微薄后,上一篇博客已经是6月份写的了... 从写的文章之后也已经过了很久,继续上路。
优化器是关系数据库的一个重要而有特色的部分,优化器的理论和实践也多半也都很复杂,本系列文章希望通过解析MySQL优化器,来用好MySQL,扬其长,避其短。顺便也一窥关系数据库优化器的实现思路。文章将重点介绍重要的数据结构和数据结构之间的关系,而不是侧重于代码(".")。
0 写在前面
本文解决了什么问题:希望通过这些文章能够帮你更加顺畅的理解MySQL优化器的行为;在你阅读MySQL源代码之前了解更多的背后思路。
本文不解决什么问题:教你如何读懂源代码;
这个系列很长,大概按这样的思路进行下去: 基本的数据结构、语法解析、JOIN的主要算法、JOIN顺序和单表访问。数据结构(以及他们的关系)和算法流程总是相互穿插介绍。
建议阅读:参考文献中的文章和书籍,都建议在阅读本文之前阅读。
1 SQL语句解析基础
1.1 语法解析基础/Flex与Bison
MySQL语法解析封装在函数MYSQLparser中完成。跟其他的语法解析器一样,它包含两个模块:词法分析(Lexical scanner)和语法规则(Grammar rule module)。词法分析将整个SQL语句打碎成一个个单词(Token),而语法规则模块则根据MySQL定义的语法规则生成对应的数据结构,并存储在对象THD->LEX结构当中。最后优化器,根据这里的数据,生成执行计划,再调用存储引擎接口执行。
词法分析和语法规则模块有两个较成熟的开源工具Flex和Bison分别用来解决这两个问题。MySQL处于性能和灵活考虑,选择了自己完成词法解析部分,语法规则部分使用Bison。词法解析和Bison沟通的核心函数是由词法解析器提供的函数接口yylex(),在Bison中,必要的时候调用yylex()获得词法解析的数据,完成自己的语法解析。Bison的入口时yyparse(),在MySQL中是,MYSQLParse。
如果对词法分析和语法规则模块感到陌生,建议阅读参考文献[4][5][6]先注1,否则很难理解整个架构,或者至少会有很强的断层感。而且,根据Bison的Action追踪MySQL数据的存储结构是很有效的。
1.2 MySQL语法解析Sample与示意图
简单的解析过程可以使用下面的示意图说明:
具体的解析一个SQL语句的WHERE部分:
2 SQL语句到MySQL的内部对象
Bison在做语法解析后,会将解析结果(一颗解析树/AST)存储在THD::LEX中。这里将通过考察存储WHERE的数据结构来查看语法解析的结果。
2.1 著名的Item对象
在了解MySQL的解析树之前,我们需要先来认识一个重要的数据结构Item。这是一个基础对象,在优化器部分代码,满地都是。在MySQL Internal Manual中也单独介绍:。
Item是一个基础类,在他的基础上派生了很多子孙。这些子类基本描述所有SQL语句中的对象,他们包括:
一个文本字符串/数值对象
一个数据表的某一列(例如,select c1,c2 from dual...中的c1,c2)
一个比较动作,例如c1>10
一个WHERE子句的所有信息
可以看到,Item基本上代码SQL语句中的所有对象。在语法解析树中,这些Item以一颗树的形式存在。示意图如下:
2.2 Bison语法中的WHERE
从SELECT子句开始,我们看到对应的where_clause就是我们关注的WHERE:
我们来看看Bison中的几个重要的Action参考注1:
where_clause:
/* empty */ {}
| WHERE expr
THD->lex->current_select->where = $2
| expr and expr
$$ = new (YYTHD->mem_root) Item_cond_and($1, $3)
|ident comp_op NUM
/*这一行并不是源码的一部分,便于理解简化如此*/
$$ = new Item_func_ge(a, b); /*这一行并不是源码的一部分,便于理解简化如此*/
根据这里的Bison语法,就可以生产上面的WHERE语法树了。如果你是和我一样刚刚了解Flex/Bison/AST,一定也会决定很巧妙!
2.3 WHERE的数据结构和他们之间的关系
绘制了下面的关系图用来描述WHERE和WHERE解析树的各个分支:
例如WHERE条件WHERE c1="orczhou" and c2 > 10,WHERE本身(lex->select->where)就是一个Item_cond_and对象,这个对象中有一个Item List,将List中每一个Item的值做AND运输,也就是这个WHERE的取值了。
这里,WHERE的List中有两个Item对象,分别代表了c1="orczhou"和c2 > 10。具体的,这两个对象的类型分别是Item_func_eq和Item_func_gt。
再单独看看Item_func_gt(代表c2 > 10)对象,这个对象由Item_func派生而来(当然追根朔源都是Item的孩儿们),这个对象有成员:Item **args。args则存放了比较操作需要使用的Item。
对于c2 > 10,这个不等式中有两个Item,分别代表字段c2和整数10,存储这两个对象的类型分别是:Item_field和Item_int。
2.4 通过GDB打印WHERE对象
WHERE条件是:WHERE id =
reg_date > ' 09';
打印WHERE中的List
(gdb) p ((Item_cond *)select_lex->where)->list
&base_list& = {
&Sql_alloc& = {&No data fields&},
members of base_list:
first = 0x7f5bbc005860,
last = 0x7f5bbc005870,
elements = 2
因为WHERE有两个判断,所以这里list中有两个元素。
打印list中的第一个判断(id = )
(gdb) p *(Item_func *)((Item_cond *)select_lex->where)->list->first->info
&Item_result_field& = {
&Item& = {
next = 0x7f,
members of Item_func:
args = 0x7f,
tmp_arg = {0x7f, 0x7f},
arg_count = 2,
这里等于操作有两个操作元素(arg_count=2),并以数组的形式存储在args中
打印上面等式的第一个对象(也就是id)
打印第一个Item的类型
p ((Item_func *)((Item_cond *)select_lex->where)->list->first->info)->args[0]->type()
$74 = Item::FIELD_ITEM
将第一个Item转换成正确的类型再打印
p *(Item_field *)((Item_func *)((Item_cond *)select_lex->where)->list->first->info)->args[0]
&Item_ident& = {
&Item& = {
name = 0x7f "id",
members of Item_ident:
orig_field_name = 0x7f "id",
field_name = 0x7f "id",
members of Item_field:
field = 0x0,
result_field = 0x0,
可以看到这里的id对象的类型是Item::FIELD_ITEM,也就是Item_field类型。
3 关于Item对象
继续从存储WHERE的Item_cond_and对象开始:
看到Item_cond_and的继承关系:Item_cond->Item_bool_func->......->Item_result_filed->Item
Item一个很重要的成员函数就是type,所以在gdb的时候如果不清楚Item的类型,可以调用该方法确定:
(gdb) p ((*(Item_func *)thd->lex->current_select->where)->tmp_arg[0])->type()
$42 = Item::FIELD_ITEM
这篇文章就到这吧,希望能够继续下去。
[5](由浅到深,较为完整的介绍)
[6] (完整的介绍)
[7] (简洁明了的介绍)
[8] MySQL Source Code
[注1] 我以前从未了解编译原理、语法解析相关的知识,这次恶补了一下,如果你也一样,那么建议阅读参考文件中的[4][5][6],我天资平平,大约花费了一周/二十个小时左右
喜欢本文,那就收藏到:您所在的位置: &
用SQL游标遍历循环数据的方法
用SQL游标遍历循环数据的方法
SQL游标的优点是可以方便从一个结果集中进行循环遍历数据在进行操作,下面就将为您介绍用SQL游标对数据进行遍历循环操作的方法,供您参考。
如果对数据进行遍历循环操作,通过的游标就可以实现,下面就为您详细介绍该方法,供您参考,希望对您学习SQL数据库能够有所帮助。
SQL游标的优点是可以方便从一个结果集中进行循环遍历数据在进行操作。
1、游标允许应用程序对查询语句select 返回的行结果集中每一行进行相同或不同的操作,而不是一次对整个结果集进行同一种操作;
2、它还提供对基于游标位置而对表中数据进行删除或更新的能力;
3、游标把作为面向集合的数据库管理系统和面向行的程序设计两者联系起来,使两个数据处理方式能够进行沟通。
&&&&&&& 然尔游标也有缺点&&复杂和低效,是游标的最大缺点,也是致使很多时候在使用存储过程中没有想到游标的主要原因。
下面是在实际工作中的一个游标实例的应用,通过游标把A表的数据的一列值复制到B表的列当中,其中二个表都有相同的UID字段,条件是对相同UID的数据进行复制.
declare @level varchar(100)
declare @uid varchar(100)
declare cur cursor--定义一个游标
for select egg_code.user_id,egg_prize_level
from egg_code inner join egg_prize on egg_prize.user_id=egg_code.user_id--为所获得的数据集指定游标
open cur--打开游标
fetch next from cur into @uid,@level--把提取操作的列数据放到局部变量中
while(@@fetch_status=0)--返回被 FETCH 语句执行的最后游标的状态,而不是任何当前被连接打开的游标的状态。
--print '等级:'+@level+'--------------用户ID:'+@uid
update egg_code set prize_level=@level&& where user_id=@uid--执行操作
--提前下一位信息
fetch next from cur into @uid,@level
close cur--关闭游标
deallocate cur--删除游标
使用游标的顺序: 声名游标、打开游标、读取数据、关闭游标、删除游标。
由于 @@FETCH_STATUS 对于在一个连接上的所有游标是全局性的,要小心使用 @@FETCH_STATUS 。在执行一条 FETCH 语句后,必须在对另一游标执行另一 FETCH 语句前测试 @@FETCH_STATUS 。在任何提取操作出现在此连接上前,@@FETCH_STATUS 的值没有定义。
例如,用户从一个游标执行一条 FETCH 语句,然后调用一个存储过程,此存储过程打开并处理另一个游标的结果。当控制从被调用的存储过程返回后,@@FETCH_STATUS 反映的是在存储过程中执行的最后的 FETCH 语句的结果,而不是在存储过程被调用之前的 FETCH 语句的结果。
使用上面的游标是泉州SEO在一次网站砸金蛋活动中,二个表的数据在使用的过程中有部份后期改到程序致使有部份数据无法同步,导致前台查询的时候所用到的表无法查到相关的数据,没用游标进行操作之前试过只用简单的SQL语句去实现这样的同步功能,但是始终无法实现,所以只能使用游标来实现。
【编辑推荐】
【责任编辑: TEL:(010)】
关于&&&&的更多文章
MySQL 5.6.10已经发布,Oracle将其称之为MySQL 5.6正式版。51CTO
数据库产品
数据库综合
数据库新闻
维基百科将切换到另外一款开源数据库MariaDB
作为甲骨文公司的基石,Oracle数据库一直占据着数据库
MySQL众多的管理工具,是广大DBA管理好数据库的利器。
本专题将带领大家走入MongoDB的世界,MongoDB是一个基
本书虽然是《网管员必读―网络应用》的改版,但它绝不是简单的修改,而是完完全全的重写,内容更实用、更专业。全书共9章,13个
51CTO旗下网站

我要回帖

更多关于 mysql 遍历树 的文章

 

随机推荐