﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-adrian-文章分类-mysql</title><link>http://www.blogjava.net/adrian/category/36212.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 26 Nov 2008 21:02:49 GMT</lastBuildDate><pubDate>Wed, 26 Nov 2008 21:02:49 GMT</pubDate><ttl>60</ttl><item><title>mysql使用内存表&amp;舍弃游标</title><link>http://www.blogjava.net/adrian/articles/242516.html</link><dc:creator>adrian615</dc:creator><author>adrian615</author><pubDate>Tue, 25 Nov 2008 05:02:00 GMT</pubDate><guid>http://www.blogjava.net/adrian/articles/242516.html</guid><wfw:comment>http://www.blogjava.net/adrian/comments/242516.html</wfw:comment><comments>http://www.blogjava.net/adrian/articles/242516.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/adrian/comments/commentRss/242516.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/adrian/services/trackbacks/242516.html</trackback:ping><description><![CDATA[mysql中的内存表使用哈希散列索引把数据保存在内存中，因此具有极快的速度，适合缓存临时数据，但是使用上受到一些限制：<br />
1、heap对所有用户的连接是可见的，这使得它非常适合做缓存。<br />
2、不允许使用TEXT和BLOB数据类型，只允许使用=和&lt;=&gt;操作符来检索数据，不允许&lt;、&gt;、&lt;=和&gt;=，不支持auto_increment；只允许对非空数据列进行索引（not null）。<br />
注：操作符 &#8220;&lt;=&gt;&#8221; 说明：NULL-safe equal.这个操作符和&#8220;=&#8221;操作符执行相同的比较操作，不过在两个操作码均为NULL时，其所得值为1而不为NULL，而当一个操作码为NULL时，其所得值为0而不为NULL。<br />
3、一旦服务器重启，所有heap表数据丢失，但是heap表结构仍然存在，因为heap表结构是存放在实际数据库路径下的，不会自动删除。重启之后，heap将被清空，这时候对heap的查询结果都是空的。<br />
4、如果heap是复制的某数据表，则复制之后所有主键、索引、自增等格式将不复存在，需要重新添加主键和索引，如果需要的话。<br />
5、对于重启造成的数据丢失，有以下的解决办法：<br />
　a、在任何查询之前，执行一次简单的查询，判断heap表是否存在数据，如果不存在，则把数据重新写入，或者DROP表重新复制某张表。这需要多做一次查询。不过可以写成include文件，在需要用该heap表的页面随时调用，比较方便。<br />
　b、对于需要该heap表的页面，在该页面第一次且仅在第一次查询该表时，对数据集结果进行判断，如果结果为空，则需要重新写入数据。这样可以节省一次查询。<br />
　c、更好的办法是在mysql每次重新启动时自动写入数据到heap，但是需要配置服务器，过程比较复杂，通用性受到限制。<br />
6、一些预期可能用到的sql语句<br />
//如果表存在，则删除<br />
DROP TABLE IF EXISTS `abc`;<br />
//复制整张表xyz为heap表abc（包含所有数据）<br />
CREATE TABLE `abc` type=heap select * from `xyz`;<br />
//添加主键id<br />
ALTER TABLE `abc` ADD PRIMARY KEY (`id`);<br />
//添加索引username<br />
ALTER TABLE `abc` ADD INDEX `abc` (`username`);<br />
7.建表实例<br />
CREATE TABLE `DB` (<br />
`id` int(11) default NULL,<br />
`songname` varchar(255) NOT NULL default '',<br />
`singer` varchar(255) NOT NULL default '',<br />
KEY `songname` (`songname`,`singer`)<br />
) TYPE=HEAP SELECT ...<br />
建表时TABLE TYPE 选项也有这个表结构就是建立了内存表。如果MYSQL重启，那么内存表的数据将会消失。但访问速度会很快哦！<br />
8、有时需要在存储过程中使用内存表，做一些回插的操作，这时会遇到类型匹配问题，例如把一个字符串回插给数字字段，这时就要使用上面的方式声明表结构，把该数字字段声明为字符串varchar类型。<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
在过程或函数中使用游标时会占用大量的系统资源不说，执行速度也会很慢，其实对于mysql来说有另外一种实现游标相同功能方法：<br />
1、这个方法只能用于使用了auto_increment主键的表。<br />
2、声明一个变量var，专门用来保存取到记录的ID（我们假设这个表的主键字段是ID）。<br />
3、使用循环取一条ID&gt;var的记录，进行相关操作，同时把所取到记录的ID赋给变量。<br />
一个完整的例子是这样的：<br />
declare v_count int default 0;<br />
declare tmp_id int default 0;#id default 0<br />
select count(1) into v_count from table1 where ...;<br />
while v_count&gt;0 do<br />
set v_count = v_count-1;<br />
select id into tmp_id from table1 where...and id&gt;tmp_id order by id limit 1;#get top 1 record which's id&gt;tmp_id<br />
...#do as you like here<br />
end while;<br />
在数据量很大的情况下，它的效率应该会比游标快，但是数据同步方面没有保证。
 <img src ="http://www.blogjava.net/adrian/aggbug/242516.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/adrian/" target="_blank">adrian615</a> 2008-11-25 13:02 <a href="http://www.blogjava.net/adrian/articles/242516.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>存储过程中游标的使用(mysql)</title><link>http://www.blogjava.net/adrian/articles/242515.html</link><dc:creator>adrian615</dc:creator><author>adrian615</author><pubDate>Tue, 25 Nov 2008 05:01:00 GMT</pubDate><guid>http://www.blogjava.net/adrian/articles/242515.html</guid><wfw:comment>http://www.blogjava.net/adrian/comments/242515.html</wfw:comment><comments>http://www.blogjava.net/adrian/articles/242515.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/adrian/comments/commentRss/242515.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/adrian/services/trackbacks/242515.html</trackback:ping><description><![CDATA[新公司使用mysql，最近给财务部门做了一些统计报表，要用到存储过程里的指针，总结一下：）<br />
1.指针的声明前面不可以有set，声明格式如下：<br />
DECLARE c_name CURSOR FOR select...<br />
2.声明一个handler用来标记指针状态：<br />
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_status = 1;<br />
3.打开指针，使用REPEAT获取记录：<br />
OPEN c_name;<br />
FETCH FROM c_sn INTO tmp_sn, tmp_batch_id;<br />
REPEAT<br />
...<br />
FETCH FROM c_sn INTO tmp_sn, tmp_batch_id;<br />
UNTIL v_status=1 END REPEAT;<br />
CLOSE c_name;<br />
OK，就这么简单。<br />
一个完整的存储过程体如下：<br />
BEGIN<br />
DECLARE v_status INT DEFAULT 0;<br />
DECLARE c_name CURSOR FOR select...;<br />
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_status = 1;&lt;--注意此处的顺序<br />
OPEN c_name;<br />
FETCH FROM c_sn INTO tmp_sn, tmp_batch_id;<br />
REPEAT<br />
...<br />
FETCH FROM c_sn INTO tmp_sn, tmp_batch_id;<br />
UNTIL v_status=1 END REPEAT;<br />
CLOSE c_name;<br />
END
 <img src ="http://www.blogjava.net/adrian/aggbug/242515.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/adrian/" target="_blank">adrian615</a> 2008-11-25 13:01 <a href="http://www.blogjava.net/adrian/articles/242515.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>