背着手扇扇子的人
往事随风......前事如梦......
posts - 35,  comments - 17,  trackbacks - 0

有人问这样的sql该怎么实现:
表数据和结构
    CODE NAME    B01    S01    B02    S02
    1          张三       数学    80  
    1          张三                            语文    75
    2          王五       数学    70  
    2          王五    
    3          李四       数学    50  
    3          李四                           语文    88

希望查询出如下结果:
    CODE SUM_STR(NAME)    B01    SUM_STR(S01)    B02    SUM_STR(S02)
    1                张三                    数学                80           语文            75
    2                王五                    数学                70  
    3                李四                    数学                50           语文             88
这个问题可以采用自定义的聚集函数来实现:

create   or   replace  type strcat_type  as  object (
    cat_string 
varchar2 ( 4000 ),
    static 
function  ODCIAggregateInitialize(cs_ctx  In  Out strcat_type)  return   number ,
    member 
function  ODCIAggregateIterate(self  In  Out strcat_type,value  in   varchar2 return  

number ,
    member 
function  ODCIAggregateMerge(self  In  Out strcat_type,ctx2  In  Out strcat_type) 

return   number ,
    member 
function  ODCIAggregateTerminate(self  In  Out strcat_type,returnValue Out 

varchar2 ,flags  in   number return   number
)
/


------------------------------------

create   or   replace  type body strcat_type  is
  static 
function  ODCIAggregateInitialize(cs_ctx  IN  OUT strcat_type)  return   number
  
is
  
begin
      cs_ctx :
=  strcat_type(  null  );
      
return  ODCIConst.Success;
  
end ;

  member 
function  ODCIAggregateIterate(self  IN  OUT strcat_type,
                                       value 
IN   varchar2  )
  
return   number
  
is
  
begin
      
if  self.cat_string  is   null   then
         self.cat_string :
=  value;
      
end   if ;
      
return  ODCIConst.Success;
  
end ;

  member 
function  ODCIAggregateTerminate(self  IN  Out strcat_type,
                                         returnValue OUT 
varchar2 ,
                                         flags 
IN   number )
  
return   number
  
is
  
begin
      returnValue :
=  self.cat_string;
      
return  ODCIConst.Success;
  
end ;

  member 
function  ODCIAggregateMerge(self  IN  OUT strcat_type,
                                     ctx2 
IN  Out strcat_type)
  
return   number
  
is
  
begin
       if self.cat_string is null then
                   self.cat_string :=  ctx2.cat_string;
          end if;
       return  ODCIConst.Success;
  
end ;

end ;
/

-------------------

CREATE   OR   REPLACE   FUNCTION  sum_str(input  varchar2  )
RETURN   varchar2
PARALLEL_ENABLE AGGREGATE USING strcat_type;
/

-------最后查询语句:

select  code,sum_str(name), sum_str(b01) b01,sum_str(s01) ,sum_str(b02) b02,sum_str(s02)
from  javaeye  group   by  code  order   by  code
posted @ 2009-01-05 21:55 kebo 阅读(967) | 评论 (4)编辑 收藏
定义标注的样式,这个决定标注显示的方式,必须定义好
 1
 $package("com.bct.map");
 2 com.bct.map.EncoderMarkerStyle = {
 3     'bigEncoder':{
 4         graphicWidth:24,
 5         graphicHeight : 24,
 6         graphicXOffset : -12,
 7         graphicYOffset : -24,
 8         externalGraphic : "scripts/map/img/channel2.png"
 9     },
10     'smallEncoder':{
11         graphicWidth:16,
12         graphicHeight : 16,
13         graphicXOffset : -8,
14         graphicYOffset : -16,
15         externalGraphic : "scripts/map/img/channel.gif"
16     },
17     'selectStyle':{
18         pointerEvents: "visiblePainted",
19         border:"border:25 outset #ff88ff",
20         cursor: "pointer",
21         graphicWidth:24,
22         graphicHeight : 24,
23         graphicXOffset : -12,
24         graphicYOffset : -24,
25         externalGraphic : "scripts/map/img/channel2.png"    
26     },
27     styleMap: new OpenLayers.StyleMap({
28                     "select"new OpenLayers.Style({pointRadius: 24})
29     })
30 }

marker层,扩展vector层,通过point和style达到marker的效果
  1 $package("com.bct.map");
  2 $import("com.bct.map.EncoderMarkerStyle");
  3 com.bct.map.MarkerVectorLayer = OpenLayers.Class(OpenLayers.Layer.Vector,{
  4     /**
  5      * parameters
  6      * attribute filer对象
  7      */
  8     getFeatureByAttribute :function(attributes){
  9         var feature = null;
 10         for(var i=0;i<this.features.length; ++i){
 11             var attri = this.features[i].attributes;
 12             var find = false;
 13             for(var j in attributes){
 14                 if(attributes[j] == attri[j]){
 15                     find = true;
 16                 }
 17             }
 18             if(find){
 19                 return this.features[i]; 
 20             }            
 21         }
 22     
 23     },
 24     addEncorderFeature:function(encNode,location){
 25         if(encNode&&this.repetitiveCheck(encNode.id)){
 26             return;
 27         }
 28         var attributes = OpenLayers.Util.extend({}, encNode.attributes);
 29         var enc_point = new OpenLayers.Geometry.Point(location.lon,location.lat);
 30         var enc_Feature = new OpenLayers.Feature.Vector(enc_point,attributes,com.bct.map.EncoderMarkerStyle['smallEncoder']);
 31         this
.addFeatures([enc_Feature]);
 32         if(encNode.attributes['lon']&&encNode.attributes['lat']&&encNode.attributes['lon'].length>0){
 33             return;
 34         }
 35         this.updateChannel(encNode.id,location.lon,location.lat);
 36     },
 37     addDeptFeature:function(deptNode,location){
 38         if(deptNode&&this.repetitiveCheck(deptNode.id)){
 39             return;
 40         }
 41         var attributes = OpenLayers.Util.extend({}, deptNode.attributes);
 42         var enc_point = new OpenLayers.Geometry.Point(location.lon,location.lat);
 43         var enc_Feature = new OpenLayers.Feature.Vector(enc_point,attributes,com.bct.map.EncoderMarkerStyle['smallEncoder']);
 44         
 45         this.addFeatures([enc_Feature]);
 46         
 47     },
 48     repetitiveCheck:function(entity_id){
 49         if(this.getFeatureByAttribute({id:entity_id})){
 50             return true;
 51         }
 52         return false;
 53     },
 54     updateChannel:function(channel_id,lon,lat){
 55         Ext.Ajax.request({
 56                url: 'deviceVideoEncoder.do?method=updateLonlat&id='+channel_id+"&lon="+lon+"&lat="+lat
 57         });
 58     },
 59     channelMarkerClick:function() {
 60         var features = this.selectedFeatures;
 61         if(features.length >=0&&features[0]) {
 62             feature = features[0];            
 63             var treeNodeAttribute = feature.attributes;
 64             var vedioPopForm = new Ext.FormPanel({
 65                                    frame:true,
 66                                 labelAlign: 'top',
 67                                 bodyStyle:'padding:5px',
 68                                 width: 400,
 69                                 height:200,
 70                                 layout: 'fit',
 71                                 items:[{
 72                                             xtype:'fieldset',
 73                                             title: '摄像头信息',
 74                                             autoHeight:true,
 75                                             autoWidth:true,
 76                                             html:"<p><font color='red' size='2'>名称:"+treeNodeAttribute['text']
 77                                             +"</font></p><p><font color='red' size='2'>通道号:"+treeNodeAttribute['channelNumber']
 78                                             +"</font></p><p><font color='red' size='2'>设备名称:"+treeNodeAttribute['deviceunitName']
 79                                             +"</font></p><p><font color='red' size='2'>所属部门:"+treeNodeAttribute['deptName']
 80                                             +"</font></p><p><font color='red' size='2'>经纬度:"+treeNodeAttribute['lon']+","+treeNodeAttribute['lat']
 81                                     }]
 82             });
 83             var win = new Ext.Window({
 84                 width : 420,
 85                 height: 220,
 86                 items : vedioPopForm
 87             });
 88             win.show();            
 89         }
 90     },
 91     cartoonFeature :function(feature){
 92         this.drawFeature(feature,com.bct.map.EncoderMarkerStyle['bigEncoder']);
 93         var runner = new Ext.util.TaskRunner(1000);
 94         var task = {
 95             run:this.drawFeature,
 96             scope:this,
 97             args:[feature,com.bct.map.EncoderMarkerStyle['smallEncoder']],
 98             interval: 1000
 99         }
100         runner.start(task);
101     },
102     removeSelectFeature:function(){
103         var features = this.selectedFeatures;
104         for(var i=features.length-1; i>=0; i--) {
105             feature = features[i];
106             this.updateChannel(feature.attributes['id'],"","");
107         }
108         this.destroyFeatures(this.selectedFeatures);
109     },
110     monitorSelectFeature:function(){        
111         var features = this.selectedFeatures;
112         if(features.length >=0&&features[0]) {
113             feature = features[0];            
114             var treeNodeAttribute = feature.attributes;
115             var objId="mapAVShow"+treeNodeAttribute['id'];
116             var win = new Ext.Window({
117                 width : 420,
118                 height: 420,
119                 html:"<div id='mapEncoder' width='100%' height='100%'><object width='100%' height='100%' id='"+objId+"' classid='clsid:574B47E8-A366-4AB9-B2EA-57F145CA3780'></object></div>"
120             });            
121             win.show();
122             Ext.lib.Ajax.request('GET','channel.do?method=getSiteId&accept=json&id='+treeNodeAttribute['id'],
123                               {success: function(o){
124                                         var encoderObj;
125                                         encoderObj=Ext.util.JSON.decode(o.responseText);
126                                         $import("com.bct.monitor.mapAVShow");
127                                         var avshowObj=document.getElementById(objId);
128                                         var avshow=new com.bct.monitor.mapAVShow(avshowObj,
129                                         encoderObj[0].siteId,encoderObj[0].enCoderId,encoderObj[0].diveceUnitTypeId,'');
130                                         avshow.startVideo();
131                                         win.on("destroy",function del(){
132                                                          avshow.stopVideo();
133                                         });
134                                 }
135                               });             
136         }
137     }
138 });


posted @ 2008-09-04 14:12 kebo 阅读(3941) | 评论 (1)编辑 收藏

在项目进入性能测试阶段,终于爆发了sql运行缓慢,系统吞吐量下降,甚至一度出现oracle服务器cpu100%的情况。具体开发和测试人员报告情况,开始介入处理。

具体查找性能缓慢的过程略除。
发现一条sql运行缓慢。通过跟踪发现一下信息
select alias_p2.pendingid, alias_p2.workitemid, alias_p2.operationid, alias_p2.operationkey,

  2  alias_p2.title, alias_p2.sendercn, alias_p2.operatedes, alias_p2.pendingstate,

  3  alias_p2.parameter, alias_p2.createdate, alias_p2.deptname, alias_p2.completeddate ,

  4  alias_p2.openstate , alias_p2.name, alias_p2.processinstanceid, alias_p2.asset

  5   from ( select alias_p1.pendingid, alias_p1.workitemid, alias_p1.operationid,

  6   alias_p1.operationkey, alias_p1.title, alias_p1.sendercn, alias_p1.operatedes,

  7    alias_p1.pendingstate, alias_p1.parameter, alias_p1.createdate, alias_p1.deptname,

  8      alias_p1.completeddate , alias_p1.openstate , alias_p1.name, alias_p1.processinstanceid ,

  9        alias_p1.asset , rownum rn from(select alias_p.pendingid, alias_p.workitemid, alias_p.operationid,

 10        alias_p.operationkey, alias_p.title, alias_p.sendercn, alias_p.operatedes, alias_p.pendingstate,

 11        alias_p.parameter, alias_p.createdate, alias_p.deptname, alias_p.completeddate , alias_p.openstate ,

 12         pd.name, w.processinstanceid , eam_db.concatassetname( alias_p.operationkey, alias_p.operationid )

 13          asset from WF_Pending alias_p, WF_WorkItem w, WF_ProcessDefinition pd, WF_ProcessInstance pi

 14          where alias_p.ownerid='qinxue'   and alias_p.pendingstate in(0,3,5,7,9,10,11,12)

 15            and (alias_p.deptname=' 审控部信息处 ' or alias_p.deptname='' or alias_p.deptname is null)

 16            and w.workitemid = alias_p.workitemid   and pi.processinstanceid = w.processinstanceid

 17  and pi.completeddate is null   and pd.processdefinitionid = w.processdefinitionid  order by alias_p.createdate desc) alias_p1 where rownum <=10)

alias_p2 where rn>=1;

 

已选择 10 行。

 

 

执行计划

----------------------------------------------------------

   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=10 Card=1 Bytes=2507

          )

 

   1    0   VIEW (Cost=10 Card=1 Bytes=2507)

   2    1     COUNT (STOPKEY)

   3    2       VIEW (Cost=10 Card=1 Bytes=2494)

   4    3         SORT (ORDER BY STOPKEY) (Cost=10 Card=1 Bytes=167)

   5    4           NESTED LOOPS (Cost=8 Card=1 Bytes=167)

   6    5             NESTED LOOPS (Cost=7 Card=1 Bytes=162)

   7    6               NESTED LOOPS (Cost=6 Card=1 Bytes=134)

   8    7                 TABLE ACCESS (FULL) OF 'WF_PENDING' (Cost=5

          Card=1 Bytes=111)

 

   9    7                 TABLE ACCESS (BY INDEX ROWID) OF 'WF_WORKITE

          M' (Cost=1 Card=3 Bytes=69)

 

  10    9                   INDEX (UNIQUE SCAN) OF 'SYS_C003694' (UNIQ

          UE)

 

  11    6               TABLE ACCESS (BY INDEX ROWID) OF 'WF_PROCESSDE

          FINITION' (Cost=1 Card=1 Bytes=28)

 

  12   11                 INDEX (UNIQUE SCAN) OF 'SYS_C003684' (UNIQUE

          )

 

  13    5             TABLE ACCESS (BY INDEX ROWID) OF 'WF_PROCESSINST

          ANCE' (Cost=1 Card=1 Bytes=5)

 

  14   13               INDEX (UNIQUE SCAN) OF 'SYS_C003662' (UNIQUE)

 

 

 

 

统计信息

----------------------------------------------------------

        314  recursive calls

          0  db block gets

      29433  consistent gets

          0  physical reads

          0  redo size

       2153  bytes sent via SQL*Net to client

        372  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

        101  sorts (memory)

          0  sorts (disk)

         10  rows processed

其中一致读达到近3万次,关联调用出现314次。排序数值也非常多,显然第一目标是把这两个数据降下来。
通过进一步的分析。发现出现这些问题的主要原因是调用eam_db.concatassetname( alias_p.operationkey, alias_p.operationid )这个包。
开始考虑直接在sql外层做关联,不用function来实现。利用聚集函数来合并数据。
着手建立:

聚集函数: CREATE OR REPLACE FUNCTION F_ASSETLINK(P_STR VARCHAR2) RETURN VARCHAR2
AGGREGATE USING asset_link;


----------------------
创建type:CREATE OR REPLACE TYPE ASSET_LINK AS OBJECT (
STR VARCHAR2(30000),
STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT ASSET_LINK) RETURN NUMBER,
MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT ASSET_LINK, VALUE IN VARCHAR2) RETURN NUMBER,
MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN ASSET_LINK, RETURNVALUE OUT VARCHAR2, FLAGS IN NUMBER) RETURN NUMBER,
MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT ASSET_LINK, CTX2 IN ASSET_LINK) RETURN NUMBER
)
------------------------------------------------------

