编程语言 - 私房课
当前位置:首页 » 编程语言

Session的生命周期 On 编程语言  @2015-08-21

以前在学习的时候没怎么注意,今天又回过头来仔细研究研究了一下Session的生命周期。

  Session存储在服务器端,一般为了防止在服务器的内存中(为了高速存取),Sessinon在用户访问第一次访问服务器时创建,需要注意只有访问JSP、Servlet等程序时才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session,可调用request.getSession(true)强制生成Session。

  Session什么时候失效?

  1. 服务器会把长时间没有活动的Session从服务器内存中清除,此时Session便失效。Tomcat中Session的默认失效时间为20分钟。

  2. 调用Session的invalidate方法。

  Session对浏览器的要求:

  虽然Session保存在服务器,对客户端是透明的,它的正常运行仍然需要客户端浏览器的支持。这是因为Session需要使用Cookie作为识别标志。HTTP协议是无状态的,Session不能依据HTTP连接来判断是否为同一客户,因此服务器向客户端浏览器发送一个名为JSESSIONID的Cookie,它的值为该Session的id(也就是HttpSession.getId()的返回值)。Session依据该Cookie来识别是否为同一用户。

  该Cookie为服务器自动生成的,它的maxAge属性一般为-1,表示仅当前浏览器内有效,并且各浏览器窗口间不共享,关闭浏览器就会失效。因此同一机器的两个浏览器窗口访问服务器时,会生成两个不同的Session。但是由浏览器窗口内的链接、脚本等打开的新窗口(也就是说不是双击桌面浏览器图标等打开的窗口)除外。这类子窗口会共享父窗口的Cookie,因此会共享一个Session。

  注意:新开的浏览器窗口会生成新的Session,但子窗口除外。子窗口会共用父窗口的Session。例如,在链接上右击,在弹出的快捷菜单中选择”在新窗口中打开”时,子窗口便可以访问父窗口的Session。

如果客户端浏览器将Cookie功能禁用,或者不支持Cookie怎么办?例如,绝大多数的手机浏览器都不支持Cookie。Java Web提供了另一种解决方案:URL地址重写。

  URL地址重写是对客户端不支持Cookie的解决方案。URL地址重写的原理是将该用户Session的id信息重写到URL地址中。服务器能够解析重写后的URL获取Session的id。这样即使客户端不支持Cookie,也可以使用Session来记录用户状态。HttpServletResponse类提供了encodeURL(String url)实现URL地址重写,该方法会自动判断客户端是否支持Cookie。如果客户端支持Cookie,会将URL原封不动地输出来。如果客户端不支持Cookie,则会将用户Session的id重写到URL中。

  注意:TOMCAT判断客户端浏览器是否支持Cookie的依据是请求中是否含有Cookie。尽管客户端可能会支持Cookie,但是由于第一次请求时不会携带任何Cookie(因为并无任何Cookie可以携带),URL地址重写后的地址中仍然会带有jsessionid。当第二次访问时服务器已经在浏览器中写入Cookie了,因此URL地址重写后的地址中就不会带有jsessionid了。

打签»   评论» Session的生命周期已关闭评论

Yii中validator之scenario(即rulse中的on) On 编程语言  @2014-03-07

Yii中有个场景的概念,我们用到场景的地方主要是在model中定义rules规则的时候,可以对不同的场景使用不同的校验规则,所以,自然而然会认为所谓的场景就是对应的action的名字。其实场景和action的名字是不同的概念来的,不能混为一谈。scenario则是M的一种属性,理论上,scenario是独立于action概念的,可以在没有action的场合下使用scenario。model的scenario是通过设置它的scenario属性设置的,它和使用model的action没有任何关系。

比如:

$model=new User;
$model->scenario = ‘create’;


$model=new User(‘create’);

都是设置了执行一个action的时候对model进行校验的场景

