吴伟贤のBlog

Feed Rss

存档: ‘网页@Web’ 分类

phpexcelreader 导入mysql

06.27.2010, phpexcelreader 导入mysql已关闭评论, php, by .

下载

sourceforge.net/projects/phpexcelreader/

一:修改reader.php内

require_once ‘Spreadsheet/Excel/Reader/OLERead.php’;

require_once ‘Excel/oleread.inc’;

 

 

二:数据库utf-8编码

 

三:php执行程序

$data = new Spreadsheet_Excel_Reader();
            $data->setOutputEncoding(‘UTF-8’);//设置编码
            $data->read(‘test.xls’);//excel,csv文件位置
            error_reporting(E_ALL ^ E_NOTICE);

            for ($i = 2; $i <= $data->sheets[0][‘numRows’]; $i++) {//插入数据库开始
                    $sql="INSERT INTO {$table}kehu (userid,sortid,danwei,xingming,zuncheng,tel,mobile,fax,email,website,qq,address,postcode,sex,beizhu,addtime) values(‘$_COOKIE[WECMS_user_id]’,’$sortid’,
                                    ‘".$data->sheets[0][‘cells’][$i][1]."’,
                                    ‘".$data->sheets[0][‘cells’][$i][2]."’,
                                    ‘".$data->sheets[0][‘cells’][$i][3]."’,
                                    ‘".$data->sheets[0][‘cells’][$i][4]."’,
                                    ‘".$data->sheets[0][‘cells’][$i][5]."’,
                                    ‘".$data->sheets[0][‘cells’][$i][6]."’,
                                    ‘".$data->sheets[0][‘cells’][$i][7]."’,
                                    ‘".$data->sheets[0][‘cells’][$i][8]."’,
                                    ‘".$data->sheets[0][‘cells’][$i][9]."’,
                                    ‘".$data->sheets[0][‘cells’][$i][10]."’,
                                    ‘".$data->sheets[0][‘cells’][$i][11]."’,
                                    ‘".$data->sheets[0][‘cells’][$i][12]."’,
                                    ‘".$data->sheets[0][‘cells’][$i][13]."’,
                                    ‘$nowtime’)";
                    $res=$db->query($sql);

//插入数据库结束
            }

 

成功

了解更多

js 图片超出范围就自动缩小的代码

05.30.2010, js 图片超出范围就自动缩小的代码已关闭评论, js, by .

<img   src= "… "   onload= "autoresize(this) ">
function   autoresize(obj){
    if(obj.width> 800)
        obj.width=800;
}

了解更多

PHP 正则判断中文 UTF-8 & GBK

05.29.2010, PHP 正则判断中文 UTF-8 & GBK已关闭评论, php, by .

UTF-8匹配:

在javascript中,要判断字符串是中文是很简单的。比如:
var str = "php编程";
if (/^[\u4e00-\u9fa5]+$/.test(str)) {
alert("该字符串全部是中文");
}
else{
alert("该字符串不全部是中文");
}

php中,是用\x表示十六进制数据的。于是,变换成如下的代码:
$str = "php编程";
if (preg_match("/^[\x4e00-\x9fa5]+$/",$str)) {
print("该字符串全部是中文");
} else {
print("该字符串不全部是中文");
}
貌似不报错了,判断的结果也正确,不过把$str换成“编程”两字,结果却还是显示“该字符串不全部是中文”,看来这样的判断还是不够准确。

重要:查阅了<精通正则表达式>发现,对于[\x4e00-\x9fa5]这块东西,自己做一个强化的解释

php的正则中, [\x4e00-\x9fa5],其实就是  字符和字符组的概念, \x{hex},表达一个16进制数, 需要注意的是hex 可以是1-2位的,也可以是4位的,但是如果是4位的必须加上大括号,

同时,如果是大于x{FF}的hex,必须和u 修饰符连用,不然会非法出错