创建type body:CREATE OR REPLACE TYPE BODY ASSET_LINK IS
STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT ASSET_LINK) RETURN NUMBER IS
BEGIN
SCTX := ASSET_LINK(NULL);
RETURN ODCICONST.SUCCESS;
END;
MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT ASSET_LINK, VALUE IN VARCHAR2) RETURN NUMBER IS
BEGIN
SELF.STR := SELF.STR ||','|| VALUE;
RETURN ODCICONST.SUCCESS;
END;
MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN ASSET_LINK, RETURNVALUE OUT VARCHAR2, FLAGS IN NUMBER) RETURN NUMBER IS
BEGIN
RETURNVALUE := SELF.STR;
RETURN ODCICONST.SUCCESS;
END;
MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT ASSET_LINK, CTX2 IN ASSET_LINK) RETURN NUMBER IS
BEGIN
NULL;
RETURN ODCICONST.SUCCESS;
END;
END;
调整sql如下:
select alias_p.pendingid, alias_p.workitemid, alias_p.operationid,
   alias_p.operationkey, alias_p.title, alias_p.sendercn, alias_p.operatedes, alias_p.pendingstate,
   alias_p.parameter, alias_p.createdate, alias_p.deptname, alias_p.completeddate , alias_p.openstate ,
   pd.name, w.processinstanceid
   --,T.ASSETCLASS3  ASSET  
   ,f_assetlink(d3.typename) ASSET
   --,eam_db.concatassetname( alias_p.operationkey, alias_p.operationid )  asset
   from WF_Pending alias_p, WF_WorkItem w,
   WF_ProcessDefinition pd, WF_ProcessInstance pi
   , tb_asset_dizhiyihao T,dic_app_wfconfig wfc,dic_app_assettype3 d3
   where alias_p.ownerid='qinxue'  
   and alias_p.pendingstate in(0,3,5,7,9,10,11,12)
   and (alias_p.deptname='审控部信息处' or alias_p.deptname='' or alias_p.deptname is null)
   and w.workitemid = alias_p.workitemid  
   and pi.processinstanceid = w.processinstanceid
   and pi.completeddate is null  
   and pd.processdefinitionid = w.processdefinitionid
   AND    t.pk_businessid = alias_p.operationid
          and alias_p.operationkey = wfc.memo_1
          and wfc.wfconfig_code = t.wfconfig_code
   and t.assetclass3 = d3.assettype3_id
   group by alias_p.pendingid, alias_p.workitemid, alias_p.operationid,
   alias_p.operationkey, alias_p.title, alias_p.sendercn, alias_p.operatedes, alias_p.pendingstate,
   alias_p.parameter, alias_p.createdate, alias_p.deptname, alias_p.completeddate , alias_p.openstate ,
   pd.name, w.processinstanceid
   order by alias_p.createdate desc