1
2
3
4
5
6
7
8
9
10
11
12
13
public function rules() {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('username, email', 'required'),
            array('password, confirm_password', 'required', 'on'=>'create'),
            array('username', 'unique'),
            array('username, email', 'length', 'max'=>50),
            array('password, confirm_password', 'length', 'min'=>6, 'max'=>32),
            array('email', 'email'),
            array('confirm_password', 'compare', 'compareAttribute'=>'password', 'on'=>'create,update')
         );
}

上面的校验规则说明了初始密码和确认密码在create场景中是required的,和密码确认的compare是在create和update场景中都必须校验的。主要在action中对默认制定了对应的场景属性,在提交表单做校验的时候就能达到rules中定义的规则了。

下面是引用yii官方论坛帖子中牛人关于场景的解释:

场景的概念来自 用例驱动的方法学

用银行操作来说 存款 取款 转账 就是用例(关于用例的概念自己查阅相关资料或者google 简单点说就是里程碑式的操作 是系统级的方法
可以认为是应用级别的事务) 在面向对象中 模型层的东西会参加多个用例(一个对象有若干个方法 并不是所有方法在一次操作中都被用到
某个用例操作中只会用到一个或几个) 你可以这样认为用例等价场景 还有就是一个用例中可能不止一个模型参与其中

对AR来说 其中的若干属性只会参与一个用例(插入insert 更新update 或者搜索search) 在某种高度对象的方法和属性是一个级别概念 所以某些属性/方法 可以用用例来归组 经常在一起使用的方法或属性可以归为一个用例(场景)之中

用例可以自己定义 根据应用特征 比如User 这个模型类 在登陆操作(场景/用例/应用事务)中只会用到用户名和密码
所有这两个组合可以归为一个场景 其他属性根据业务可以自定义归组 ; 在拿改密码来说你可能需要用户输入旧密码 和新密码
那么这两个就会归属同一个用例(可以随意起名 比如changePassword等)

场景名不是yii定死的 但insert update 和search 是默认的(惯例而已) 在actionCreate actionUpdate
actionAdmin中出现的$model 默认的scenario 就分别是insert,update,search 你可以打印出来
echo $model->scenario ;die(); //在render 之前 试着调试输出;

官方链接地址:关于场景的解释

打签» ,   评论» Yii中validator之scenario(即rulse中的on)已关闭评论

php编译原理 On 编程语言  @2014-02-15

刚看到一个不错的文章,关于php编译的,分享下(忘记了地址~~):

最近要给Yahoo的同事们做一个关于PHP和Apache处理请求的内部机制的讲座,刚好写了些关于Opcodes的文字,就发上来了,这个文章基于 Sara Golemon大师的《Understanding OPcode》

Opcode是一种PHP脚本编译后的中间语言,就像Java的ByteCode,或者.NET的MSL,举个例子,比如你写下了如下的PHP代码:

1
2
3
4
5
<?php
   echo "Hello World";
   $a = 1 + 1;
   echo $a;
?>

PHP执行这段代码会经过如下4个步骤(确切的来说,应该是PHP的语言引擎Zend)

1.Scanning(Lexing) ,将PHP代码转换为语言片段(Tokens)
2.Parsing, 将Tokens转换成简单而有意义的表达式
3.Compilation, 将表达式编译成Opocdes
4.Execution, 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。
题外话:现在有的Cache比如APC,可以使得PHP缓存住Opcodes,这样,每次有请求来临的时候,就不需要重复执行前面3步,从而能大幅的提高PHP的执行速度。