网上只能找到匹配全角字符的正则:   ^[\x80-\xff]*^/   ,这里可以不加大括号
[\u4e00-\u9fa5]可以匹配中文,但是PHP又不支持   
不过,既然\x表示的十六进制数据,为什么和js里边提供的范围\x4e00-\x9fa5不一样呢?于是我就换成了下边的代码,发现真的准确了:
$str = "php编程";
if (preg_match("/^[\x{4e00}-\x{9fa5}]+$/u",$str)) {
print("该字符串全部是中文");
} else {
print("该字符串不全部是中文");
}

知道了php中utf-8编码下用正则表达式匹配汉字的最终正确表达式——/^[\x{4e00}-\x{9fa5}]+$/u,
参考以上文章写了如下一段测试代码(复制以下代码保存成.php文件)

<?php
$action = trim($_GET[‘action’]);
if($action == "sub")
{
    $str = $_POST[‘dir’];   
    //if(!preg_match("/^[".chr(0xa1)."-".chr(0xff)."A-Za-z0-9_]+$/",$str)) //GB2312汉字字母数字下划线正则表达式
    if(!preg_match("/^[\x{4e00}-\x{9fa5}A-Za-z0-9_]+$/u",$str))   //UTF-8汉字字母数字下划线正则表达式
    {  
        echo "<font color=red>您输入的[".$str."]含有违法字符</font>";  
    }
    else
    {
        echo "<font color=green>您输入的[".$str."]完全合法,通过!</font>";  
    }
}
?>
<form method="POST" action="?action=sub">
输入字符(数字,字母,汉字,下划线):
    <input type="text" name="dir" value="">
    <input type="submit" value="提交">
</form>

GBK:

preg_match("/^[".chr(0xa1)."-".chr(0xff)."A-Za-z0-9_]+$/",$str); //GB2312汉字字母数字下划线正则表达式

了解更多

手工移动mysql的数据库目录

05.17.2010, 手工移动mysql的数据库目录已关闭评论, mysql, by .

原因:
朋友的机器有块硬盘有问题,正好MYSQL的数据库数据在上面,想转到另外一个盘里,转后无法启动MSYQL 。我在VM上试验并成功了。