得到统计数据如下:
C:\Documents and Settings\ibm>sqlplus /nolog

SQL*Plus: Release 10.2.0.1.0 - Production on 星期一 9月 10 19:27:33 2007

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

SQL> conn jic/jic@name
已连接。
SQL> set autotrace traceonly
SQL> select alias_p.pendingid, alias_p.workitemid, alias_p.operationid,
  2     alias_p.operationkey, alias_p.title, alias_p.sendercn, alias_p.operatedes, alias_p.pendingstate,
  3     alias_p.parameter, alias_p.createdate, alias_p.deptname, alias_p.completeddate , alias_p.openstate ,
  4     pd.name, w.processinstanceid
  5     --,T.ASSETCLASS3  ASSET
  6     ,f_assetlink(d3.typename) ASSET
  7     --,eam_db.concatassetname( alias_p.operationkey, alias_p.operationid )  asset
  8     from WF_Pending alias_p, WF_WorkItem w,
  9     WF_ProcessDefinition pd, WF_ProcessInstance pi
 10     , tb_asset_dizhiyihao T,dic_app_wfconfig wfc,dic_app_assettype3 d3
 11     where alias_p.ownerid='qinxue'
 12     and alias_p.pendingstate in(0,3,5,7,9,10,11,12)
 13     and (alias_p.deptname='审控部信息处' or alias_p.deptname='' or alias_p.deptname is null)
 14     and w.workitemid = alias_p.workitemid
 15     and pi.processinstanceid = w.processinstanceid
 16     and pi.completeddate is null
 17     and pd.processdefinitionid = w.processdefinitionid
 18     AND    t.pk_businessid = alias_p.operationid
 19            and alias_p.operationkey = wfc.memo_1
 20            and wfc.wfconfig_code = t.wfconfig_code
 21     and t.assetclass3 = d3.assettype3_id
 22     group by alias_p.pendingid, alias_p.workitemid, alias_p.operationid,
 23     alias_p.operationkey, alias_p.title, alias_p.sendercn, alias_p.operatedes, alias_p.pendingstate,
 24     alias_p.parameter, alias_p.createdate, alias_p.deptname, alias_p.completeddate , alias_p.openstate ,
 25     pd.name, w.processinstanceid
 26     order by alias_p.createdate desc;

已选择30行。


执行计划
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE (Cost=19 Card=1 Bytes=205)
   1    0   SORT (GROUP BY) (Cost=19 Card=1 Bytes=205)
   2    1     NESTED LOOPS (Cost=17 Card=1 Bytes=205)
   3    2       HASH JOIN (Cost=16 Card=1 Bytes=191)
   4    3         HASH JOIN (Cost=11 Card=1 Bytes=183)
   5    4           NESTED LOOPS (Cost=8 Card=1 Bytes=167)
   6    5             NESTED LOOPS (Cost=7 Card=1 Bytes=139)
   7    6               NESTED LOOPS (Cost=6 Card=1 Bytes=134)
   8    7                 TABLE ACCESS (FULL) OF 'WF_PENDING' (Cost=5
          Card=1 Bytes=111)

   9    7                 TABLE ACCESS (BY INDEX ROWID) OF 'WF_WORKITE
          M' (Cost=1 Card=1 Bytes=23)

  10    9                   INDEX (UNIQUE SCAN) OF 'SYS_C004347' (UNIQ
          UE)

  11    6               TABLE ACCESS (BY INDEX ROWID) OF 'WF_PROCESSIN
          STANCE' (Cost=1 Card=1 Bytes=5)

  12   11                 INDEX (UNIQUE SCAN) OF 'SYS_C004334' (UNIQUE
          )

  13    5             TABLE ACCESS (BY INDEX ROWID) OF 'WF_PROCESSDEFI
          NITION' (Cost=1 Card=1 Bytes=28)

  14   13               INDEX (UNIQUE SCAN) OF 'SYS_C004329' (UNIQUE)
  15    4           TABLE ACCESS (FULL) OF 'DIC_APP_WFCONFIG' (Cost=2
          Card=24 Bytes=384)

  16    3         TABLE ACCESS (FULL) OF 'TB_ASSET_DIZHIYIHAO' (Cost=4
           Card=310 Bytes=2480)

  17    2       TABLE ACCESS (BY INDEX ROWID) OF 'DIC_APP_ASSETTYPE3'
          (Cost=1 Card=1 Bytes=14)

  18   17         INDEX (UNIQUE SCAN) OF 'PK_DIC_APP_ASSETTYPE3' (UNIQ
          UE)

 

 