那什么是Lexing? 学过编译原理的同学都应该对编译原理中的词法分析步骤有所了解,Lex就是一个词法分析的依据表。 Zend/zend_language_scanner.c会根据Zend/zend_language_scanner.l(Lex文件),来输入的 PHP代码进行词法分析,从而得到一个一个的“词”,PHP4.2开始提供了一个函数叫token_get_all,这个函数就可以讲一段PHP代码 Scanning成Tokens;
如果用这个函数处理我们开头提到的PHP代码,将会得到如下结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Array
(
    [0] => Array
        (
           [0] => 367
           [1] => Array
        (
            [0] => 316
            [1] => echo
        )
    [2] => Array
        (
            [0] => 370
            [1] =>
        )
    [3] => Array
        (
            [0] => 315
            [1] => "Hello World"
        )
    [4] => ;
    [5] => Array
        (
            [0] => 370
            [1] =>
        )
    [6] => =
    [7] => Array
        (
            [0] => 370
            [1] =>
        )
    [8] => Array
        (
            [0] => 305
            [1] => 1
        )
    [9] => Array
        (
            [0] => 370
            [1] =>
        )
    [10] => +
    [11] => Array
        (
            [0] => 370
            [1] =>
        )
    [12] => Array
        (
            [0] => 305
            [1] => 1
        )
    [13] => ;
    [14] => Array
        (
            [0] => 370
            [1] =>
        )
    [15] => Array
        (
            [0] => 316
            [1] => echo
        )
    [16] => Array
        (
            [0] => 370
            [1] =>
        )
    [17] => ;
)

分析这个返回结果我们可以发现,源码中的字符串,字符,空格,都会原样返回。每个源代码中的字符,都会出现在相应的顺序处。而,其他的比如标签,操作符,语句,都会被转换成一个包含俩部分的Array: Token ID (也就是在Zend内部的改Token的对应码,比如,T_ECHO,T_STRING),和源码中的原来的内容。
接下来,就是Parsing阶段了,Parsing首先会丢弃Tokens Array中的多于的空格,然后将剩余的Tokens转换成一个一个的简单的表达式

1.echo a constant string
2.add two numbers together
3.store the result of the prior expression to a variable
4.echo a variable

然后就改Compilation阶段了,它会把Tokens编译成一个个op_array, 每个op_arrayd包含如下5个部分:

1.Opcode数字的标识,指明了每个op_array的操作类型,比如add , echo
2.结果 存放Opcode结果
3.操作数1 给Opcode的操作数
4.操作数2
5.扩展值 1个整形用来区别被重载的操作符
比如,我们的PHP代码会被Parsing成:

* ZEND_ECHO ‘Hello World’
* ZEND_ADD ~0 1 1
* ZEND_ASSIGN !0 ~0
* ZEND_ECHO !0

呵呵,你可能会问了,我们的$a去那里了?
恩,这个要介绍操作数了,每个操作数都是由以下俩个部分组成:

a)op_type : 为IS_CONST, IS_TMP_VAR, IS_VAR, IS_UNUSED, or IS_CV

b)u,一个联合体,根据op_type的不同,分别用不同的类型保存了这个操作数的值(const)或者左值(var)
而对于var来说,每个var也不一样

IS_TMP_VAR, 顾名思义,这个是一个临时变量,保存一些op_array的结果,以便接下来的op_array使用,这种的操作数的u保存着一个指向变量表的一个句柄(整数),这种操作数一般用~开头,比如~0,表示变量表的0号未知的临时变量

IS_VAR 这种就是我们一般意义上的变量了,他们以$开头表示

IS_CV 表示ZE2.1/PHP5.1以后的编译器使用的一种cache机制,这种变量保存着被它引用的变量的地址,当一个变量第一次被引用的时候,就会被CV起来,以后对这个变量的引用就不需要再次去查找active符号表了,CV变量以!开头表示。

这么看来,我们的$a被优化成!0了。

打签»   评论» php编译原理已关闭评论

分享一个国内身份证号码验证程序 On 编程语言  @2013-10-21