目标:
原来MYSQL数据库位置是:/var/lib/mysql/*,移动到/home/lib/mysql/*下。

环境:
VM WORKSTATION5
centos4.4
mysql4.1
apache2
Discuz5

步骤:
1。
#service mysqld stop
#ps -ef |grep mysqld    #确认停止了。
2。
#cd /var/lib/
#tar cvf mysql.tar mysql/    #打包,以防万一恢复。
#mkdir /home/lib/mysql/
#mv mysql/* /home/lib/mysql/
#ll /home/lib/mysql/     #查看确认都复制过来了。
3。
#cp /etc/my.cnf /etc/my.cnf.bak    #备份
#vi /etc/my.cnf
修改后的路径:
[mysqld]
datadir=/home/lib/mysql
socket=/home/lib/mysql/mysql.sock
添加下面的内容:
[client]
socket = /home/lib/mysql/mysql.sock
4。
#service mysqld start     #启动,因该可以看到可以启动。

5。
测试即可。

难点:
[client]
socket = /home/lib/mysql/mysql.sock
默认的/etc/my.cnf里没有这个。如果不加则无法启动。

再试试:chown -R mysql:mysql /home/mysql

了解更多

MySQL百万以上数据分页

05.13.2010, MySQL百万以上数据分页已关闭评论, mysql, by .

MySQL优化SQL语句
最快和最少两个原则
最快:
1、使用主键作为条件
2、使用唯一的索引作为条件
3、使用整数(或时间)类型的索引作为条件
4、使用定长的列索引作为条件
最少:
缩小查询范围
用 select id 等代替 select *
用查询先找出最少的主键:select id from my_tab order by id desc limit 0,100

百万以上数据分页实例

取总数: Select SQL_BUFFER_RESULT count(id) as all_ID from my_tab

总页数: 总数/每页条数

最后一页的条数: 总数%每页条数

查询数据:
select id,title,price from my_tab m INNER JOIN ( select id as my_id from ( select id from my_tab order by id desc limit 1741500,100 ) as tmp ) as temp ON my_id=id

第一步、按照最快原则,以主键id作为条件排序 ( select id from my_tab order by id desc limit 1741500,100 ) as tmp

第二步、按照最少原则,只取回当前所需的记录,而且只取id ( select id from my_tab order by id desc limit 1741500,100 ) as tmp

第三步、按照最快原则,以主键id作为条件取回所需的信息 select id,title,price from my_tab m INNER JOIN ( … ) as temp ON my_id=id

显示列表实例: http://58.dwyfz.com

了解更多

Mysql limit 优化,百万至千万级快速分页,–复合索引的引用并应用于轻量级框架

05.13.2010, Mysql limit 优化,百万至千万级快速分页,–复合索引的引用并应用于轻量级框架已关闭评论, mysql, by .

MySql 性能到底能有多高?用了php半年多,真正如此深入的去思考这个问题还是从前天开始。有过痛苦有过绝望,到现在充满信心!MySql 这个数据库绝对是适合dba级的高手去玩的,一般做一点1万篇新闻的小型系统怎么写都可以,用xx框架可以实现快速开发。可是数据量到了10万,百万至千万,他的性能还能那么高吗?一点小小的失误,可能造成整个系统的改写,甚至更本系统无法正常运行!好了,不那么多废话了。用事实说话,看例子:

数据表 collect ( id, title ,info ,vtype) 就这4个字段,其中 title 用定长,info 用text, id 是逐渐,vtype是tinyint,vtype是索引。这是一个基本的新闻系统的简单模型。现在往里面填充数据,填充10万篇新闻。

最后collect 为 10万条记录,数据库表占用硬盘1.6G。OK ,看下面这条sql语句:

select id,title from collect limit 1000,10; 很快;基本上0.01秒就OK,再看下面的

select id,title from collect limit 90000,10; 从9万条开始分页,结果?

8-9秒完成,my god 哪出问题了????其实要优化这条数据,网上找得到答案。看下面一条语句:

select id from collect order by id limit 90000,10; 很快,0.04秒就OK。 为什么?因为用了id主键做索引当然快。网上的改法是:

select id,title from collect where id>=(select id from collect order by id limit 90000,1) limit 10;

这就是用了id做索引的结果。可是问题复杂那么一点点,就完了。看下面的语句

select id from collect where vtype=1 order by id limit 90000,10; 很慢,用了8-9秒!

到了这里我相信很多人会和我一样,有崩溃感觉!vtype 做了索引了啊?怎么会慢呢?vtype做了索引是不错,你直接 select id from collect where vtype=1 limit 1000,10; 是很快的,基本上0.05秒,可是提高90倍,从9万开始,那就是0.05*90=4.5秒的速度了。和测试结果8-9秒到了一个数量级。从这里开始有人提出了分表的思路,这个和discuz 论坛是一样的思路。思路如下:

建一个索引表: t (id,title,vtype) 并设置成定长,然后做分页,分页出结果再到 collect 里面去找info 。 是否可行呢?实验下就知道了。

10万条记录到 t(id,title,vtype) 里,数据表大小20M左右。用

select id from t where vtype=1 order by id limit 90000,10; 很快了。基本上0.1-0.2秒可以跑完。为什么会这样呢?我猜想是因为collect 数据太多,所以分页要跑很长的路。limit 完全和数据表的大小有关的。其实这样做还是全表扫描,只是因为数据量小,只有10万才快。OK, 来个疯狂的实验,加到100万条,测试性能。

加了10倍的数据,马上t表就到了200多M,而且是定长。还是刚才的查询语句,时间是0.1-0.2秒完成!分表性能没问题?错!因为我们的limit还是9万,所以快。给个大的,90万开始

select id from t where vtype=1 order by id limit 900000,10; 看看结果,时间是1-2秒!

why ?? 分表了时间还是这么长,非常之郁闷!有人说定长会提高limit的性能,开始我也以为,因为一条记录的长度是固定的,mysql 应该可以算出90万的位置才对啊? 可是我们高估了mysql 的智能,他不是商务数据库,事实证明定长和非定长对limit影响不大? 怪不得有人说 discuz到了100万条记录就会很慢,我相信这是真的,这个和数据库设计有关!

难道MySQL 无法突破100万的限制吗???到了100万的分页就真的到了极限???

答案是: NO !!!! 为什么突破不了100万是因为不会设计mysql造成的。下面介绍非分表法,来个疯狂的测试!一张表搞定100万记录,并且10G 数据库,如何快速分页!

好了,我们的测试又回到 collect表,开始测试结论是: 30万数据,用分表法可行,超过30万他的速度会慢道你无法忍受!当然如果用分表+我这种方法,那是绝对完美的。但是用了我这种方法后,不用分表也可以完美解决!

答案就是:复合索引! 有一次设计mysql索引的时候,无意中发现索引名字可以任取,可以选择几个字段进来,这有什么用呢?开始的select id from collect order by id limit 90000,10; 这么快就是因为走了索引,可是如果加了where 就不走索引了。抱着试试看的想法加了 search(vtype,id) 这样的索引。然后测试

select id from collect where vtype=1 limit 90000,10; 非常快!0.04秒完成!

再测试: select id ,title from collect where vtype=1 limit 90000,10; 非常遗憾,8-9秒,没走search索引!

再测试:search(id,vtype),还是select id 这个语句,也非常遗憾,0.5秒。

综上:如果对于有where 条件,又想走索引用limit的,必须设计一个索引,将where 放第一位,limit用到的主键放第2位,而且只能select 主键!

完美解决了分页问题了。可以快速返回id就有希望优化limit , 按这样的逻辑,百万级的limit 应该在0.0x秒就可以分完。看来mysql 语句的优化和索引时非常重要的!

好了,回到原题,如何将上面的研究成功快速应用于开发呢?如果用复合查询,我的轻量级框架就没的用了。分页字符串还得自己写,那多麻烦?这里再看一个例子,思路就出来了:

select * from collect where id in (9000,12,50,7000); 竟然 0秒就可以查完!

mygod ,mysql 的索引竟然对于in语句同样有效!看来网上说in无法用索引是错误的!

有了这个结论,就可以很简单的应用于轻量级框架了:

代码如下:

$db=dblink();
$db->pagesize=20;

$sql="select id from collect where vtype=$vtype";

$db->execute($sql);
$strpage=$db->strpage(); //将分页字符串保存在临时变量,方便输出
while($rs=$db->fetch_array()){
   $strid.=$rs[‘id’].’,’;
}
$strid=substr($strid,0,strlen($strid)-1); //构造出id字符串
$db->pagesize=0; //很关键,在不注销类的情况下,将分页清空,这样只需要用一次数据库连接,不需要再开;
$db->execute("select id,title,url,sTime,gTime,vtype,tag from collect where id in ($strid)");

<?php while($rs=$db->fetch_array()): ?>
<tr>
    <td>&nbsp;<?php echo $rs[‘id’];?></td>
    <td>&nbsp;<?php echo $rs[‘url’];?></td>
    <td>&nbsp;<?php echo $rs[‘sTime’];?></td>
    <td>&nbsp;<?php echo $rs[‘gTime’];?></td>
    <td>&nbsp;<?php echo $rs[‘vtype’];?></td>
    <td>&nbsp;<a href="?act=show&id=<?php echo $rs[‘id’];?>" target="_blank"><?php echo $rs[‘title’];?></a></td>
    <td>&nbsp;<?php echo $rs[‘tag’];?></td>
</tr>
<?php endwhile; ?>
</table>
<?php
echo $strpage;

通过简单的变换,其实思路很简单:1)通过优化索引,找出id,并拼成 "123,90000,12000" 这样的字符串。2)第2次查询找出结果。

小小的索引+一点点的改动就使mysql 可以支持百万甚至千万级的高效分页!

通过这里的例子,我反思了一点:对于大型系统,PHP千万不能用框架,尤其是那种连sql语句都看不到的框架!因为开始对于我的轻量级框架都差点崩溃!只适合小型应
用的快速开发,对于ERP,OA,大型网站,数据层包括逻辑层的东西都不能用框架。如果程序员失去了对sql语句的把控,那项目的风险将会成几何级数增加!尤其是用mysql 的时候,mysql 一定需要专业的dba 才可以发挥他的最佳性能。一个索引所造成的性能差别可能是上千倍!

PS: 经过实际测试,到了100万的数据,160万数据,15G表,190M索引,就算走索引,limit都得0.49秒。所以分页最好别让别人看到10万条以后的数据,要不然会很慢!就算用索引。经过这样的优化,mysql到了百万级分页是个极限!但有这样的成绩已经很不错,如果你是用sqlserver肯定卡死!而160万的数据用 id in (str) 很快,基本还是0秒。如果这样,千万级的数据,mysql应该也很容易应付。

了解更多

网页循环播放音乐代码mp3

03.28.2010, 网页循环播放音乐代码mp3已关闭评论, div+css & html, by .

网页循环播放音乐代码

打开网页后自动播放(就象背景音乐)声音文件mlh.mp3:
<Embed src="mlh.mp3" HIDDEN="TRUE" AUTOSTART="TRUE"></Embed>
2、插入播放背景音乐(wav、midi、mp3)的代码
只要在代码窗口中的<head>和</head>标签之间以下代码即可:
<bgsound src="Music File Name" loop=n>
【注】①Music File Name是背景音乐文件名,其格式可以是:.mid,.mp3,.wav,.wma,.rmi。
②n表示循环次数,若n为-1则表示无限循环。
③网页文件和音乐文件要在同一文件夹中。
【例5】无限循环播放背景音乐mlh.mp3:
<bgsound src="mlh.mp3" loop="-1">

了解更多

linux fgetcsv 乱码

03.08.2010, linux fgetcsv 乱码已关闭评论, php, by .

上传数据使用fgetcsv 在windows下不会乱码,传到linux上,出现乱码了。

网上找了解决办法

在读取CSV时候加上

setlocale(LC_ALL,’zh_CN’);

setlocale(LC_ALL,’zh_CN’);
            while($data=fgetcsv($handle,1000,","))
            { }

 

以下是网上找到的文章

mark一下

 

fgetcsv对区域设置敏感

CSV 逗号分隔符作为批量处理文件非常的方便适用。可以做为系统之间数据传递的通用文件格式。

在PHP中对csv格式文件处理的函数fgetcsv 能非常方便的处理csv格式的文件!

但是fgetcsv 对服务器区域设置是敏感的。

注意:

该函数对区域设置是敏感的。比如说 LANG 设为 en_US.UTF-8 的话,单字节编码的文件就会出现读取错误。

这是PHP 手册上的说明。

实际应用中,当你在Linux 系统的服务器上对gb2312的csv格式文件进行处理的时候,就会出现乱码现象,如果你的linux系统是默认设置的话。

解决方法是:

使用: setlocale 函数设置环境变量。比如要设置使用gb 的区域设置可以在fgetcsv前使用下面的语句。

setlocale(LC_ALL,array(‘zh_CN.gbk’,’zh_CN.gb2312′,’zh_CN.gb18030′));

具体使用哪些locale 可以使用linux 命令 locale -a 查看系统支持哪些。

这可以解决fgetcsv 函数对区域设置的敏感问题。
Windows 系统服务器不知道setlocale是否好使,(php手册上没有说明setlocale只适用于Linux)!

了解更多

mysql insert into select

03.05.2010, mysql insert into select已关闭评论, mysql, by .

今天数据迁移用到的

insert into `wetao_mobile2` (mobile,addtime,name,address,haomaleibie,price)
SELECT mobilenumber,addtime,name,address,brand,price FROM `wetao_mobile`

了解更多

mysql select 字段固定值

03.04.2010, mysql select 字段固定值已关闭评论, mysql, by .

select *,-1+0 as total_count from table
给total_count固定值-1
等于
select *,(-1) total_count from table

了解更多