统计信息
----------------------------------------------------------
          6  recursive calls
          0  db block gets
        847  consistent gets
          0  physical reads
          0  redo size
       4102  bytes sent via SQL*Net to client
        383  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)

其中排序由101变为1次
一致读降为847。下降非常客观
关联调用仅有6次。
此sql性能优化非常可观。至此优化结束:)

posted @ 2007-09-10 19:35 kebo 阅读(461) | 评论 (0)编辑 收藏
数据库迁移过程中需要目标数据库和原数据库结构相同和数据是最新。
为了保持最新数据和快速切换就不可以利用exp/imp的方式,利用data guard则有平台的问题。
在这种情况下,可以利用on prebuilt table选项创建mv。然后同步运行一段时间。一次切换,删除
mv,这种情况下可以保持同名的表。mv删除。达到数据同步,切换的目标。
posted @ 2007-08-14 15:32 kebo 阅读(227) | 评论 (0)编辑 收藏
select z.a,z.b,z.c from (select lag(t.a,2)over(order by t.a) pp_val, lag(t.a,1)over(order by t.a) p_val, t.a, lead(t.a,1)over(order by t.a) n_val, lead(t.a,2)over(order by t.a) nn_val, t.b,t.c from test2 t) z where z.a = '1' and ((z.p_val = '1' and z.pp_val = '1') or (z.p_val = '1' and z.n_val = '1') or (z.n_val = '1' and z.nn_val = '1'));
posted @ 2007-07-17 16:55 kebo 阅读(230) | 评论 (0)编辑 收藏
查询结果xml化: select dbms_xmlquery.getXML(' select * from test')from dual; 表的历史记录:执行:begin dbms_wm.enableversioning('tablename','VIEW_WO_OVERWRITE') 则对这个表的cud操作都会记录历史,这个在系统中做历史再好不过了。 还有终于被tom说明:分析函数原来就是矩阵运算,呵呵,终于知道这类函数的数学原理了,呵呵,真爽,总算知道怎么理解了。 还有宝贝儿遇到新项目,需要很深的会计知识了,还被老板乱说,导致不好工作,希望她不要烦恼,开心工作
posted @ 2007-07-11 00:15 kebo 阅读(264) | 评论 (0)编辑 收藏

配置:server.modules 
server.modules              = (
                                "mod_rewrite",
                                "mod_redirect",
                                "mod_access",
                                "mod_status",
                                "mod_scgi",
                                "mod_accesslog" )
配置
index-file.names            = ( "index.php", "index.html",
                                            "index.htm", "default.htm" )
#### accesslog module
accesslog.filename          = "c:/depot/log/access.log"
static-file.exclude-extensions = ( ".php", ".pl", ".fcgi",".scgi" )       标红的需要加上

## bind to port (default: 80)
server.port                = 8080------------------访问端口,我设置8080

## error-handler for status 404
server.error-handler-404   = "/dispatch.scgi"
-----------------------------------------------
scgi.server = ("dispatch.scgi" => ((
"host" => "127.0.0.1",
"port" => 9999,
"check-local" => "disable"
)) )

scgi.debug=3

status.status-url = "/server-status"
status.config-url = "/server-config"

-------------------------------------
## server.virtual-* options
server.document-root        = "c:/depot/public"
记得这个需要设置到public目录,不然按默认的rails生成的文档一些东西访问不来的
-----------------------------------------------------------------------------------------------------
需要注意的是你开发的程序需要放在c盘下,不然找不到config/scgi.yaml这个文件
然后lighttpd必须装在c盘下(当前版本下1.4.11)

posted @ 2007-01-02 21:08 kebo 阅读(553) | 评论 (0)编辑 收藏
今天给数据库执行@spcreate.sql老是出
SP2-0734:unknown command beginning "spcreate.s..." - rest of line ignored.
郁闷坏了。经过一番折腾原来是
solution Description:
 =====================
You need to enter a valid SQL*Plus command.
In this case, you cannot start svrmgrl from within SQL*Plus,
you have to start svrmgrl from the command prompt.
This error will also occur when trying to execute a
the @ symbol is mapped to the key 'Kill' from the user's keyboard.
The way to find out the current keyboard mapping in a unix environment is using the command 'stty -a'.
The way to correct problem is to map 'Kill' to some other keyboard symbol.
The command example would be 'stty kill ^U'.
Having remapped the key you would then log into SQL*Plus and execute script.
 -------------------------------纪念一下
如果出现空行报错的话 记得执行:
SET SQLBLANKLINES ON
posted @ 2006-12-27 22:24 kebo 阅读(515) | 评论 (0)编辑 收藏
呵呵,最近吵架比较多,我们项目和另公司合作,经常出现两家吵架的事件,小弟不信参与其中。通过具体实践,发现我现在很容易发现别人说话的漏洞。然后常常质问对方大哥无法可说,呵呵,痛快。 我想这是 我比较最近比较喜欢高手们争论话题的帖子,建议想提高吵架水平的人多学学(别用在mm身上^^)
posted @ 2006-11-01 04:11 kebo 阅读(337) | 评论 (0)编辑 收藏
  今天听了下oracle讲座,一个感受,以后不敢操作数据库了,发现对大多数数据库命令产生的后果和影响都不是很清楚。想起以前切换双机

的时候也出现eygle说的问题,然来真的对数据库基础知识预备不足啊。感觉以前真是可以称为“虎胆”哦。难怪老幕以前佩服我!!!卡卡卡。

恩,感觉oracle入门现在都够不上,不敢再给别人解决问题:)免得惹笑话。梳理了一下,估计也就对sql,集合的理解熟悉点,有点把我哦。低

调,低调......学习学习......
posted @ 2006-10-03 01:43 kebo 阅读(472) | 评论 (0)编辑 收藏
一个比较好的缓存中间件memcached。可以用做系统的各种缓存。支持分布式。使用方便。网上有很多介绍。多是linux&unix版。现在也有window32版本了。方便实现SNA架构。在网站架构上用处多多。
http://jehiah.com/projects/memcached-win32/
启动,使用都是比较方便。可以到http://www.danga.com/memcached/下各种客户api。下载的client有使用test。一看就明白。
呵呵,真实好东西。

-----------------------

呵呵,发现plone中也用它做缓存了.

--------------------------
前几天使用了一下,发现在win下面容易出现占用cpu 100%的情况,不知道什么原因,有谁知道?没有别的什么操作,insert/get操作而已.

查找中.......

奇怪,plone中为什么不出现!!!!