本程序主要用于国内身份证号码的验证,支持15位与最新的18位身份证号码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
function is_idcard( $id )
{
    $id = strtoupper($id);
    $regx = "/(^\d{15}$)|(^\d{17}([0-9]|X)$)/";
    $arr_split = array();
    if(!preg_match($regx, $id))
    {
        return FALSE;
    }
    if(15==strlen($id)) //检查15位
    {
        $regx = "/^(\d{6})+(\d{2})+(\d{2})+(\d{2})+(\d{3})$/";
 
        @preg_match($regx, $id, $arr_split);
        //检查生日日期是否正确
        $dtm_birth = "19".$arr_split[2] . '/' . $arr_split[3]. '/' .$arr_split[4];
        if(!strtotime($dtm_birth))
        {
            return FALSE;
        } else {
            return TRUE;
        }
    }
    else           //检查18位
    {
        $regx = "/^(\d{6})+(\d{4})+(\d{2})+(\d{2})+(\d{3})([0-9]|X)$/";
        @preg_match($regx, $id, $arr_split);
        $dtm_birth = $arr_split[2] . '/' . $arr_split[3]. '/' .$arr_split[4];
        if(!strtotime($dtm_birth))  //检查生日日期是否正确
        {
            return FALSE;
        }
        else
        {
            //检验18位身份证的校验码是否正确。
            //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。
            $arr_int = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
            $arr_ch = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
            $sign = 0;
            for ( $i = 0; $i < 17; $i++ )
            {
                $b = (int) $id{$i};
                $w = $arr_int[$i];
                $sign += $b * $w;
            }
            $n  = $sign % 11;
            $val_num = $arr_ch[$n];
            if ($val_num != substr($id,17, 1))
            {
                return FALSE;
            }
            else
            {
                return TRUE;
            }
        }
    }
 
}
打签»   评论» 分享一个国内身份证号码验证程序已关闭评论

新鲜出炉LNMP安装包,快来下载呀 On 编程语言  @2013-10-18

DebianLNMP是一个用Linux Shell编写的可以为Debian/Ubuntu VPS(VDS)或独立主机安装LNMP(Nginx、MySQL、PHP、phpMyAdmin)生产环境的Shell程序。
DebianLNMP 是以 Debian + Linux + Nginx + MySQL + PHP 的安装顺序命名;
DebianLNMP一键安装包是很不错的安装脚本,用在低配置VPS上最合适不过啦,安装方便快捷,轻轻松松全自动安装LNMP(Nginx、MySQL、PHP、phpMyAdmin)可直接用再生产环境。

1
2
root@DebianLNMP-Jimmyli:~# wget http://sourceforge.net/projects/debian-lnmp/files/DebianLNMP/DebianLNMP-Jimmyli.sh
root@DebianLNMP-Jimmyli:~# sh DebianLNMP-Jimmyli.sh

下载地址:
http://sourceforge.net/projects/debian-lnmp/files/DebianLNMP/

打签» , , , , , ,   评论» 新鲜出炉LNMP安装包,快来下载呀已关闭评论

php常见的几种排序算法 On 编程语言  @2013-10-10

以下是应用示例,在这几种算法中,我分别对3000个数组元素做排序操作,其中插入排序、选择排序、冒泡排序花费的时间大约在60秒左右(应不同电脑配置而定),而快速排序相对要快得多。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?php
//插入排序(一维数组)
function insert_sort($arr){
    $count = count($arr);
    for($i=1; $i<$count; $i++){
        $tmp = $arr[$i];
        $j = $i - 1;
        while($arr[$j] > $tmp){
            $arr[$j+1] = $arr[$j];
            $arr[$j] = $tmp;
            $j--;
        }
    }
    return $arr;
}


//选择排序(一维数组)
function select_sort($arr){
    $count = count($arr);
    for($i=0; $i<$count; $i++){
        $k = $i;
        for($j=$i+1; $j<$count; $j++){
            if ($arr[$k] > $arr[$j])
                $k = $j;
            if ($k != $i){
                $tmp = $arr[$i];
                $arr[$i] = $arr[$k];
                $arr[$k] = $tmp;
            }
        }
    }
    return $arr;
}

//冒泡排序(一维数组) 
function bubble_sort($array){ 
    $count = count($array); 
    if ($count <= 0) return false; 
    
    for($i=0; $i<$count; $i++){ 
        for($j=$count-1; $j>$i; $j--){ 
            if ($array[$j] < $array[$j-1]){ 
                $tmp = $array[$j]; 
                $array[$j] = $array[$j-1]; 
                $array[$j-1] = $tmp; 
            } 
        } 
    } 
    return $array; 
} 

//快速排序(一维数组) 
function quick_sort($array){ 
    if (count($array) <= 1) return $array; 

    $key = $array[0]; 
    $left_arr = array(); 
    $right_arr = array(); 
    for ($i=1; $i<count($array); $i++) {
        if($array[$i] <= $key) {
            $left_arr[] = $array[$i]; 
        } else {
            $right_arr[] = $array[$i];
        }
    }
    $left_arr = quick_sort($left_arr); 
    $right_arr = quick_sort($right_arr); 
    
    return array_merge($left_arr, array($key), $right_arr); 
} 

?>
打签» ,   评论» php常见的几种排序算法已关闭评论

介绍几款不错的汉字分词处理系统 On 编程语言  @2013-07-21

汉字分词是做中文检索、文件分析的基础,在搜索引擎数据挖掘方面有广泛的应用。中文分词不像英语哪样使用空格对词进行区分,而是以语素做为基本元素。下面给大家推荐几款不错的分词处理工具:
1、ICTCLAS

  • 全球最受欢迎的汉语分词开源系统
  • 获得首届国际分词大赛综合排名第一,国家973评测第一名
  • 人名识别、地名识别、组织机构名识别
  • 支持行业词典、用户自定义词典
  • 多级词性标注
  • 关键词提取、指纹提取

ICTCLAS有共享版、商业版、行业版,支持Linux平台,但不开源。ICTCLAS已进入商用,且应用范围较广,相信分词效率出色。
官方网站:http://ictclas.org/index.html
2、HTTPCWS – 基于HTTP协议的开源中文分词系统

张宴的作品。目前仅支持Linux系统。HTTPCWS使用“ICTCLAS 3.0 2009共享版中文分词算法”的API进行分词处理,得出分词结果。

ICTCLAS(Institute of Computing Technology, Chinese Lexical Analysis System)是中国科学院计算技术研究所在多年研究工作积累的基础上,基于多层隐马模型研制出的汉语词法分析系统,主要功能包括中文分词;词性标注;命名实体识别;新词识别;同时支持用户词典。ICTCLAS分词精度达到98.45%,各种词典数据压缩后不到3M。

由于 ICTCLAS 3.0 2009 共享版只支持GBK编码,因此,如果是UTF-8编码的字符串,可以先用iconv函数转换成GBK编码,再用httpcws进行分词处理,最后转换回UTF-8编码。

HTTPCWS 软件自身(包括httpcws.cpp源文件、dict/httpcws_dict.txt自定义词库)采用NewBSD开源协议,可以自由修改。HTTPCWS 使用的 ICTCLAS 共享版 API 及 dict/Data/ 目录内的语料库,版权及著作权归中国科学院计算技术研究所、ictclas.org所有,使用需遵循其相关协议。
下载地址:https://code.google.com/p/httpcws/
3、SCWS – 简易中文分词系统

SCWS 在概念上并无创新成分,采用的是自行采集的词频词典,并辅以一定程度上的专有名称、人名、地名、数字年代等规则集,经小范围测试大概准确率在 90% ~ 95% 之间,已能基本满足一些中小型搜索引擎、关键字提取等场合运用。 SCWS 采用纯 C 代码开发,以 Unix-Like OS 为主要平台环境,提供共享函数库,方便植入各种现有软件系统。此外它支持 GBK,UTF-8,BIG5 等汉字编码,切词效率高。