posted @ 2006-08-11 00:03 kebo 阅读(534) | 评论 (1)编辑 收藏
早上9点的飞机,昨天晚上电话本来有很多话想说。最后竟木木的什么也没说。
想象着空中的佳佳.......
想象着她忙忙碌碌的样子......
小猪开始了新的生活了......
不知道什么时候才可以再见到......
晚上等电话了......盼望着她尽快安定下来......
希望她在异国他乡平平安安,健健康康的.
posted @ 2006-07-30 16:52 kebo 阅读(305) | 评论 (0)编辑 收藏
佳佳要飞的日子越来越近了,我已经感到了一丝丝残酷了。一直一直麻痹自己。
posted @ 2006-07-19 10:29 kebo 阅读(300) | 评论 (0)编辑 收藏
劫财劫色死了,哎,可怜的两个小家伙,悲哀中!!!!!!!!
都是你的主人没有好好照顾你,投胎时别在做龟了
posted @ 2006-07-14 23:50 kebo 阅读(228) | 评论 (0)编辑 收藏
在实际的软件开发过程中,我们常常可以看到这样的情形:一方面是开发人员指责需求人员不懂用户的真正的需求,讲解的需求和最后客户的要求想去甚远或指责需求只是客户的传声筒,拿到的需求不整理一下,就丢给开发人员开始做。另一方面是需求骂开发人员笨,对需求一点不理解,只懂机械的做。
这样的情况,常常导致系统不停的修改,bug不断。客户,需求,开发都筋疲力尽,然后就是项目延期,直到死亡。

       这样的情况,相信每个做企业系统的开发人员都遇到过,一提起这样的问题,大家只有摆脑袋,喃喃到“简直就是恶梦,太难了”
^_^(希望不要勾起你痛苦的回忆)

     其实出现这样的情况,大部分是应为需求人员和开发人员对问题的思考模式不同导致的。在业务语言和业务规则向计算机语言和系统模型转换之间有一个的过程。这个过程必须有一个衔接的人和模式来做这件事情。
     这个角色需要精通业务概念和系统实现方式。然后运用分析模式方式把业务概念转换为系统模型概念。需求人员理解业务总是自觉不自觉的把一些他们认为是常识的思维放进去,但是这部分只是不会出现在需求文档中。这就需要分析人员不断的和他需求聊天,不但的询问挖掘出来。然后写入概要设计和详细涉及文档中。
还有需求人员往往在写程序需要处理的逻辑的时候会不自觉的融入人类的思考模式,在其中加入一些智能判断,但是这部分逻辑往往用计算机实现比较困难。这就需要分析人员的洞察能力,找到客户的真正需求,然后转换方式来实现。

      例如:有这样一个需求是分析业务数据的。表中有27列,其中a,b,c,d,e,g,p,q,y,z为判断过程中所涉及到的数据项,各项之间的关系为:b列中的传输系统速决定z列中的最大时隙编号。如2。5G系统对应的最大时隙编号为16或8(保护)。10g系统对应的最大时隙编号为64或32(保护)。
      D列为与C列中站点相领的前向站点,e列为与c列中站点相领的后向站点。
      G列与p列或q列为--对应关系,即唯一的一个端口对应当前传输系统的一个时隙。
      p列和q列在一行中不同时出现。即同时只有前项时隙或后项时隙,两者不同时存在。
      y列为版本号,1代表设计版,2代表工程版。当g列中相同的两个端口对应的z列不同的时隙时,以Y列为2的为准。

 
(一下为客户平时所用的人工分析方式)
分析过程:
1)首先根据系统名称中的2。5G可以判断出Z列的最大编号为16或8,对z列进行观察后得出最大编号为8。即存在8个时隙,编号分别为1~8.
2)  将c列为“杭环城北路”站点下所有z列的数据观察后可看出z列无5,6两个时隙,于是初步判断时隙在该站点为穿通。
3)c列为“杭环城北路”所对应的D列前向站点为“衢州网通”。在z列中查找所有c列为“衢州网通”所对应的时隙,发现5,6两个时隙编号,且p,q两列中仅q列有数据,说明该时隙为后向时隙。可得出5,6两个时隙的起始站点为“衢州网通”。因该时隙对应的Y列均有1,2两个数值,根据“各项间关系”,仅取Y列数值为2的数据为有效数据。
4)c列为“杭环城北路”所对应的e列后向站点为“宁波网通”。在z列中查找所有c列为“宁波网通”所对应的时隙,发现5,6两个时隙编号。且p,q两列仅p列有数据,说明该时隙为前向时隙,可得出5,6两个时隙的终止站点为“宁波网通”。因该时隙对应的Y列均有1,2两个数据,根据各项间干系,取Y列为2的数据为有效数据。
综合判断1~4不的判断过程,可以得出结论:编号为5,6的两个时隙以“衢州网通”为起点,途径“杭环城北路”以“宁波网通”为终点


可以看到这个分析过程很不利于计算机话
(一下为我的分析方式)



------推荐的方式



-------其他


(未完待续........)
posted @ 2006-07-01 11:58 kebo 阅读(392) | 评论 (0)编辑 收藏
     与人为善,种善因,得善果.
懂得说谢谢,会说谢谢,对人际关系很重要。
今天碰到一个刚毕业的小孩,给他教东西的时候,竟没有听到一句感谢的话.
郁闷噢
posted @ 2006-06-23 23:52 kebo 阅读(286) | 评论 (0)编辑 收藏
     昨天晚上做了一个奇怪的梦,梦到被一条蛇咬了一下。清楚的记得是手指被咬的,竟痛醒了,醒了还感到手指隐隐做痛

然后今天八卦的查了一下,周公解梦如下:

蛇化龙得贵人助, 蛇咬人主得大财, 蛇多者主阴司事, 鹤上天主小口灾, 鹦鹉唤人主口舌, 燕子至有造客来, 

呵呵,难道是真的?

然后今天很奇怪,一把黄杨木梳也折断了.......可惜了,跟我两年了。

posted @ 2006-06-19 19:42 kebo 阅读(285) | 评论 (0)编辑 收藏

xxx购物超市折扣规则描述:
 1.任何顾客的购物总价大于1000元则享受9折优惠
 2.vip顾客的时候无论购物总价是多少享受7折优惠
 3.普通顾客没有特别政策,另有规定的除外
 4.白金顾客享受8.5优惠,无论购物总价多少。
 5.黄金顾客享受9折优惠无论购物总价多少。
 6.任何顾客所够商品中包含tv的时候,优惠后再优惠9.5折
这个user case 是自己想的,不是很复杂

对应的规则文件

#created on: 2006-6-10
#created by: kebo
package com.sample

import com.sample.Person;
import com.sample.ShopCat;
import com.sample.Product;
import com.sample.Helper;


rule "PRICE_DISCOUT"
 salience 2
 no-loop true
 when
  p:Person(c:cat->(c.getTotalPrice()>1000),discout==1)     
 then
  p.setDiscout(0.9);
  modify(p); 
end

rule "VIP"
 salience 3
 no-loop true
 when
  p:Person(type==Person.VIP,discout==1)     
 then
  p.setDiscout(0.7);
  modify(p); 
end

rule "COMMON"
 salience 3
 no-loop true
 when
  p:Person(type==Person.COMMON,discout==1)     
 then
  p.setDiscout(1);
  modify(p);
end

rule "PLATINA"
 salience 3
 no-loop true
 when
  p:Person(type==Person.PLATINA,discout==1)     
 then
  p.setDiscout(0.85); 
  modify(p);
end

rule "GOLD"
 salience 3
 no-loop true
 when
  p:Person(type==Person.GOLD,discout==1)     
 then  
  p.setDiscout(0.9); 
  modify(p);
end

rule "CONTAIN TV"
 salience 1
 no-loop true
 when
  p:Person(c:cat->(Helper.isContainType(c.getProducts(),Product.TV)))     
 then
  p.setDiscout(0.95 * p.getDiscout());
  modify(p);
end

解决rule的冲突还是比较麻烦的。

为什么blogjava没有code着色功能呢?代码贴上去一点都不好看,唉!

 

 