系统平台:Windows/Unix

开发语言:C

使用方式:PHP扩展

演示网址:http://www.ftphp.com/scws/demo.php

开源官网:http://www.ftphp.com/scws/

特色:作为PHP扩展,容易与现有的基于PHP架构的Web系统继续集成,是其一大优势。

4、PhpanAlysis – PHP无组件分词系统
PhpanAlysis分词系统是基于字符串匹配的分词方法 ,这种方法又叫做机械分词方法,它是按照一定的策略将待分析的汉字串与一个“充分大的”机器词典中的词条进行配,若在词典中找到某个字符串,则匹配成功(识别出一个词)。按照扫描方向的不同,串匹配分词方法可以分为正向匹配 和逆向匹配;按照不同长度优先匹配的情况,可以分为最大(最长)匹配和最小(最短)匹配;按照是否与词性标注过程相结合,又可以分为单纯分词方法和分词与标注相结合的一体化方法。

系统平台:PHP环境

开发语言:PHP

使用方式:HTTP服务

演示网址:http://www.itgrass.com/phpanalysis/

开源官网:http://www.itgrass.com/phpanalysis/

晴枫附注:实现简单,容易使用,能做一些简单应用,但大数据量的计算效率不如前几种。

试用了几个系统,基本分词功能都没什么问题,只是在个别一些词的划分上存在一些差异;对于词性的确定,系统间有所不同。

另外,可以看看我以前写的一篇中文分词的简单介绍 http://www.sifangke.com/2012/01/php-segword/

打签»   评论» 介绍几款不错的汉字分词处理系统已关闭评论

MYSQL中无重复插入更新的三种方法 On 编程语言  @2013-05-26

第一种解决方案:
如果你指定了ON DUPLICATE KEY UPDATE命令语句,那么在唯一索引或者主索引的作用下将不插入与数据库记录重复的内容,但同时会更新数据库中的旧记录。例如,字段a被声明为唯一索引并且里面只包含有值为1的记录,以下两个语句会达到同样的效果:

一、INSERT INTO table (a,b,c) VALUES (1,2,3)
     ON DUPLICATE KEY UPDATE c=c+1;

二、UPDATE table SET c=c+1 WHERE a=1;

受影响的是a=1的行,当插入时c的值加1。
如果字段b也是唯一的话,这个插入语句将和以下语句的效果一样:
UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
如果a=1 OR b=2匹配了不止一行,也只是第一行被更新。一般地,如果表中有多个唯一索引的话,你应该避免在使用用ON DUPLICATE KEY子句。
你可以在插入更新语句 INSERT … UPDATE 中使用 VALUES(字段名) 函数去关联某一行记录。也就是说, VALUES(字段名) 可以用在UPDATE语句中去更新某字段的值而不会出现重复键。这个函数在多行插入中尤其有用。但是函数 VALUES() 仅当用在 INSERT … UPDATE 语句中才有意义,否则会返回NULL。例如:

INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
  ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

这个语句和下面两个是同效果的:

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=3;
INSERT INTO table (a,b,c) VALUES (4,5,6)
  ON DUPLICATE KEY UPDATE c=9;

如果表中包含有一个自动递增字段AUTO_INCREMENT,并用 INSERT … UPDATE 插入一行,函数 LAST_INSERT_ID()会返回AUTO_INCREMENT的值,如果这个语句更新某一行, LAST_INSERT_ID() 就没有意义了。但是,你可以通过用 LAST_INSERT_ID(expr)使它变得有意义,假如id字段是自动递增栏的话,使 LAST_INSERT_ID() 对更新语句有意义的方法如下:

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;

如果你使用 ON DUPLICATE KEY UPDATE 语句的话,延迟执行选项 DELAYED 将被忽略。
第二种解决方案
这种解决方案比较通用,不过个人感觉性能不是很好(没有测试)
示例一:插入多条记录
假设有一个主键为 client_id 的 clients 表,可以使用下面的语句:

INSERT INTO clients 
(client_id, client_name, client_type) 
SELECT supplier_id, supplier_name, 'advertising' 
FROM suppliers 
WHERE not exists (select * from clients 
where clients.client_id = suppliers.supplier_id); 

示例二:插入单条记录

INSERT INTO clients 
(client_id, client_name, client_type) 
SELECT 10345, 'IBM', 'advertising' 
FROM dual 
WHERE not exists (select * from clients 
where clients.client_id = 10345); 

使用 dual 做表名可以让你在 select 语句后面直接跟上要插入字段的值,即使这些值还不存在当前表中。
第三种解决方案
使用REPLACE语句
  我们在使用数据库时可能会经常遇到这种情况。如果一个表在一个字段上建立了唯一索引,当我们再向这个表中使用已经存在的键值插入一条记录,那将会抛出一个主键冲突的错误。当然,我们可能想用新记录的值来覆盖原来的记录值。如果使用传统的做法,必须先使用DELETE语句删除原先的记录,然后再使用INSERT插入新的记录。而在MySQL中为我们提供了一种新的解决方案,这就是REPLACE语句。使用REPLACE插入一条记录时,如果不重复,REPLACE就和INSERT的功能一样,如果有重复记录,REPLACE就使用新记录的值来替换原来的记录值。
  使用REPLACE的最大好处就是可以将DELETE和INSERT合二为一,形成一个原子操作。这样就可以不必考虑在同时使用DELETE和INSERT时添加事务等复杂操作了。

  在使用REPLACE时,表中必须有唯一索引,而且这个索引所在的字段不能允许空值,否则REPLACE就和INSERT完全一样的。

  在执行REPLACE后,系统返回了所影响的行数,如果返回1,说明在表中并没有重复的记录,如果返回2,说明有一条重复记录,系统自动先调用了DELETE删除这条记录,然后再记录用INSERT来插入这条记录。如果返回的值大于2,那说明有多个唯一索引,有多条记录被删除和插入。

  REPLACE的语法和INSERT非常的相似,如下面的REPLACE语句是插入或更新一条记录。

  REPLACE INTO users (id,name,age) VALUES(123, '赵本山', 50); 

  插入多条记录:

  REPLACE INTO users(id, name, age) 
  VALUES(123, '赵本山', 50), (134,'Mary',15); 

  REPLACE也可以使用SET语句

  REPLACE INTO users SET id = 123, name = '赵本山', age = 50; 

  上面曾提到REPLACE可能影响3条以上的记录,这是因为在表中有超过一个的唯一索引。在这种情况下,REPLACE将考虑每一个唯一索引,并对每一个索引对应的重复记录都删除,然后插入这条新记录。假设有一个table1表,有3个字段a, b, c。它们都有一个唯一索引。

  CREATE TABLE table1(a INT NOT NULL UNIQUE,b INT NOT NULL UNIQUE,c INT NOT NULL UNIQUE); 

  假设table1中已经有了3条记录

  a b c 
  1 1 1 
  2 2 2 
  3 3 3 

  下面我们使用REPLACE语句向table1中插入一条记录。

  REPLACE INTO table1(a, b, c) VALUES(1,2,3); 

  返回的结果如下

  Query OK, 4 rows affected (0.00 sec) 

  在table1中的记录如下

  a b c 
  1 2 3 

我们可以看到,REPLACE将原先的3条记录都删除了,然后将(1, 2, 3)插入。

打签» ,   评论» MYSQL中无重复插入更新的三种方法已关闭评论

discuz!2.5与dedeCMS实现积分同步 On 编程语言  @2013-04-25