posted @ 2006-06-13 01:19 kebo 阅读(2036) | 评论 (0)编辑 收藏
     今天去客户处开会,让我看到了政治。
人与人的关系真实复杂啊!真的是看到因一句话不小心而引火烧身例子,本来那个同事是可以安枕无优的,最后怎一个
惨字了得。记住,以为戒。

     还有一点感受,做信息系统,最重要的是什么?
功能?模块?速度?是否漂亮?是否有好的架构?
其实这些都是次要的,真正重要的是如何保证“信息的正确性”
数据错误,数据表达的不完整,数据不全。这些东西决定了一个
系统的价值。如果一个系统没有做到这点,那么这个系统就
毫无价值。依据这些信息做的决策会死人的。
没有99%,只有100%
posted @ 2006-06-08 22:41 kebo 阅读(232) | 评论 (0)编辑 收藏
       '"下辈子如果我还记得你"马郁诠释的非常棒
淡淡的忧愁,淡淡的思念还有对往日情人的深深怀念,
对昔日山盟海誓的追忆.和不能和恋人在一起的丝丝痛楚..
很好听
这辈子你是否还记得我?
posted @ 2006-06-07 14:21 kebo 阅读(310) | 评论 (1)编辑 收藏
今天的面试经历,,瞒搞笑的..
聊到最后,,我听着有些纳闷,,然后问他招聘什么职位..答'"'测试工程师"
晕倒,,我告他'"'我做开发的"
答'"'我们测试也开发,,也是开发工程师"
我说'''对不起,,我对专门做测试没兴趣"
然后散

郁闷..浪费时间

前台mm不错..很性感的



      下午再面一家,问了一个问题,一门动态语言,没有调试器,现在程序出错了,
但是没有给出任何错误信息,
或者错误信息就提示错误,代码
行数有3k多,现在你怎么快速的定位错误行?
靠,这个有什么办法?
我答'"'先预测错误的问题,然后输出调试"
告我'"'不是,,让我回去想想"
然后说这个问题没有答出来,不能给我期望的工资(ft,,难道要答出所有的问题吗?)
我说'"'不会吧,,面试的人能答出所有的问题吗?"
告我'"'这个问题很简单"
切!!,难道真的简单?
posted @ 2006-06-06 15:46 kebo 阅读(262) | 评论 (0)编辑 收藏
      七十年前,一个年轻的矿工马上要和新娘举行婚礼,婚礼前最后一次下井,但发生了塌方,矿工永远没有回来。新娘子不相信她的爱人就此离她而去,苦苦等了七十年。前些日子重新整理矿井,在坑道深处一汪积水中发现一具尸体,正是七十年前被埋在井里的新郎。由于没有空气,又浸泡在饱含矿物质的水中,他仍如七十年前一般年轻。新娘子已成为白发苍苍的老妪。她扑在心爱的人身上痛哭。她做了一个决定,继续与爱人完成他们的婚礼。那一幕太动人了:八十多岁的新娘子一身盛装,洁白如雪。头发也如雪。她的爱人,依然那么年轻,闭着眼睛躺在一驾马车上。婚礼与葬礼同时举行。多少人都落泪了。
这个是什么呢?!!!!!!!!!!!!!!!!!!!!!!!!
posted @ 2006-06-02 14:21 kebo 阅读(301) | 评论 (2)编辑 收藏
     刻苦钻研主机(linu$unix)知识.和oracle数据库知识
争取年底主机达到一般主机工程师水平
数据库水平要达到中级dba水平

     java方面继续研究lucene和drools知识.为将来做架构扩大知识面和选择面

web方面主要对ajax只是保持一定的关注.特别是关注ui方面的进展.服务端继续试用dwr(已经很好用了.)
关注ajax对传统web开发模式的影响.

  唉,看来算法方面还是放一放了.
posted @ 2006-05-29 16:26 kebo 阅读(213) | 评论 (0)编辑 收藏

        在企业应用中报表生成是一个无法回避的问题,对格式的要求也是多种多样的
特别是excel的,直接生成需要自己一行一行的填写,麻烦之极.
利用excel模板生成excel文件.省去直接写代码生成报表之苦,还可以任意设计报表样式
免去一格一格填写之苦,赶紧使用吧:)
目前基本实现了简单报表的生成的需要
支持循环和条件判断
控制语法如下
#if:exp
eg:
#for:#{employee}#
#for:exp
#end#exp
#elsif:exp
表达式语法为:#{xxx.xxx}

其中循环中的每个元素用item表达.支持普通对象,map,list,javabean,如同jstl

目前没有实现的功能嵌套语句,不支持控制语句的嵌套(报表中应该不需要如此复杂的功能)和pdf版

基本使用方法为:
        1:把kebo-0.1.jar
              commons-jexl-1.0.jar,
              commons-logging.jar,
              jxl.jar
              log4j-1.2.9.jar放入classpath,配置好log4j.xml(也可不配置)
        2:代码如下:
        OutputStream writer = new FileOutputStream("Book2.xls");//生成的报表文件
  InputStream is = new FileInputStream("Book1.xls");//报表模板文件
  
  TemplateEngine engine = EngineFactory.createEngine("excel");//创建excel报表引擎
  engine.assertObject("modul",modul);//加入数据
  Students s = new Students();
  s.setName("小东");
  s.setAge("23");
  
  engine.assertObject("student",s);
  engine.assertObject("employee",modul.get("employee"));
  
  engine.evaluate(is,writer);//执行转换,生成报表
如果各位同学在使用当中有问题,请及时反馈给我,谢谢.mail:huang.kebo@gmail.com
源码编译,导入到eclipse中,直接ant目录下的build.xml即可

http://www.blogjava.net/Files/kebo/ReportTemplateEngine.rar

网速慢的朋友,留下mail.发给你们

posted @ 2006-05-23 11:00 kebo 阅读(2788) | 评论 (6)编辑 收藏
江南白衣同学聚集一群热心的人们,推出一个Pragmatic企业开发方方面面的最佳实践. 很值得用spring开发,j2ee应用的同学们参考参考. 项目主页:www.springside.org.cn 在实例中你不仅可以学到spring的最佳实践 还可以学到目前流行的开源工具的使用方法和整合方法 最重要的是你可以真真切切的感受到"简单,适用"这样的理念怎么指导项目开发 (j2ee开发往往被弄的很复杂,即使一些人在使用spring的时候也是这样).
posted @ 2006-04-18 10:38 kebo 阅读(1299) | 评论 (1)编辑 收藏
 这几天很郁闷,公司弄来一台IBM小机.让我装系统.在公司的时候用DHCP给分配IP,安装好系统和oracle后,拉到现场设置静态ip后就是无法联网
ip怎么设置也不正确。经检查网线和交换机都是正常的。同样的ip和网线用本是没有任何问题的。最后只好找公司的主机工程师来调试了。来了也是设置半天也没有成功,当中还问过ibm的工程师,也没有搞定。哎,把我们俩给郁闷的。最后同事找了一个朋友问,一步一步地做,才发现经过DHCP后在按一般的步骤设置是不可以的,必须重新设置网卡的状态,设置ip后重起(?)。经过3个多小时的折腾,网络终于调试正常。记blog,留为纪念
posted @ 2006-04-14 15:06 kebo 阅读(1340) | 评论 (1)编辑 收藏
sql
(转)



-- 逻辑读多的SQL
select * from (select buffer_gets, sql_text
from v$sqlarea
where buffer_gets > 500000
order by buffer_gets desc) where rownum<=30;

-- 执行次数多的SQL
select sql_text,executions from
(select sql_text,executions from v$sqlarea order by executions desc)
where rownum<81;

-- 读硬盘多的SQL
select sql_text,disk_reads from
(select sql_text,disk_reads from v$sqlarea order by disk_reads desc)
where rownum<21;

-- 排序多的SQL
select sql_text,sorts from
(select sql_text,sorts from v$sqlarea order by sorts desc)
where rownum<21;

--分析的次数太多,执行的次数太少,要用绑变量的方法来写sql
set pagesize 600;
set linesize 120;
select substr(sql_text,1,80) "sql", count(*), sum(executions) "totexecs"
from v$sqlarea
where executions < 5
group by substr(sql_text,1,80)
having count(*) > 30
order by 2;
posted @ 2006-03-29 13:41 kebo 阅读(277) | 评论 (0)编辑 收藏
SELECT * FROM ( SELECT row_.*, rownum rownum_ FROM (...... ) row_ WHERE rownum <= ?) WHERE rownum_ > ?
posted @ 2006-01-30 12:00 kebo 阅读(286) | 评论 (0)编辑 收藏
      前段时间在项目中一个模块中用了ajax技术实现了一些功能.由于没有使用一些ajax框架,用自己封装的的一些js脚本实现的,开始写的时候就非常痛苦,脚本的调试太麻烦,好在修改的也方便,还算比较快的实现了功能需求.使用感受也比较酷.没有使用常用的js+xml实现,而是直接在服务端把简单的javabean转换为js对象
然后返回给前台,前台用eval就方便的拿到的js对象.比较简单快捷.少了前台的xml解析.
      但现在还过来看这些写的脚本和页面,非常难看懂,项目组的人也说看起来比较困难.而且现在要修改一些东西的话,也比较难找到地方.
     感受用ajax,必须有一个成熟的框架,把一些基础的东西封装好,只有这样,隐藏具体的数据转换和页面生成
但是也试用了一些开源的ajax框架,还没找到满意,方便的框架.现在的ajax框架满天飞,希望06年有一个框架可以脱颖而出.
posted @ 2006-01-23 20:21 kebo 阅读(286) | 评论 (0)编辑 收藏
前言

  正则表达式是烦琐的,但是强大的,学会之后的应用会让你除了提高效率外,会给你带来绝对的成就感。只要认真去阅读这些资料,加上应用的时候进行一定的参考,掌握正则表达式不是问题。

索引

1. 引子
  目前,正则表达式已经在很多软件中得到广泛的应用,包括*nix(Linux, Unix等),HP等操作系统,PHP,C#,Java等开发环境,以及很多的应用软件中,都可以看到正则表达式的影子。

  正则表达式的使用,可以通过简单的办法来实现强大的功能。为了简单有效而又不失强大,造成了正则表达式代码的难度较大,学习起来也不是很容易,所以需要付出一些努力才行,入门之后参照一定的参考,使用起来还是比较简单有效的。

  例子: ^.+@.+\\..+$

  这样的代码曾经多次把我自己给吓退过。可能很多人也是被这样的代码给吓跑的吧。继续阅读本文将让你也可以自由应用这样的代码。

  注意:这里的第7部分跟前面的内容看起来似乎有些重复,目的是把前面表格里的部分重新描述了一次,目的是让这些内容更容易理解。
2. 正则表达式的历史

  正则表达式的“祖先”可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。

  1956 年, 一位叫 Stephen Kleene 的数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题为“神经网事件的表示法”的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为“正则集的代数”的表达式,因此采用“正则表达式”这个术语。

  随后,发现可以将这一工作应用于使用 Ken Thompson 的计算搜索算法的一些早期研究,Ken Thompson 是 Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的 qed 编辑器。

  如他们所说,剩下的就是众所周知的历史了。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。
3. 正则表达式定义

  正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。

  列目录时, dir *.txt或ls *.txt中的*.txt就不是一个正则表达式,因为这里*与正则式的*的含义是不同的。

  正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

  3.1 普通字符

  由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符,所有数字,所有标点符号以及一些符号。

  3.2 非打印字符

字符 含义
\cx 匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。

 
  3.3 特殊字符

  所谓特殊字符,就是一些有特殊含义的字符,如上面说的"*.txt"中的*,简单的说就是表示任何字符串的意思。如果要查找文件名中有*的文件,则需要对*进行转义,即在其前加一个\。ls \*.txt。正则表达式有以下特殊字符。

特别字符 说明
$ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。
( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。
* 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。
+ 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。
. 匹配除换行符 \n之外的任何单字符。要匹配 .,请使用 \。
[ 标记一个中括号表达式的开始。要匹配 [,请使用 \[。
? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。
\ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。
^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。
{ 标记限定符表达式的开始。要匹配 {,请使用 \{。
| 指明两项之间的一个选择。要匹配 |,请使用 \|。


  构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。
 

  3.4 限定符

  限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有*或+或?或{n}或{n,}或{n,m}共6种。

  *、+和?限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个?就可以实现非贪婪或最小匹配。

  正则表达式的限定符有:

字符 描述
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,} n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。


  3.5 定位符

  用来描述字符串或单词的边界,^和$分别指字符串的开始与结束,\b描述单词的前或后边界,\B表示非单词边界。不能对定位符使用限定符。

  3.6 选择

  用圆括号将所有选择项括起来,相邻的选择项之间用|分隔。但用圆括号会有一个副作用,是相关的匹配会被缓存,此时可用?:放在第一个选项前来消除这种副作用。

  其中?:是非捕获元之一,还有两个非捕获元是?=和?!,这两个还有更多的含义,前者为正向预查,在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串,后者为负向预查,在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。

  3.7 后向引用

  对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容存储。存储子匹配的缓冲区编号从 1 开始,连续编号直至最大 99 个子表达式。每个缓冲区都可以使用 '\n' 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。

  可以使用非捕获元字符 '?:', '?=', or '?!' 来忽略对相关匹配的保存。
4. 各种操作符的运算优先级

  相同优先级的从左到右进行运算,不同优先级的运算先高后低。各种操作符的优先级从高到低如下:

操作符 描述
\ 转义符
(), (?:), (?=), [] 圆括号和方括号
*, +, ?, {n}, {n,}, {n,m} 限定符
^, $, \anymetacharacter 位置和顺序
| “或”操作
5. 全部符号解释

字符 描述
\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "\" 而 "\(" 则匹配 "("。
^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。
$ 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,} n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
. 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。
(pattern) 匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 '\(' 或 '\)'。
(?:pattern) 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。
(?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x|y 匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
[xyz] 字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz] 负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。
[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\cx 匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
\d 匹配一个数字字符。等价于 [0-9]。
\D 匹配一个非数字字符。等价于 [^0-9]。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。
\w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
\W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。
\xn 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'\x41' 匹配 "A"。'\x041' 则等价于 '\x04' & "1"。正则表达式中可以使用 ASCII 编码。.
\num 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)\1' 匹配两个连续的相同字符。
\n 标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
\nm 标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。
\nml 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。
\un 匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号 (?)。
6. 部分例子

正则表达式 说明
/\b([a-z]+) \1\b/gi 一个单词连续出现的位置
/(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/ 将一个URL解析为协议、域、端口及相对路径
/^(?:Chapter|Section) [1-9][0-9]{0,1}$/ 定位章节的位置
/[-a-z]/ A至z共26个字母再加一个-号。
/ter\b/ 可匹配chapter,而不能terminal
/\Bapt/ 可匹配chapter,而不能aptitude
/Windows(?=95 |98 |NT )/ 可匹配Windows95或Windows98或WindowsNT,当找到一个匹配后,从Windows后面开始进行下一次的检索匹配。
7. 正则表达式匹配规则

  7.1 基本模式匹配

  一切从最基本的开始。模式,是正规表达式最基本的元素,它们是一组描述字符串特征的字符。模式可以很简单,由普通的字符串组成,也可以非常复杂,往往用特殊的字符表示一个范围内的字符、重复出现,或表示上下文。例如:

  ^once

  这个模式包含一个特殊的字符^,表示该模式只匹配那些以once开头的字符串。例如该模式与字符串"once upon a time"匹配,与"There once was a man from NewYork"不匹配。正如如^符号表示开头一样,$符号用来匹配那些以给定模式结尾的字符串。

  bucket$

  这个模式与"Who kept all of this cash in a bucket"匹配,与"buckets"不匹配。字符^和$同时使用时,表示精确匹配(字符串与模式一样)。例如:

  ^bucket$

  只匹配字符串"bucket"。如果一个模式不包括^和$,那么它与任何包含该模式的字符串匹配。例如:模式

  once

  与字符串

  There once was a man from NewYork
  Who kept all of his cash in a bucket.

  是匹配的。

  在该模式中的字母(o-n-c-e)是字面的字符,也就是说,他们表示该字母本身,数字也是一样的。其他一些稍微复杂的字符,如标点符号和白字符(空格、制表符等),要用到转义序列。所有的转义序列都用反斜杠(\)打头。制表符的转义序列是:\t。所以如果我们要检测一个字符串是否以制表符开头,可以用这个模式:

  ^\t

  类似的,用\n表示“新行”,\r表示回车。其他的特殊符号,可以用在前面加上反斜杠,如反斜杠本身用\\表示,句号.用\.表示,以此类推。

  7.2 字符簇

  在INTERNET的程序中,正规表达式通常用来验证用户的输入。当用户提交一个FORM以后,要判断输入的电话号码、地址、EMAIL地址、信用卡号码等是否有效,用普通的基于字面的字符是不够的。

  所以要用一种更自由的描述我们要的模式的办法,它就是字符簇。要建立一个表示所有元音字符的字符簇,就把所有的元音字符放在一个方括号里:

  [AaEeIiOoUu]

  这个模式与任何元音字符匹配,但只能表示一个字符。用连字号可以表示一个字符的范围,如:

  [a-z] //匹配所有的小写字母
  [A-Z] //匹配所有的大写字母
  [a-zA-Z] //匹配所有的字母
  [0-9] //匹配所有的数字
  [0-9\.\-] //匹配所有的数字,句号和减号
  [ \f\r\t\n] //匹配所有的白字符

  同样的,这些也只表示一个字符,这是一个非常重要的。如果要匹配一个由一个小写字母和一位数字组成的字符串,比如"z2"、"t6"或"g7",但不是"ab2"、"r2d3" 或"b52"的话,用这个模式:

  ^[a-z][0-9]$

  尽管[a-z]代表26个字母的范围,但在这里它只能与第一个字符是小写字母的字符串匹配。

  前面曾经提到^表示字符串的开头,但它还有另外一个含义。当在一组方括号里使用^是,它表示“非”或“排除”的意思,常常用来剔除某个字符。还用前面的例子,我们要求第一个字符不能是数字:

  ^[^0-9][0-9]$

  这个模式与"&5"、"g7"及"-2"是匹配的,但与"12"、"66"是不匹配的。下面是几个排除特定字符的例子:

  [^a-z] //除了小写字母以外的所有字符
  [^\\\/\^] //除了(\)(/)(^)之外的所有字符
  [^\"\'] //除了双引号(")和单引号(')之外的所有字符

  特殊字符"." (点,句号)在正规表达式中用来表示除了“新行”之外的所有字符。所以模式"^.5$"与任何两个字符的、以数字5结尾和以其他非“新行”字符开头的字符串匹配。模式"."可以匹配任何字符串,除了空串和只包括一个“新行”的字符串。

  PHP的正规表达式有一些内置的通用字符簇,列表如下:

  字符簇含义

  [[:alpha:]] 任何字母
  [[:digit:]] 任何数字
  [[:alnum:]] 任何字母和数字
  [[:space:]] 任何白字符
  [[:upper:]] 任何大写字母
  [[:lower:]] 任何小写字母
  [[:punct:]] 任何标点符号
  [[:xdigit:]] 任何16进制的数字,相当于[0-9a-fA-F]

  7.3 确定重复出现

  到现在为止,你已经知道如何去匹配一个字母或数字,但更多的情况下,可能要匹配一个单词或一组数字。一个单词有若干个字母组成,一组数字有若干个单数组成。跟在字符或字符簇后面的花括号({})用来确定前面的内容的重复出现的次数。

  字符簇 含义
  ^[a-zA-Z_]$ 所有的字母和下划线
  ^[[:alpha:]]{3}$ 所有的3个字母的单词
  ^a$ 字母a
  ^a{4}$ aaaa
  ^a{2,4}$ aa,aaa或aaaa
  ^a{1,3}$ a,aa或aaa
  ^a{2,}$ 包含多于两个a的字符串
  ^a{2,} 如:aardvark和aaab,但apple不行
  a{2,} 如:baad和aaa,但Nantucket不行
  \t{2} 两个制表符
  .{2} 所有的两个字符

  这些例子描述了花括号的三种不同的用法。一个数字,{x}的意思是“前面的字符或字符簇只出现x次”;一个数字加逗号,{x,}的意思是“前面的内容出现x或更多的次数”;两个用逗号分隔的数字,{x,y}表示“前面的内容至少出现x次,但不超过y次”。我们可以把模式扩展到更多的单词或数字:

  ^[a-zA-Z0-9_]{1,}$ //所有包含一个以上的字母、数字或下划线的字符串
  ^[0-9]{1,}$ //所有的正数
  ^\-{0,1}[0-9]{1,}$ //所有的整数
  ^\-{0,1}[0-9]{0,}\.{0,1}[0-9]{0,}$ //所有的小数

  最后一个例子不太好理解,是吗?这么看吧:与所有以一个可选的负号(\-{0,1})开头(^)、跟着0个或更多的数字([0-9]{0,})、和一个可选的小数点(\.{0,1})再跟上0个或多个数字([0-9]{0,}),并且没有其他任何东西($)。下面你将知道能够使用的更为简单的方法。

  特殊字符"?"与{0,1}是相等的,它们都代表着:“0个或1个前面的内容”或“前面的内容是可选的”。所以刚才的例子可以简化为:

  ^\-?[0-9]{0,}\.?[0-9]{0,}$

  特殊字符"*"与{0,}是相等的,它们都代表着“0个或多个前面的内容”。最后,字符"+"与 {1,}是相等的,表示“1个或多个前面的内容”,所以上面的4个例子可以写成:

  ^[a-zA-Z0-9_]+$ //所有包含一个以上的字母、数字或下划线的字符串
  ^[0-9]+$ //所有的正数
  ^\-?[0-9]+$ //所有的整数
  ^\-?[0-9]*\.?[0-9]*$ //所有的小数

  当然这并不能从技术上降低正规表达式的复杂性,但可以使它们更容易阅读。
posted @ 2006-01-22 14:28 kebo 阅读(282) | 评论 (0)编辑 收藏

<2006年1月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
2930311234

常用链接

留言簿(1)

随笔分类

随笔档案

文章档案

相册

收藏夹

朋友

搜索

  •  

积分与排名

  • 积分 - 22860
  • 排名 - 1603

最新评论

阅读排行榜

评论排行榜