在dede与discuz整合的过程中,我们有时候需要将discuz中的积分同步到dede中,目前常见的整合方案是使用discuz自带的ucenter的积分兑换功能进行整合,但这种整合方式不是很完美,不能达到时时在两套系统中同步积分的功能,需要用户在下一次登录系统的时候才会将积分更新,为了解决这个问题我特别写了如下代码(利用MySQL5的触发器功能)实现积分时时同步功能。特别需要注意的是本程序需要你在mysql命令行中执行。(我在phpmyadmin中没有执行成功,搜索了一下貌似我的phpmyadmin版本不支持触发器)

drop trigger if exists tfly_db.scores_update;
CREATE TRIGGER tfly_db.scores_update BEFORE UPDATE on tfly_db.dz_common_member
for each row
begin 
    IF NEW.credits<>0  THEN 
      update tfly_db.ctscms_member set scores=NEW.credits where mb=NEW.username;
    END IF;
end;

这里是执行的截图:

打签» ,   评论» discuz!2.5与dedeCMS实现积分同步已关闭评论

github在windows下的安装使用 On 编程语言  @2013-04-23

现在最流行的源码托管网站应该是github,github带SNS功能,大概已经超越了老牌的sourceforge, google托管等。

但是在使用过程中,github的一堆配置,有些麻烦,比如:http://www.wojilu.com/Forum1/Topic/2266 有相关配置的教程。
昨天,github发布了 windows 下的管理工具,我试用了一下,非常简单、直观、易操作。效果也很炫(完全的 metro UI 风格)。推荐大家体验一下。
官方就这个工具发布的说明:https://github.com/blog/1127-github-for-windows
官方网址:http://windows.github.com/
点击此处下载:http://github-windows.s3.amazonaws.com/setup.exe
下载之后,安装:

安装之后,桌面的快捷方式

程序菜单中的快捷方式

用你在github上的帐号登录

然后将源码库clone到本地

可以通过下面的 open in explorer打开源码所在文件夹。

也可以通过 open a shell here 打开git的命令行窗口。

下面是命令行操作窗口
【创建源码库】你也可以在本地创建一个源码库
【代码提交】接下来,在源码文件夹试着写一些代码,或者直接提交:

【同步到github】

提交之后,点击下图的“sync”就可以同步到github上。也可以不马上同步,多个提交之后再publish。
(这个工具将git本身的pull/push简化为一个同步命令,更加易用)

【分支管理】点击下图 master左侧的分支图标,出现分支管理界面,可以创建分支等。

【恢复到某个旧版本】

先定位到某个提交,然后点击下图的 “rall back to this commit” 即可恢复到此版本

【删除某个提交的内容】

如上图,点击 “revert commit” 即可将此提交内容删除掉(通过创建一个新的提交来删除内容)
总之,这个工具极大的简化了 github 本身的操作,比如clone,创建,帐号管理等等。
同时,也极大的简化了git的操作,完美支持中文(中文文件必须用utf8保存)和中文目录。
【动手,测试一个开源项目】
你可以在github上fork “我记录网站综合系统”来测试,这个源码集成了“SNS/门户CMS/论坛/博客/相册/微博/wiki”等应用程序,在github上的源码网址是:https://github.com/wojilu/wojilu ,然后点击项目右上角的“Fork”命令

这个命令会在你的账号下创建一个 wojilu 项目的复制品,一个wojilu的派生库,并且显示它是“forked from wojilu/wojilu”

——————————————————-
另外,其他类型的git可视化操作工具,最近都有更新,比如 msysGit 也发布了 1.7.10 ,msysGit 正式支持 unicode,同时 TortoiseGit 也发布了1.7.9,完全支持UTF8,也就是支持中文。
http://code.google.com/p/msysgit/downloads/list
http://code.google.com/p/tortoisegit/downloads/list
可以说,在 windows 平台下,无论是 git工具,还是 github工具,都已经很完善了。
打签» ,   评论» github在windows下的安装使用已关闭评论