TypeScirpt 新增接口的特性特性相比于JavaScript有什么优势

模块化的JavaScript开发的优势在哪里
稿源:雨夜带刀‘s Blog
如今模块化的 JavaScript 的开发越来越火热,无论是模块加载器还是优秀的 JavaScript 模块,都是层出不穷。既然这么火,肯定是有存在的理由,肯定是解决了某些实际问题。很多没接触过模块化 JavaScript 开发者不禁要问,我真的需要模块化吗,模块化相比于传统的模式有什么优势?
JavaScript 本身是没有模块化支持的,很多语言多有,就连CSS都有这样的加载方式。
@import "fed.css";
虽然因为性能问题不推荐CSS这样来进行加载,但这是一种模块化的思想,这种思想对于 JavaScript 来说很有用。幸好JavaScript是一门灵活的语言,可以通过下面这段代码来进行动态加载 JavaScript 文件。
var script = document.createElement( 'script' ),&&& head = document.
script.src = '/test.js';script.async = 'async';head.insertBefore( script, head.firstChild );
传统的加载方式必须在页面中放置一个 script 标签来进行加载。
&script type="text/javascript" src="/test.js"&&/script&
更好的分离
那如果要加载多个就得放置多个 script 标签,如果是加载模块的话,拿 easy.js 来说,页面中始终只要引用 easy.js 即可,这样对于 HTML 和 JavaScript 分离很有好处,在某些场景下这个分离度很重要。
就拿我司的情况来说吧。后端的 view 层并不是由我们前端来开发的,项目上线的时候,前端只能更新 CSS 和 JS 文件,HTML 文件动不了。如果前端要在该页面新增一个 JavaScript 文件的引用是很麻烦的,因为后端程序的更新都要严格按照流程来并有固定的更新时间,如果是用模块加载的方式不用再理会后端的更新。当然,你也许会说,如果原页面中已经有 JavaScript 文件,我直接在原文件中加代码不就行了,那么接下来说说直接在原文件中新增代码会碰到什么样的问题。
更好的代码组织方式
如果单个文件越来越大,维护起来出问题的几率也会越来越大,一个人开发还好,如果是多人开发,不同的代码风格,超多的业务逻辑混杂在一起,不要说维护了,光想想都蛋痛。模块式的开发,一个文件就是一个模块,控制了文件的粒度,每个模块可以专注于一个功能。正所谓一个萝卜一个坑,多人开发时,各自管好自己坑里的萝卜就行了,这也正是 OOP 的思想。
还是围绕单个文件来说事,当文件大到一定的程度,性能问题也随之而来了。合并文件是能减少请求,这是会带来性能的提升,但是当文件大到一定的体积时,此时的下载时间可能并不会比多个小文件的下载时间更短。此时就需要权衡请求数和文件体积的关系了。
单文件还有一个问题,那就是缓存是否能充分的利用好。如果一个大体积的文件内包含了超多的业务逻辑和复杂的功能,而这个文件同时又被很多页面引用到。比如在某页面,实际只用到了该文件一个很少的功能,那么其他的代码对于该页面来说就是多余的,浪费了加载流量。你或许会说,这个文件虽然大,但是它第一次加载的时候就被缓存过了,尽管在某页面只用到了极少部分的功能,但只要缓存过,加载还是挺快的。是的,如果情况有这么理想肯定是好事。但是,往往理想和现实都会有差距,如果产品的迭代更新太快,业务需求一天一个样,那么该文件就会三天两头的更新,更新可能是一个很小的功能,但是这样的更新对于刷新缓存的代价可是很大的。如果确实有这种情况,就说明这种设计确实是有问题。如果能合理的对文件进行模块化的管理,那么可以尽量减少不必要的加载,尽量减少刷新大文件的缓存带来的损失,这也需要权衡好,比如将很少更新的合并成一个文件,常更新的独立成模块。
避免命名冲突
JavaScript 本身是没有命名空间的,为了避免命名冲突,经常会使用对象和闭包的办法来避免。用对象仅仅是降低了冲突的概率而已,拿经常使用 jQuery 的开发来说,无论是往 $ 上扩展还是在 $.fn 上扩展,人多了难免会起冲突。或者用自定义的对象,搞个好几层,不光是写起来难记,这样的调用也会在性能上打折扣的。模块化就很好的解决了这个问题,在该模块内的任何形式的命名都不会再和其他模块有冲突,你想起啥名都行了。当然,你硬要在模块内部给 window 上挂一堆东西,我也没办法。
既然每个模块都是封闭式的,那么模块之间如何通信呢?接口的设计那是必须的。很简单,对于像 seajs 这种 CMD 规范的,需要使用自定义的关键字来向外部暴露一个接口。
define(function( require, exports ){&&& var hello = 'hello world';&&& // 向外部暴露该模块的接口&&& exports.hello =});
easy.js 遵循 AMD 规范,暴露接口更简单,直接用 return 关键词即可。
define( 'hello', function(){&&& var hello = 'hello world';&&& // 向外部暴露该模块的接口&&&});
更好的依赖处理
传统的开发模式,如果 B 文件要依赖 A 文件,那么必须在 B 文件前面用 script 的形式先加载好 A 文件。如果有一天,B 文件不再需要依赖 A 文件,或者要增加依赖文件 C,那么又回到了我说的第一个问题上。如果这个 B 文件被 N 个页面在调用,而且页面还跨业务站点,那改起来简直就是噩梦啊。如果是用模块化,只需要在模块内部声明好依赖就行了,增加删除都直接修改模块即可。调用的时候也不用管该模块依赖了哪些其他模块,放心的用就是了。
好了,讲了这么多,如果你还是觉得无动于衷,要么是你接触到的项目较小,还没复杂到这个程度,要么就是我的表达能力有问题。如果你觉得还有什么需要补充的,欢迎在下面留言。
文章来源:,转载请注明出处。
有好的文章希望站长之家帮助分享推广,猛戳这里
本网页浏览已超过3分钟,点击关闭或灰色背景,即可回到网页11618人阅读
.Net技术(3)
在ASP.Net中两种利用CSS实现多界面的方法
通过使页面动态加载不同CSS实现多界面方法一: &%@page language="C#"%& &%@import namespace="System.Data"%& &script language="c#" runat="server"& public void page_load(Object obj,EventArgs e) { //创建服务器端控件. //指定的标记"LINK"初始化此类的新实例. HtmlGenericControl objLink=new HtmlGenericControl("LINK"); objLink.ID=ID; objLink.Attributes["rel"]="stylesheet"; objLink.Attributes["type"]="text/css"; objLink.Attributes["href"]="portal.css"; //此控件不产生任何可见输出,仅作为其他控件的容器,可在其中添加,插入或移除控件. MyCSS.Controls.Add(objLink); } &/script& &html& &head& &title&c#&/title& &asp:placeholder id="MyCSS" runat="server"&&/asp:placeholder& &/head& &body bgColor="#ffcc66" style="FONT:9pt"& &form runat="server"& &/form& &/body& &/html& 通过动态设置页面所有同类型控件的样式来该变界面: 方法二:可以通过改变WEB控件的CssClass属性,可方便地设置和修改控件的样式。 但在实际开发过程中,一个个地设置控件的CssClass属性,非常繁琐,所以此思路应用不广. 但下面的代码段演示了一次性改变页面所有同类型控件的样式的方法,可以实现简单的SKIN等功能。 代码如下: public void page_load(Object obj,EventArgs e) { if(!Page.IsPostBack){ //为页面的所有控件设置样式. SetCSS(Page.Controls); } } private void SetCSS(System.Web.UI.ControlCollection vControls) { for(int i=0;i&vControls.Ci++) { System.Web.UI.Control vControl=vControls[i]; //得到控件的类型 //可增加控件类型及相应处理方法 string PType=vControl.GetType().N switch (PType) { case "TextBox": TextBox_CSS ((TextBox) vControl);
case "Button": //Button_CSS ((Button) vControl);
case "DataGrid": //DataGrid_CSS ((DataGrid) vControl);
} if(vControl.Controls.Count&0) SetCSS(vControl.Controls); } } private void TextBox_CSS(TextBox tb){ tb.CssClass="TextBox_show"; } &form runat="server"& &asp:textbox id="Search1" runat="server"/& &asp:textbox id="Search2" CssClass="INPUT" runat="server"/& &/form& 运行后,查看页面源码.可发现文本框的样式已统一修改为"TextBox_show".
1、DateTime 数字型 System.DateTime currentTime=new System.DateTime();; 1.1 取当前年月日时分秒 currentTime=System.DateTime.N; 1.2 取当前年 int 年=currentTime.Y; 1.3 取当前月 int 月=currentTime.M; 1.4 取当前日 int 日=currentTime.D; 1.5 取当前时 int 时=currentTime.H; 1.6 取当前分 int 分=currentTime.M; 1.7 取当前秒 int 秒=currentTime.S; 1.8 取当前毫秒 int 毫秒=currentTime.M; (变量可用中文) 2、Int32.Parse(变量) Int32.Parse("常量") 字符型转换 转为32位数字型 3、 变量.ToString() 字符型转换 转为字符串 12345.ToString("n");; //生成 12,345.00 12345.ToString("C");; //生成 ¥12,345.00 12345.ToString("e");; //生成 1.4 12345.ToString("f4");; //生成
12345.ToString("x");; //生成 3039 (16进制) 12345.ToString("p");; //生成 1,234,500.00% 4、变量.Length 数字型 取字串长度: 如: string str="中国";; int Len = str.L; //Len是自定义变量, str是求测的字串的变量名 5、System.Text.Encoding.Default.GetBytes(变量) 字码转换 转为比特码 如:byte[] bytStr = System.Text.Encoding.Default.GetBytes(str);; 然后可得到比特长度: len = bytStr.L; 6、System.Text.StringBuilder("") 字符串相加,(+号是不是也一样?) 如:System.Text.StringBuilder sb = new System.Text.StringBuilder("");; sb.Append("中华");; sb.Append("人民");; sb.Append("共和国");; 7、变量.Substring(参数1,参数2);; 截取字串的一部分,参数1为左起始位数,参数2为截取几位。 如:string s1 = str.Substring(0,2);; 8、String user_IP=Request.ServerVariables["REMOTE_ADDR"].ToString();; 取远程用户IP地址 9、穿过代理服务器取远程用户真实IP地址: if(Request.ServerVariables["HTTP_VIA"]!=null){ string user_IP=Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();; }else{ string user_IP=Request.ServerVariables["REMOTE_ADDR"].ToString();; } 10、 Session["变量"];; 存取Session值; 如,赋值: Session["username"]="小布什";; 取值: Object objName=Session["username"];; String strName=objName.ToString();; 清空: Session.RemoveAll();; 11、String str=Request.QueryString["变量"];; 用超链接传送变量。 如在任一页中建超链接:〈a href=Edit.aspx?fbid=23〉点击〈/a〉 在Edit.aspx页中取值:String str=Request.QueryString["fdid"];; 12、DOC对象.CreateElement("新建节点名");; 创建XML文档新节点 13、父节点.AppendChild(子节点); 将新建的子节点加到XML文档父节点下 14、 父节点.RemoveChild(节点);; 删除节点 15、Response Response.Write("字串"); Response.Write(变量); 向页面输出。 Response.Redirect("URL地址"); 跳转到URL指定的页面 16、char.IsWhiteSpce(字串变量,位数)&&逻辑型 查指定位置是否空字符; 如: string str="中国 人民";; Response.Write(char.IsWhiteSpace(str,2));; //结果为:True, 第一个字符是0位,2是第三个字符。 17、char.IsPunctuation('字符') --逻辑型 查字符是否是标点符号 如:Response.Write(char.IsPunctuation('A'));; //返回:False 18、(int)'字符' 把字符转为数字,查代码点,注意是单引号。 如: Response.Write((int)'中');; //结果为中字的代码:20013 19、(char)代码 把数字转为字符,查代码代表的字符。 如: Response.Write((char)22269);; //返回;国&字。 20、 Trim() 清除字串前后空格 21 、字串变量.Replace("子字串","替换为") 字串替换 如: string str="中国";; str=str.Replace("国","央");; //将国字换为央字 Response.Write(str);; //输出结果为;中央& 再如:(这个非常实用) string str="这是〈script〉脚本";; str=str.Replace("〈","〈font〉〈〈/font〉");; //将左尖括号替换为〈font〉 与 〈 与 〈/font〉 (或换为〈,但估计经XML存诸后,再提出仍会还原) Response.Write(str);; //显示为:;这是〈script〉脚本& 如果不替换,〈script〉将不显示,如果是一段脚本,将运行;而替换后,脚本将不运行。 这段代码的价值在于:你可以让一个文本中的所有HTML标签失效,全部显示出来,保护你的具有交互性的站点。 具体实现:将你的表单提交按钮脚本加上下面代码: string strSubmit=label1.T; //label1是你让用户提交数据的控件ID。 strSubmit=strSubmit.Replace("〈","〈font〉〈〈/font〉");; 然后保存或输出strSubmit。 用此方法还可以简单实现UBB代码。 22、Math.Max(i,j) 取i与j中的最大值 如 int x=Math.Max(5,10);; // x将取值 10 23、字串对比一般都用: if(str1==str2){ } , 但还有别的方法: (1)、 string str1;; str2 //语法: str1.EndsWith(str2);; __检测字串str1是否以字串str2结尾,返回布尔值.如: if(str1.EndsWith(str2)){ Response.Write("字串str1是以"+str2+"结束的");; } (2)、 //语法:str1.Equals(str2);; __检测字串str1是否与字串str2相等,返回布尔值,用法同上. (3)、 //语法 Equals(str1,str2);; __检测字串str1是否与字串str2相等,返回布尔值,用法同上. 24、IndexOf() 、LastIndexOf() 查找字串中指定字符或字串首次(最后一次)出现的位置,返回索引值,如: str1.IndexOf("字"); //查找;字&在str1中的索引值(位置) str1.IndexOf("字串");//查找;字串&的第一个字符在str1中的索引值(位置) str1.IndexOf("字串",3,2);//从str1第4个字符起,查找2个字符,查找;字串&的第一个字符在str1中的索引值(位置) 25、Insert() 在字串中指定索引位插入指定字符。如: str1.Insert(1,"字");;在str1的第二个字符处插入;字&,如果str1="中国",插入后为;中字国&; 26、PadLeft()、PadRight() 在字串左(或右)加空格或指定char字符,使字串达到指定长度,如: 〈% string str1="中国人";; str1=str1.PadLeft(10,'1');; //无第二参数为加空格 Response.Write(str1);; //结果为;1111111中国人& , 字串长为10 %〉 27、Remove() 从指定位置开始删除指定数的字符 字串对比一般都用: if(str1==str2){ } , 但还有别的方法: 1、 string str1;; str2 //语法: str1.EndsWith(str2);; __检测字串str1是否以字串str2结尾,返回布尔值.如: if(str1.EndsWith(str2)){ Response.Write("字串str1是以"+str2+"结束的");; } 2、 //语法:str1.Equals(str2);; __检测字串str1是否与字串str2相等,返回布尔值,用法同上. 3、 //语法 Equals(str1,str2);; __检测字串str1是否与字串str2相等,返回布尔值,用法同上. IndexOf() 查找字串中指定字符或字串首次出现的位置,返首索引值,如: str1.IndexOf("字"); //查找;字&在str1中的索引值(位置) str1.IndexOf("字串");//查找;字串&的第一个字符在str1中的索引值(位置) str1.IndexOf("字串",3,2);//从str1第4个字符起,查找2个字符,查找;字串&的第一个字符在str1中的索引值(位置) 1.9 取中文日期显示&&年月日时分 string strY=currentTime.ToString("f");; //不显示秒 1.10 取中文日期显示_年月 string strYM=currentTime.ToString("y");; 1.11 取中文日期显示_月日 string strMD=currentTime.ToString("m");; 1.12 取当前年月日,格式为: string strYMD=currentTime.ToString("d");; 1.13 取当前时分,格式为:14:24 string strT=currentTime.ToString("t");;
正则表达式用于字符串处理,表单验证等场合,实用高效,但用到时总是不太把握,以致往往要上网查一番。我将一些常用的表达式收藏在这里,作备忘之用。本贴随时会更新。
匹配中文字符的正则表达式: [/u4e00-/u9fa5]
匹配双字节字符(包括汉字在内):[^/x00-/xff]
应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
String.prototype.len=function(){return this.replace([^/x00-/xff]/g,"aa").}
匹配空行的正则表达式:/n[/s| ]*/r
匹配HTML标记的正则表达式:/&(.*)&.*&///1&|&(.*) //&/
匹配首尾空格的正则表达式:(^/s*)|(/s*$)
String.prototype.trim = function(){&&& return this.replace(/(^/s*)|(/s*$)/g, "");}
利用正则表达式分解和转换IP地址:
下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的Javascript程序:
function IP2V(ip){&re=/(/d+)/.(/d+)/.(/d+)/.(/d+)/g& //匹配IP地址的正则表达式if(re.test(ip)){return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1}else{&throw new Error("Not a valid IP address!")}}
不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:
var ip="10.100.20.168"ip=ip.split(".")alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))
匹配Email地址的正则表达式:/w+([-+.]/w+)*@/w+([-.]/w+)*/./w+([-.]/w+)*
匹配网址URL的正则表达式:http://([/w-]+/.)+[/w-]+(/[/w- ./?%&=]*)?
利用正则表达式去除字串中重复的字符的算法程序:[注:此程序不正确,原因见本贴回复]
var s="abacabefgeeii"var s1=s.replace(/(.).*/1/g,"$1")var re=new RegExp("["+s1+"]","g")var s2=s.replace(re,"") alert(s1+s2)& //结果为:abcefgi我原来在CSDN上发贴寻求一个表达式来实现去除重复字符的方法,最终没有找到,这是我能想到的最简单的实现方法。思路是使用后向引用取出包括重复的字符,再以重复的字符建立第二个表达式,取到不重复的字符,两者串连。这个方法对于字符顺序有要求的字符串可能不适用。
得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1
s="http://www.9499.net/page1.htm"s=s.replace(/(.*//){0,}([^/.]+).*/ig,"$2")alert(s)
利用正则表达式限制网页表单里的文本框输入内容:
用正则表达式限制只能输入中文:onkeyup="value=value.replace(/[^/u4E00-/u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^/u4E00-/u9FA5]/g,''))"
用正则表达式限制只能输入全角字符:&onkeyup="value=value.replace(/[^/uFF00-/uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^/uFF00-/uFFFF]/g,''))"
用正则表达式限制只能输入数字:onkeyup="value=value.replace(/[^/d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^/d]/g,''))"
用正则表达式限制只能输入数字和英文:onkeyup="value=value.replace(/[/W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^/d]/g,''))"
正则表达式,相关链接
微软的正则表达式教程(五):选择/编组和后向引用
微软的正则表达式教程(四):限定符和定位符
微软的正则表达式教程(三):字符匹配
微软的正则表达式教程(二):正则表达式语法和优先权顺序
微软的正则表达式教程(一):正则表达式简介
小程序大作为:高级查找/替换、正则表达式练习器、Javascript脚本程序调试器
经典正则表达式 正则表达式,正规表达式,正则表达式匹配,正则表达式语法,模式匹配,正规表达式匹配 javascript正则表达式 ASP正则表达式 ASP.NET正则表达式 C#正则表达式 JSP正则表达式 PHP正则表达式 VB.NET正则表达式 VBSCript正则表达式编程 delphi正则表达式 jscript
正则表达式 regular expression 正则表达式 RegExp 模式 pattern 匹配 Match .NET命名空间: System.Text.RegularExpression
补充: ^/d+$  //匹配非负整数(正整数 + 0) ^[0-9]*[1-9][0-9]*$  //匹配正整数 ^((-/d+)|(0+))$  //匹配非正整数(负整数 + 0) ^-[0-9]*[1-9][0-9]*$  //匹配负整数 ^-?/d+$    //匹配整数 ^/d+(/./d+)?$  //匹配非负浮点数(正浮点数 + 0) ^(([0-9]+/.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*/.[0-9]+)|([0-9]*[1-9][0-9]*))$  //匹配正浮点数 ^((-/d+(/./d+)?)|(0+(/.0+)?))$  //匹配非正浮点数(负浮点数 + 0) ^(-(([0-9]+/.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*/.[0-9]+)|([0-9]*[1-9][0-9]*)))$  //匹配负浮点数 ^(-?/d+)(/./d+)?$  //匹配浮点数 ^[A-Za-z]+$  //匹配由26个英文字母组成的字符串 ^[A-Z]+$  //匹配由26个英文字母的大写组成的字符串 ^[a-z]+$  //匹配由26个英文字母的小写组成的字符串 ^[A-Za-z0-9]+$  //匹配由数字和26个英文字母组成的字符串 ^/w+$  //匹配由数字、26个英文字母或者下划线组成的字符串 ^[/w-]+(/.[/w-]+)*@[/w-]+(/.[/w-]+)+$    //匹配email地址 ^[a-zA-z]+://匹配(/w+(-/w+)*)(/.(/w+(-/w+)*))*(/?/S*)?$  //匹配url
利用正则表达式去除字串中重复的字符的算法程序: var s="abacabefgeeii" var s1=s.replace(/(.).*/1/g,"$1") var re=new RegExp("["+s1+"]","g") var s2=s.replace(re,"") alert(s1+s2) //结果为:abcefgi =============================== 如果var s = "abacabefggeeii" 结果就不对了,结果为:abeicfgg 正则表达式的能力有限
1.确认有效电子邮件格式 下面的代码示例使用静态 Regex.IsMatch 方法验证一个字符串是否为有效电子邮件格式。如果字符串包含一个有效的电子邮件地址,则 IsValidEmail 方法返回 true,否则返回 false,但不采取其他任何操作。您可以使用 IsValidEmail,在应用程序将地址存储在数据库中或显示在 ASP.NET 页中之前,筛选出包含无效字符的电子邮件地址。 [Visual Basic] Function IsValidEmail(strIn As String) As Boolean ' Return true if strIn is in valid e-mail format. Return Regex.IsMatch(strIn, ("^([/w-/.]+)@((/[[0-9]{1,3}/.[0-9]{1,3}/.[0-9]{1,3}/.)|(([/w-]+/.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(/]?)$") End Function [C#] bool IsValidEmail(string strIn) { // Return true if strIn is in valid e-mail format. return Regex.IsMatch(strIn, @"^([/w-/.]+)@((/[[0-9]{1,3}/.[0-9]{1,3}/.[0-9]{1,3}/.)|(([/w-]+/.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(/]?)$"); } 2.清理输入字符串 下面的代码示例使用静态 Regex.Replace 方法从字符串中抽出无效字符。您可以使用这里定义的 CleanInput 方法,清除掉在接受用户输入的窗体的文本字段中输入的可能有害的字符。CleanInput 在清除掉除 @、-(连字符)和 .(句点)以外的所有非字母数字字符后返回一个字符串。 [Visual Basic] Function CleanInput(strIn As String) As String ' Replace invalid characters with empty strings. Return Regex.Replace(strIn, "[^/w/.@-]", "") End Function [C#] String CleanInput(string strIn) { // Replace invalid characters with empty strings. return Regex.Replace(strIn, @"[^/w/.@-]", ""); } 3.更改日期格式 以下代码示例使用 Regex.Replace 方法来用 dd-mm-yy 的日期形式代替 mm/dd/yy 的日期形式。 [Visual Basic] Function MDYToDMY(input As String) As String Return Regex.Replace(input, _ "/b(?&month&/d{1,2})/(?&day&/d{1,2})/(?&year&/d{2,4})/b", _ "${day}-${month}-${year}") End Function [C#] String MDYToDMY(String input) { return Regex.Replace(input, "//b(?&month&//d{1,2})/(?&day&//d{1,2})/(?&year&//d{2,4})//b", "${day}-${month}-${year}"); } Regex 替换模式 本示例说明如何在 Regex.Replace 的替换模式中使用命名的反向引用。其中,替换表达式 ${day} 插入由 (?&day&...) 组捕获的子字符串。 有几种静态函数使您可以在使用正则表达式操作时无需创建显式正则表达式对象,而 Regex.Replace 函数正是其中之一。如果您不想保留编译的正则表达式,这将给您带来方便 4.提取 URL 信息 以下代码示例使用 Match.Result 来从 URL 提取协议和端口号。例如,&:8080/letters/readme.html&将返回&http:8080&。 [Visual Basic] Function Extension(url As String) As String Dim r As New Regex("^(?&proto&/w+)://[^/]+?(?&port&:/d+)?/", _ piled) Return r.Match(url).Result("${proto}${port}") End Function [C#] String Extension(String url) { Regex r = new Regex(@"^(?&proto&/w+)://[^/]+?(?&port&:/d+)?/", piled); return r.Match(url).Result("${proto}${port}"); }
  一、正则表达式基础知识  我们先从简单的开始。假设你要搜索一个包含字符&cat&的字符串,搜索用的正则表达式就是&cat&。如果搜索对大小写不敏感,单词&catalog&、&Catherine&、&sophisticated&都可以匹配。也就是说:
  1.1句点符号  假设你在玩英文拼字游戏,想要找出三个字母的单词,而且这些单词必须以&t&字母开头,以&n&字母结束。另外,假设有一本英文字典,你可以用正则表达式搜索它的全部内容。要构造出这个正则表达式,你可以使用一个通配符??句点符号&.&。这样,完整的表达式就是&t.n&,它匹配&tan&、&ten&、&tin&和&ton&,还匹配 &t#n&、&tpn&甚至&tn&,还有其他许多无意义的组合。这是因为句点符号匹配所有字符,包括空格、Tab字符甚至换行符:
  1.2方括号符号  为了解决句点符号匹配范围过于广泛这一问题,你可以在方括号(&[]&)里面指定看来有意义的字符。此时,只有方括号里面指定的字符才参与匹配。也就是说,正则表达式&t[aeio]n&只匹配&tan&、&Ten&、&tin&和&ton&。但&Toon&不匹配,因为在方括号之内你只能匹配单个字符:
  1.4表示匹配次数的符号  表一显示了表示匹配次数的符号,这些符号用来确定紧靠该符号左边的符号出现的次数:
  假设我们要在文本文件中搜索美国的社会安全号码。这个号码的格式是999-99-9999。用来匹配它的正则表达式如图一所示。在正则表达式中,连字符(&-&)有着特殊的意义,它表示一个范围,比如从0到9。因此,匹配社会安全号码中的连字符号时,它的前面要加上一个转义字符&/&。
  图一:匹配所有123-12-1234形式的社会安全号码  假设进行搜索的时候,你希望连字符号可以出现,也可以不出现??即,999-99-999都属于正确的格式。这时,你可以在连字符号后面加上&?&数量限定符号,如图二所示:
  图二:匹配所有123-12-234形式的社会安全号码  下面我们再来看另外一个例子。美国汽车牌照的一种格式是四个数字加上二个字母。它的正则表达式前面是数字部分&[0-9]{ 4}&,再加上字母部分&[A-Z]{ 2}&。图三显示了完整的正则表达式。
  图三:匹配典型的美国汽车牌照号码,如8836KV  1.5&否&符号  &^&符号称为&否&符号。如果用在方括号内,&^&表示不想要匹配的字符。例如,图四的正则表达式匹配所有单词,但以&X&字母开头的单词除外。
  图四:匹配所有单词,但&X&开头的除外  1.6圆括号和空白符号  假设要从格式为&June26,1951&的生日日期中提取出月份部分,用来匹配该日期的正则表达式可以如图五所示:
  图五:匹配所有MothDD,YYYY格式的日期  新出现的&/s&符号是空白符号,匹配所有的空白字符,包括Tab字符。如果字符串正确匹配,接下来如何提取出月份部分呢?只需在月份周围加上一个圆括号创建一个组,然后用OROAPI(本文后面详细讨论)提取出它的值。修改后的正则表达式如图六所示:
  图六:匹配所有MonthDD,YYYY格式的日期,定义月份值为第一个组  1.7其它符号  为简便起见,你可以使用一些为常见正则表达式创建的快捷符号。如表二所示:  表二:常用符号
  例如,在前面社会安全号码的例子中,所有出现&[0-9]&的地方我们都可以使用&/d&。修改后的正则表达式如图七所示:
/*------------------------ 功能:替换任何空白字符 -------------------------*/ function TrimString (strVal) { strTmp = strVal + ""; if (strTmp.length == 0) return (strTmp); reVal = /^/s*/; strTmp = strTmp.replace (reVal, ''); reVal = //s*$/; return (strTmp.replace (reVal, '')); } /*------------------------ 功能:检测是否是有效数字 -------------------------*/ function Check_Num( num ) { num = ( TrimString( num ) ); if (num.length == 0) return (false); return ( Number( num ) ); } /*------------------------ 功能:检测是否是有效日期 -------------------------*/ function Check_Date (strDate) { strDate = (TrimString (strDate)); if (strDate.length == 0) return (false); reVal = /^([1-2]/d{3})[//|/-](0?[1-9]|10|11|12)[//|/-]([1-2]?[0-9]|0[1-9]|30|31)$/; return (reVal.test (strDate)); } /*------------------------ 功能:检测是否是有效Email -------------------------*/ function Check_Email (strEmail) { strEmail = (TrimString (strEmail)); if (strEmail.length == 0) return (false); reVal = /^[/-!#/$%&'/*/+///.//0-9=/?A-Z/^_`a-z{|}~]+@[/-!#/$%&'/*/+///.//0-9=/?A-Z/^_`a-z{|}~]+(/.[/-!#/$%&'/*/+///.//0-9=/?A-Z/^_`a-z{|}~]+)+$/; return (reVal.test (strEmail)); } /*------------------------ 功能:检测是否是有效时间 -------------------------*/ function Check_Time (strTime) { strTime = (TrimString (strTime)); if (strTime.length == 0) return (false); reVal = /^(([0-9]|[01][0-9]|2[0-3])(:([0-9]|[0-5][0-9])){0,2}|(0?[0-9]|1[0-1])(:([0-9]|[0-5][0-9])){0,2}/s?[aApP][mM])?$/; return (reVal.test (strTime)); } /*------------------------ 功能:检测是否是有效日期特定格式 -------------------------*/ function Check_Date_1 (strDate) { strDate = (TrimString (strDate)); if (strDate.length == 0) return (false); reVal = /^([1-2]/d{3})[//](0?[1-9]|10|11|12)[//]([1-2]?[0-9]|0[1-9]|30|31)$/; return (reVal.test (strDate)); } /*------------------------ 功能:检测是否是有效日期特定格式 -------------------------*/ function Check_Date_2 (strDate) { strDate = (TrimString (strDate)); if (strDate.length == 0) return (false); reVal = /^([1-2]/d{3})[/-](0[1-9]|10|11|12)[/-]([1-2][0-9]|0[1-9]|30|31)$/; return (reVal.test (strDate)); } /*-------------------------------------- 功能:换行定行 ---------------------------------------*/ function enter( form, temp ) { if ( window.event.keyCode == 13 ) { eval( form + temp + ".focus()" ); eval( form + temp + ".select()" ); } else return (false); } /*-------------------------------------- 功能:检查字符串长度 ---------------------------------------*/ function ByteString (strVal) { nLen = 0; for (i = 0; i & strVal. i ++) { if (strVal.charCodeAt (i) & 255) nLen += 2; else nLen ++; }; return (nLen); } /*-------------------------------------- 功能:按要求截取字符串长度 ---------------------------------------*/ function SubString(strVal,nStrLen) { nLen = 0; nTemp = 0; for (i = 0; i & strVal. i ++) { if (strVal.charCodeAt (i) & 255) nLen += 2; else nLen ++; if(nLen &= nStrLen) nTemp = else
}; return(strVal.substr(0,nTemp+1)); } /*------------------------ 功能:检测密码,密码只能由英文字母、数字、减号、下划线、$、#、*、(和)构成,且首位必须是英文字母 -------------------------*/ function Check_Pass( strPass ) { strPass = ( TrimString( strPass ) ); if (strPass.length == 0) return (false); reVal = /^[a-zA-Z]{1}[a-zA-Z0-9-_$#*()]{0,29}$/; return ( reVal.test (strPass) ); } 这是所有的,不过是PHP的,你自己转换一下吧~~
&re: 正则表达式
^(((19)|(20))/d{2})(((((-|/)0?)|0)[1-9])|((-|/)?1[0-2]))((((((-|/)0?)|0)[1-9])|((-|/)?[1-2][0-9]))|((-|/)?3[0-1]))$ 格式
&re: 正则表达式
一、验证类 1、数字验证内 1.1 整数 1.2 大于0的整数 (用于传来的ID的验证) 1.3 负整数的验证 1.4 整数不能大于iMax 1.5 整数不能小于iMin 2、时间类 2.1 短时间,形如 (13:04:06) 2.2 短日期,形如 () 2.3 长时间,形如 ( 13:04:06) 2.4 只有年和月。形如(2003-05,或者2003-5) 2.5 只有小时和分钟,形如(12:03) 3、表单类 3.1 所有的表单的值都不能为空 3.2 多行文本框的值不能为空。 3.3 多行文本框的值不能超过sMaxStrleng 3.4 多行文本框的值不能少于sMixStrleng 3.5 判断单选框是否选择。 3.6 判断复选框是否选择. 3.7 复选框的全选,多选,全不选,反选 3.8 文件上传过程中判断文件类型 4、字符类 4.1 判断字符全部由a-Z或者是A-Z的字字母组成 4.2 判断字符由字母和数字组成。 4.3 判断字符由字母和数字,下划线,点号组成.且开头的只能是下划线和字母 4.4 字符串替换函数.Replace(); 5、浏览器类 5.1 判断浏览器的类型 5.2 判断ie的版本 5.3 判断客户端的分辨率 6、结合类 6.1 email的判断。 6.2 手机号码的验证 6.3 身份证的验证 二、功能类 1、时间与相关控件类 1.1 日历 1.2 时间控件 1.3 万年历 1.4 显示动态显示时钟效果(文本,如OA中时间) 1.5 显示动态显示时钟效果 (图像,像手表) 2、表单类 2.1 自动生成表单 2.2 动态添加,修改,删除下拉框中的元素 2.3 可以输入内容的下拉框 2.4 多行文本框中只能输入iMax文字。如果多输入了,自动减少到iMax个文字(多用于短信发送) 3、打印类 3.1 打印控件 4、事件类 4.1 屏蔽右键 4.2 屏蔽所有功能键 4.3 --& 和&-- F5 F11,F9,F1 4.4 屏蔽组合键ctrl+N 5、网页设计类 5.1 连续滚动的文字,图片(注意是连续的,两段文字和图片中没有空白出现) 5.2 html编辑控件类 5.3 颜色选取框控件 5.4 下拉菜单 5.5 两层或多层次的下拉菜单 5.6 仿IE菜单的按钮。(效果如的导航栏目) 5.7 状态栏,title栏的动态效果(例子很多,可以研究一下) 5.8 双击后,网页自动滚屏 6、树型结构。 6.1 asp+SQL版 6.2 asp+xml+sql版 6.3 java+sql或者java+sql+xml 7、无边框效果的制作 8、连动下拉框技术 9、文本排序 一、验证类 1、数字验证内 1.1 整数 /^(-|/+)?/d+$/.test(str) 1.2 大于0的整数 (用于传来的ID的验证) /^/d+$/.test(str) 1.3 负整数的验证 /^-/d+$/.test(str) 2、时间类 2.1 短时间,形如 (13:04:06) function isTime(str) { var a = str.match(/^(/d{1,2})(:)?(/d{1,2})/2(/d{1,2})$/); if (a == null) {alert('输入的参数不是时间格式');} if (a[1]&24 || a[3]&60 || a[4]&60) { alert("时间格式不对"); return false }
} 2.2 短日期,形如 () function strDateTime(str) { var r = str.match(/^(/d{1,4})(-|//)(/d{1,2})/2(/d{1,2})$/); if(r==null) var d= new Date(r[1], r[3]-1, r[4]); return (d.getFullYear()==r[1]&&(d.getMonth()+1)==r[3]&&d.getDate()==r[4]); } 2.3 长时间,形如 ( 13:04:06) function strDateTime(str) { var reg = /^(/d{1,4})(-|//)(/d{1,2})/2(/d{1,2}) (/d{1,2}):(/d{1,2}):(/d{1,2})$/; var r = str.match(reg); if(r==null) var d= new Date(r[1], r[3]-1,r[4],r[5],r[6],r[7]); return (d.getFullYear()==r[1]&&(d.getMonth()+1)==r[3]&&d.getDate()==r[4]&&d.getHours()==r[5]&&d.getMinutes()==r[6]&&d.getSeconds()==r[7]); } 2.4 只有年和月。形如(2003-05,或者2003-5) 2.5 只有小时和分钟,形如(12:03) 3、表单类 3.1 所有的表单的值都不能为空 &input onblur="if(this.value.replace(/^/s+|/s+$/g,'')=='')alert('不能为空!')"& 3.2 多行文本框的值不能为空。 3.3 多行文本框的值不能超过sMaxStrleng 3.4 多行文本框的值不能少于sMixStrleng 3.5 判断单选框是否选择。 3.6 判断复选框是否选择. 3.7 复选框的全选,多选,全不选,反选 3.8 文件上传过程中判断文件类型 4、字符类 4.1 判断字符全部由a-Z或者是A-Z的字字母组成 &input onblur="if(/[^a-zA-Z]/g.test(this.value))alert('有错')"& 4.2 判断字符由字母和数字组成。 &input onblur="if(/[^0-9a-zA-Z]/g.test(this.value))alert('有错')"& 4.3 判断字符由字母和数字,下划线,点号组成.且开头的只能是下划线和字母 /^([a-zA-z_]{1})([/w]*)$/g.test(str) 4.4 字符串替换函数.Replace(); 5、浏览器类 5.1 判断浏览器的类型 window.navigator.appName 5.2 判断ie的版本 window.navigator.appVersion 5.3 判断客户端的分辨率 window.screen. window.screen. 6、结合类 6.1 email的判断。 function ismail(mail) { return(new RegExp(/^/w+((-/w+)|(/./w+))*/@[A-Za-z0-9]+((/.|-)[A-Za-z0-9]+)*/.[A-Za-z0-9]+$/).test(mail)); } 6.2 手机号码的验证 6.3 身份证的验证 function isIdCardNo(num) { if (isNaN(num)) {alert("输入的不是数字!");} var len = num.length, if (len == 15) re = new RegExp(/^(/d{6})()?(/d{2})(/d{2})(/d{2})(/d{3})$/); else if (len == 18) re = new RegExp(/^(/d{6})()?(/d{4})(/d{2})(/d{2})(/d{3})(/d)$/); else {alert("输入的数字位数不对!");} var a = num.match(re); if (a != null) { if (len==15) { var D = new Date("19"+a[3]+"/"+a[4]+"/"+a[5]); var B = D.getYear()==a[3]&&(D.getMonth()+1)==a[4]&&D.getDate()==a[5]; } else { var D = new Date(a[3]+"/"+a[4]+"/"+a[5]); var B = D.getFullYear()==a[3]&&(D.getMonth()+1)==a[4]&&D.getDate()==a[5]; } if (!B) {alert("输入的身份证号 "+ a[0] +" 里出生日期不对!");} }
} 3.7 复选框的全选,多选,全不选,反选 &form name=hrong& &input type=checkbox name=All onclick="checkAll('mm')"&全选&br/& &input type=checkbox name=mm onclick="checkItem('All')"&&br/& &input type=checkbox name=mm onclick="checkItem('All')"&&br/& &input type=checkbox name=mm onclick="checkItem('All')"&&br/& &input type=checkbox name=mm onclick="checkItem('All')"&&br/& &input type=checkbox name=mm onclick="checkItem('All')"&&br/&&br/& &input type=checkbox name=All2 onclick="checkAll('mm2')"&全选&br/& &input type=checkbox name=mm2 onclick="checkItem('All2')"&&br/& &input type=checkbox name=mm2 onclick="checkItem('All2')"&&br/& &input type=checkbox name=mm2 onclick="checkItem('All2')"&&br/& &input type=checkbox name=mm2 onclick="checkItem('All2')"&&br/& &input type=checkbox name=mm2 onclick="checkItem('All2')"&&br/& &/form& &SCRIPT LANGUAGE="JavaScript"& function checkAll(str) { var a = document.getElementsByName(str); var n = a. for (var i=0; i&n; i++) a[i].checked = window.event.srcElement. } function checkItem(str) { var e = window.event.srcE var all = eval("document.hrong."+ str); if (e.checked) { var a = document.getElementsByName(e.name); all.checked = for (var i=0; i&a. i++) { if (!a[i].checked){ all.checked =} } } else all.checked = } &/SCRIPT& 3.8 文件上传过程中判断文件类型 &input type=file onchange="alert(this.value.match(/^(.*)(/.)(.{1,8})$/)[3])"& 画图: &OBJECT id=S style="LEFT: 0 WIDTH: 392 TOP: 0 HEIGHT: 240px" height=240 width=392 classid="clsid:-D7AC-11D0-89D5-00A0C90833E6"& &/OBJECT& &SCRIPT& S.DrawingSurface.ArcDegrees(0,0,0,30,50,60); S.DrawingSurface.ArcRadians(30,0,0,30,50,60); S.DrawingSurface.Line(10,10,100,100); &/SCRIPT& 写注册表: &SCRIPT& var WshShell = WScript.CreateObject("WScript.Shell"); WshShell.RegWrite ("HKCU//Software//ACME//FortuneTeller//", 1, "REG_BINARY"); WshShell.RegWrite ("HKCU//Software//ACME//FortuneTeller//MindReader", "Goocher!", "REG_SZ"); var bKey = WshShell.RegRead ("HKCU//Software//ACME//FortuneTeller//"); WScript.Echo (WshShell.RegRead ("HKCU//Software//ACME//FortuneTeller//MindReader")); WshShell.RegDelete ("HKCU//Software//ACME//FortuneTeller//MindReader"); WshShell.RegDelete ("HKCU//Software//ACME//FortuneTeller//"); WshShell.RegDelete ("HKCU//Software//ACME//"); &/SCRIPT& TABLAE相关(客户端动态增加行列) &HTML& &SCRIPT LANGUAGE="JScript"& function numberCells() { var count=0; for (i=0; i & document.all.mytable.rows. i++) { for (j=0; j & document.all.mytable.rows(i).cells. j++) { document.all.mytable.rows(i).cells(j).innerText = count++; } } } &/SCRIPT& &BODY onload="numberCells()"& &TABLE id=mytable border=1& &TR&&TH&&&/TH&&TH&&&/TH&&TH&&&/TH&&TH&&&/TH&&/TR& &TR&&TD&&&/TD&&TD&&&/TD&&TD&&&/TD&&TD&&&/TD&&/TR& &TR&&TD&&&/TD&&TD&&&/TD&&TD&&&/TD&&TD&&&/TD&&/TR& &/TABLE& &/BODY& &/HTML& 1.身份证严格验证: &script& var aCity={11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",21:"辽宁",22:"吉林",23:"黑龙江 ",31:"上海",32:"江苏",33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东",41:"河南",42:"湖北 ",43:"湖南",44:"广东",45:"广西",46:"海南",50:"重庆",51:"四川",52:"贵州",53:"云南",54:"西藏 ",61:"陕西",62:"甘肃",63:"青海",64:"宁夏",65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外 "} function cidInfo(sId){ var iSum=0 var info="" if(!/^/d{17}(/d|x)$/i.test(sId)) sId=sId.replace(/x$/i,"a"); if(aCity[parseInt(sId.substr(0,2))]==null)return "Error:非法地区"; sBirthday=sId.substr(6,4)+"-"+Number(sId.substr(10,2))+"-"+Number(sId.substr(12,2)); var d=new Date(sBirthday.replace(/-/g,"/")) if(sBirthday!=(d.getFullYear()+"-"+ (d.getMonth()+1) + "-" + d.getDate()))return "Error:非法生日"; for(var i = 17;i&=0;i --) iSum += (Math.pow(2,i) % 11) * parseInt(sId.charAt(17 - i),11) if(iSum%11!=1)return "Error:非法证号"; return aCity[parseInt(sId.substr(0,2))]+","+sBirthday+","+(sId.substr(16,1)%2?"男":"女") } document.write(cidInfo("300016"),"&br/&"); document.write(cidInfo("300019"),"&br/&") document.write(cidInfo("111111"),"&br/&") document.write(cidInfo("01001x"),"&br/&"); &/script& 2.验证IP地址 &SCRIPT LANGUAGE="JavaScript"& function isip(s){ var check=function(v){try{return (v&=255 && v&=0)}catch(x){return false}}; var re=s.split(".") return (re.length==4)?(check(re[0]) && check(re[1]) && check(re[2]) && check(re[3])):false } var s="202.197.78.129"; alert(isip(s)) &/SCRIPT& 3.加sp1后还能用的无边框窗口!! &HTML XMLNS:IE& &meta http-equiv="Content-Type" content="text/ charset=gb2312"& &IE:Download ID="include" STYLE="behavior:url(#default#download)" /& &title&Chromeless Window&/title& &SCRIPT LANGUAGE="JScript"& /*--- Special Thanks For andot ---*/ /* This following code are designed and writen by Windy_sk && You can use it freely, but u must held all the copyright items! */ /*--- Thanks For andot Again ---*/ var CW_width = 400; var CW_height = 300; var CW_top = 100; var CW_left = 100; var CW_url = "/"; var New_CW = window.createPopup(); var CW_Body = New_CW.document. var content = ""; var CSStext = "margin:1color: border:2border-style:expression(onmouseout=onmouseup=function(){this.style.borderStyle='outset'}, onmousedown=function(){if(event.button!=2)this.style.borderStyle='inset'});background-color:width:16height:14font-size:12line-height:11cursor:D"; //Build Window include.startDownload(CW_url, function(source){content=source}); function insert_content(){ var temp = ""; CW_Body.style.overflow = "hidden"; CW_Body.style.backgroundColor = "white"; CW_Body.style.border = "solid black 1px"; content = content.replace(/&a ([^&]*)&/g,"&a onclick='parent.open(this.href);return false' $1&"); temp += "&table width=100% height=100% cellpadding=0 cellspacing=0 border=0&"; temp += "&tr style=';font-size:12background:#0099CC;height:20;cursor:default' ondblclick=/"Max.innerText=Max.innerText=='1'?'2':'1';parent.if_max=!parent.if_parent.show_CW();/" onmouseup='parent.drag_up(event)' onmousemove='parent.drag_move(event)' onmousedown='parent.drag_down(event)' onselectstart='return false' oncontextmenu='return false'&"; temp += "&td style='color:#padding-left:5px'&Chromeless Window For IE6 SP1&/td&"; temp += "&td style='color:#padding-right:5' align=right&"; temp += "&span id=Help onclick=/"alert('Chromeless Window For IE6 SP1 - Ver 1.0//n//nCode By Windy_sk//n//nSpecial Thanks For andot')/" style=/""+CSStext+"font-family:Spadding-right:2/"&?&/span&"; temp += "&span id=Min onclick='parent.New_CW.hide();parent.blur()' style=/""+CSStext+"font-family:W/" title='Minimum'&0&/span&"; temp += "&span id=Max onclick=/"this.innerText=this.innerText=='1'?'2':'1';parent.if_max=!parent.if_parent.show_CW();/" style=/""+CSStext+"font-family:W/" title='Maximum'&1&/span&"; temp += "&span id=Close onclick='parent.opener=parent.close()' style=/""+CSStext+"font-family:Spadding-right:2/" title='Close'&x&/span&"; temp += "&/td&&/tr&&tr&&td colspan=2&"; temp += "&div id=include style='overflow:overflow-x:overflow-y: HEIGHT: 100%; width:"+CW_width+"'&"; temp += temp += "&/div&"; temp += "&/td&&/tr&&/table&"; CW_Body.innerHTML = } setTimeout("insert_content()",1000); var if_max = function show_CW(){ window.moveTo(1); if(if_max){ New_CW.show(CW_top, CW_left, CW_width, CW_height); if(typeof(New_CW.document.all.include)!="undefined"){ New_CW.document.all.include.style.width = CW_ New_CW.document.all.Max.innerText = "1"; } }else{ New_CW.show(0, 0, screen.width, screen.height); New_CW.document.all.include.style.width = screen. } } window.onfocus = show_CW; window.onresize = show_CW; // Move Window var drag_x,drag_y,draging=false function drag_move(e){ if (draging){ New_CW.show(e.screenX-drag_x, e.screenY-drag_y, CW_width, CW_height);
} } function drag_down(e){ if(e.button==2) if(New_CW.document.body.offsetWidth==screen.width && New_CW.document.body.offsetHeight==screen.height) drag_x=e.clientX; drag_y=e.clientY; draging= e.srcElement.setCapture(); } function drag_up(e){ draging= e.srcElement.releaseCapture(); if(New_CW.document.body.offsetWidth==screen.width && New_CW.document.body.offsetHeight==screen.height) CW_top = e.screenX-drag_x; CW_left = e.screenY-drag_y; } &/SCRIPT& &/HTML& 电话号码的验证 要求:   (1)电话号码由数字、"("、")"和"-"构成   (2)电话号码为3到8位   (3)如果电话号码中包含有区号,那么区号为三位或四位   (4)区号用"("、")"或"-"和其他部分隔开   (5)移动电话号码为11或12位,如果为12位,那么第一位为0   (6)11位移动电话号码的第一位和第二位为"13"   (7)12位移动电话号码的第二位和第三位为"13"   根据这几条规则,可以与出以下正则表达式:   (^[0-9]{3,4}/-[0-9]{3,8}$)|(^[0-9]{3,8}$)|(^/([0-9]{3,4}/)[0-9]{3,8}$)|(^0{0,1}13[0-9]{9}$) &script language="javascript"& function PhoneCheck(s) { var str=s; var reg=/(^[0-9]{3,4}/-[0-9]{3,8}$)|(^[0-9]{3,8}$)|(^/([0-9]{3,4}/)[0-9]{3,8}$)|(^0{0,1}13[0-9]{9}$)/ alert(reg.test(str)); } &/script& &input type=text name="iphone"& &input type=button onclick="PhoneCheck(document.all.iphone.value)" value="Check"& 具有在输入非数字字符不回显的效果,即对非数字字符的输入不作反应。 function numbersonly(field,event){ var key, if(window.event){ key = window.event.keyC } else if (event){ key = event. } else{ return true } keychar = String.fromCharCode(key); if((key == null)||(key == 0)||(key == 8)||(key == 9)||(key == 13)||(key == 27)){
} else if((".").indexOf(keychar)&-1){ window.status = "";
} else { window.status = "Field excepts numbers only";
} } 验证ip str=document.RegExpDemo.txtIP. if(/^(/d{1,3})/.(/d{1,3})/.(/d{1,3})/.(/d{1,3})$/.test(str)==false) { window.alert('错误的IP地址格式'); document.RegExpDemo.txtIP.select(); document.RegExpDemo.txtIP.focus();
} if(RegExp.$1&1 || RegExp.$1&254||RegExp.$2&0||RegExp.$2&254||RegExp.$3&0||RegExp.$3&254||RegExp.$4&1||RegExp.$4&254) { window.alert('错误的IP地址'); document.RegExpDemo.txtIP.select(); document.RegExpDemo.txtIP.focus();
} //剔除 如 010.020.020.03 前面 的0 var str=str.replace(/0(/d)/g,"$1"); str=str.replace(/0(/d)/g,"$1"); window.alert(str); //一下是取数据的类 //Obj参数指定数据的来源(限定Table),默认第一行为字段名称行 //GetTableData类提供MoveNext方法,参数是表的行向上或向下移动的位数,正数向下移动,负数向上. //GetFieldData方法获得指定的列名的数据 //Sort_desc方法对指定的列按降序排列 //Sort_asc方法对指定的列按升序排列 //GetData方法返回字段值为特定值的数据数组,提供数据,可以在外部进行其他处理 //Delete方法删除当前记录,数组减少一行 //初始化,Obj:table的名字,Leftlen:左面多余数据长度,Rightlen:右面多余数据长度, function GetTableData(Obj,LeftLen,RightLen){ var MyObj=document.all(Obj); var iRow=MyObj.rows. var iLen=MyObj.rows[0].cells. var i,j; TableData=new Array(); for (i=0;i& iRi++){ TableData[i]=new Array(); for (j=0;j&iLj++){ TableStr=MyObj.rows(i).cells(j).innerT TableStr=TableStr.substring(LeftLen, TableStr.length-RightLen).Trim(); TableStr=TableStr.replace(/ /gi,"").replace(//r/n/ig,""); TableData[i][j]=TableS } } this.TableData=TableD this.cols=this.TableData[0]. this.rows=this.TableData. this.rowindex=0; } function movenext(Step){ if (this.rowindex&=this.rows){ return } if (Step=="" || typeof(Step)=="undefined") { if (this.rowindex&this.rows-1) this.rowindex++;
} else{ if (this.rowindex + Step&=this.rows-1 && this.rowindex + Step&=0 ){ this.rowindex=this.rowindex + S } else { if (this.rowindex + Step&0){ this.rowindex= 0;
} if (this.rowindex + Step&this.rows-1){ this.rowindex= this.rows-1;
} } } } function getfielddata(Field){ var colindex=-1; var i=0; if (typeof(Field) == "number"){ colindex=F } else { for (i=0;i&this.cols && this.rowindex&this.i++){ if (this.TableData[0][i]==Field){ colindex=i;
} } } if (colindex!=-1) { return this.TableData[this.rowindex][colindex]; } } function sort_desc(){//降序 var colindex=-1; var highindex=-1; desc_array=new Array(); var i,j; for (n=0; n&arguments. n++){ Field=arguments[arguments.length-1-n]; for (i=0;i&this.i++){ if (this.TableData[0][i]==Field){ colindex=i;
} } if ( colindex==-1 )
else { desc_array[0]=this.TableData[0]; for(i=1;i&this.i++){ desc_array[i]=this.TableData[1]; highindex=1; for(j=1;j&this.TableData.j++){ if (desc_array[i][colindex]&this.TableData[j][colindex]){ desc_array[i]=this.TableData[j]; highindex=j; } } if (highindex!=-1) this.TableData=this.TableData.slice(0,highindex).concat(this.TableData.slice(highindex+1,this.TableData.length)); } } this.TableData=desc_ }
} function sort_asc(){//升序 var colindex=-1; var highindex=-1; var i,j; for (n=0; n&arguments. n++){ asc_array=new Array(); Field=arguments[arguments.length-1-n]; for (i=0;i&this.i++){ if (this.TableData[0][i]==Field){ colindex=i;
} } if ( colindex==-1 )
else { asc_array[0]=this.TableData[0]; for(i=1;i&this.i++){ asc_array[i]=this.TableData[1]; highindex=1; for(j=1;j&this.TableData.j++){//找出最小的列值 if (asc_array[i][colindex]&this.TableData[j][colindex]){ asc_array[i]=this.TableData[j]; highindex=j; } } if (highindex!=-1) this.TableData=this.TableData.slice(0,highindex).concat(this.TableData.slice(highindex+1,this.TableData.length)); } } this.TableData=asc_ }
} function getData(Field,FieldValue){ var colindex=-1; var i,j; GetData=new Array(); if (typeof(Field)=="undefined" || typeof(FieldValue)=="undefined" ){ return this.TableD } for(j=0;j&this.j++){ if (this.TableData[0][j]==Field){ colindex=j; } } if (colindex!=-1){ for(i=1;i&this.i++){ if (this.TableData[i][colindex]==FieldValue){ GetData[i]=new Array(); GetData[i]=this.TableData[i]; } } } return GetD } function DeletE(){ this.TableData=this.TableData.slice(0,this.rowindex).concat(this.TableData.slice(this.rowindex+1,this.TableData.length)); this.rows=this.TableData.
} function updateField(Field,FieldValue){ var colindex=-1; var i=0; if (typeof(Field) == "number"){ colindex=F } else { for (i=0;i&this.cols && this.rowindex&this.i++){ if (this.TableData[0][i]==Field){ colindex=i;
} } } if (colindex!=-1) { this.TableData[this.rowindex][colindex]=FieldV } } function movefirst(){ this.rowindex=0; } function movelast(){ this.rowindex=this.rows-1; } function String.prototype.Trim() {return this.replace(/(^/s*)|(/s*$)/g,"");} GetTableData.prototype.MoveNext = GetTableData.prototype.GetFieldData = GetTableData.prototype.Sort_asc = sort_ GetTableData.prototype.Sort_desc = sort_ GetTableData.prototype.GetData = getD GetTableData.prototype.Delete = DeletE; GetTableData.prototype.UpdateField = updateF GetTableData.prototype.MoveFirst = 具体的例子: 在每个文本框的onblur事件中调用校验代码,并且每个文本框中onKeyDown事件中写一个enter转tab函数 //回车键换为tab function enterToTab() { if(event.srcElement.type != 'button' && event.srcElement.type != 'textarea' && event.keyCode == 13) { event.keyCode = 9; } }&
declare @i bigint,@j int,@str nvarchar(160) ,@int_temp int,@str_temp nvarchar(10),@Card_NO nvarchar(10) ;set @i = ;while (@i&=)beginset @j = 0;set @str='';while (@j&=16)beginset @int_temp=rand()*9;set @str_temp=str(@int_temp);set @str=@str+@str_set @j=@j+1;end set @Card_NO=str(@i); set @str=replace(@str,' ','');insert into IN_Card (Card_No,[Password],[Value])values(@Card_NO,@str,100); set @i=@i+1;
& 最近在用Asp.Net编写点东西时遇到个问题:即用户在提交表单后按刷新就会重复提交数据,即所谓的&刷新重复提交&的问题。在网上搜 一下,可以找到很多关于这方面的资料,其中有一篇是来自MSDN上的一种解决方法:
它是通过重新定义 System.Web.UI.Page 类来实现加载页面时,是&刷新&、&后退&请求,还是正常请求,其他的页面则继承了自定义的这 个Page类。感觉他这个方法比较独特,有例子可以下载,有兴趣的可以研究研究。 网上最多的解决此类问题的方法就是不保存缓存,即提交后表单上的数据不会被浏览器的缓存保存,如果此时再遇到刷新或者后退请求时, 就会显示&网页已过期&,数据也就不会重复提交了,这就起到了阻止刷新重复提交的效果。 下面以简单的提交一篇帖子为例,介绍禁用缓存防止刷新重复提交的方法,表单数据包括&标题&和&正文&两个部分。 以下是该方法的代码(post.aspx):
//页面加载 protected void Page_Load(object sender, EventArgs e) { & &//可以在页面加载时设置页面的缓存为&SetNoStore()&,即无缓存 & &Response.Cache.SetNoStore(); & &//Session中存储的变量&IsSubmit&是标记是否提交成功的 & &if ((bool)Session["IsSubmit"]) & &{ & &&&//如果表单数据提交成功,就设&Session["IsSubmit"]&为false & &&&Session["IsSubmit"] = & &&&//显示提交成功信息 & &&&ShowMsg.Text = " * 提交成功!"; & &} & &else & &&&//否则的话(没有提交,或者是页面刷新),不显示任何信息 & &&&ShowMsg.Text = ""; } //提交按钮(btnOK)单击事件 protected void btnOK_Click(object sender, EventArgs e) { & &if (txtTitle.Text.ToString().Trim() == "") & &&&//ShowMsg是用来显示提示信息的 & &&&ShowMsg.Text = " * 标题不能为空!"; &&else if (txtText.Text.ToString().Trim() == "") & &&&ShowMsg.Text = " * 内容不能为空!"; &&else & &{ & &&&//这里是将数据提交到数据库中,省略 & &&&/* & &&&string sql = "insert into tab...values(...)"; & &&&MyConn.ExecQuery(sql); & &&&*/ & &&&//提交成功后,设&Session["IsSubmit"]&为true & &&&Session["IsSubmit"] = & &&&//强制转换页面(不可少,否则刷新仍会重复提交,仍转到本页), & &&&通过页面的转换将缓存中的提交的数据都释放了,即提交的标单数据不会被保存到缓存里, & &&&如果后退的话,将会出现该页无法显示 & &&&Response.Redirect("post.aspx"); &&} }
上面这个方法非常简单也很实用,推荐大家使用。 下面是我自己研究出来的另一种方法,该方法不同于&不保存缓存的方法&,它是让浏览器保存所有页面缓存的。该方法通过随机码的方式 来判断是正常提交还是&刷新&或&后退&的。 首先(提交页面是post.aspx)在 Session 中 增加变量 Rnd 用来存放随机码,同时在提交表单数据时不做处理,而是让页面转到 post.aspx?r=x,这里&x&等于Session["Rnd"],这个时候在页面加载时,通过判断r的值和Session["Rnd"]的值是否相同,如果相同就处理提 交的数据,否则即可认为是&刷新&或者是&后退&操作了,最后再次付给Session["Rnd"]一个随机码。 以下是该方法代码(post.aspx):
//获取随机码 public class MyRnd { & &public static string Rnd() & &{ & &&&//随机码是由 0-9 a-z A-Z 之间的数字或字母组成的 & &&&//下面是生成的20位随机码 & &&&//0..9 A..Z a..z & &&&//48-57 65-90 97-122 & &&&string rst = ""; & &&&Random rr = new Random(); & &&&for (int i = 0; i & 20; i++) & &&&{ & && & int ir = 0; & && & do & && & { & && && &ir = rr.Next(123); & && && &if((ir &= 48) && (ir &= 57)) & && && &else if((ir &= 65) && (ir &= 90)) & && && &else if ((ir &= 97) && (ir &= 122)) & && & } & && & while (true); & && & rst += ((char)ir).ToString(); & && & } & &&& & &} } //页面加载 protected void Page_Load(object sender, EventArgs e) { & &//获取URL中请求的&r&值,如果&r&不存在则 r="" & &string r = ""; & &if(Request.QueryString["r"] != null) & &&&r = Request.QueryString["r"].ToString().Trim(); & & & &//获取 &Session& 中的 &Rnd& 值,用于和&r&比较 & &t = Session["Rnd"].ToString().Trim(); & &//如果&r=t&则为提交操作,即可对表单的数据进行处理 &&if(r == t) &&{ & &&&if (txtTitle.Text.ToString().Trim() == "") & && & ShowMsg.Text = " * 标题不能为空!"; & &&&else if (txtText.Text.ToString().Trim() == "") & && & ShowMsg.Text = " * 内容不能为空!"; & &&&else& && &{ & && & //这里是将数据提交到数据库中,省略 & && & /* & && & string sql = "insert into tab...values(...)"; & && & MyConn.ExecQuery(sql); & && & */ & && & //提交成功后清空表单数据 & && & txtTitle.Text = ""; & && & txtText.Text = ""; & && & //显示提交成功信息 & && & ShowMsg.Text = " * 提交成功!"; & &&&} &&} & &//否则可以认为是&刷新&或者&后退&操作 & &else & &{ & && & txtTitle.Text = ""; & && & txtText.Text = ""; &&} &&//最后要重新获得&Session["Rnd"]&的值,并将&btnOK.PostBackUrl&设为&Session["Rnd"]&的值 &&Session["Rnd"] = MyRnd.Rnd(); &&btnOK.PostBackUrl ="post.aspx?r=" + Session["Rnd"].ToString().Trim(); } //这里提交按钮(btnOK)单击事件就不需要写任何代码了
通过这种方法,每次加载页面时&Session["Rnd"]&都将得到一个新的值,而在刷新或后退时就不会得到相同的&r&和&t&值,数据也就 不会被重复提交,只有通过&btnOK&来提交的操作才会得到&r==t&,数据才会被提交处理的,通过判断随机码的方式来阻止刷新重复提交就 可以实现了。
有时,为了让应用程序运行得更快,所做的全部工作就是在这里或那里做一些很小调整。但关键在于确定如何进行调整!迟早您会遇到这种情况:应用程序中的 SQL 查询不能按照您想要的方式进行响应。它要么不返回数据,要么耗费的时间长得出奇。如果它降低了企业应用程序的速度,用户必须等待很长时间。用户希望应用程序响应迅速,他们的报告能够在瞬间之内返回分析数据。就我自己而言,如果在Web上冲浪时某个页面要耗费十多秒才能加载,我也会很不耐烦。
  为了解决这些问题,重要的是找到问题的根源。那么,从哪里开始呢?根本原因通常在于数据库设计和访问它的查询。我将讲述四项技术,这些技术可用于提高基于SQL Server的应用程序的性能或改善其可伸缩性。我将仔细说明 LEFT JOIN、CROSS JOIN 的使用以及IDENTITY 值的检索。请记住,根本没有神奇的解决方案。调整您的数据库及其查询需要占用时间、进行分析,还需要大量的测试。这些技术都已被证明行之有效,但对您的应用程序而言,可能其中一些技术比另一些技术更适用。
  从 INSERT 返回 IDENTITY
  我决定从遇到许多问题的内容入手:如何在执行SQL INSERT后检索IDENTITY值。通常,问题不在于如何编写检索值的查询,而在于在哪里以及何时进行检索。在SQL Server中,下面的语句可用于检索由最新在活动数据库连接上运行的 SQL 语句所创建的 IDENTITY 值:
  SELECT @@IDENTITY
  这个 SQL 语句并不复杂,但需要记住的一点是:如果这个最新的 SQL 语句不是 INSERT,或者您针对非 INSERT SQL 的其他连接运行了此 SQL,则不会获得期望的值。您必须运行下列代码才能检索紧跟在 INSERT SQL 之后且位于同一连接上的 IDENTITY,如下所示:
  INSERT INTO Products (ProductName) VALUES ('Chalk')
  SELECT @@IDENTITY
  在一个连接上针对 Northwind 数据库运行这些查询将返回一个名称为 Chalk 的新产品的 IDENTITY 值。所以,在使用ADOVisual Basic应用程序中,可以运行以下语句:
  Set oRs = oCn.Execute("SET NOCOUNT ON;INSERT INTO Products _
  (ProductName) VALUES ('Chalk');SELECT @@IDENTITY")
  lProductID = oRs(0) 
  此代码告诉 SQL Server 不要返回查询的行计数,然后执行 INSERT 语句,并返回刚刚为这个新行创建的 IDENTITY 值。SET NOCOUNT ON 语句表示返回的记录集有一行和一列,其中包含了这个新的 IDENTITY 值。如果没有此语句,则会首先返回一个空的记录集(因为 INSERT 语句不返回任何数据),然后会返回第二个记录集,第二个记录集中包含 IDENTITY 值。这可能有些令人困惑,尤其是因为您从来就没有希望过 INSERT 会返回记录集。之所以会发生此情况,是因为 SQL Server 看到了这个行计数(即一行受到影响)并将其解释为表示一个记录集。因此,真正的数据被推回到了第二个记录集。当然您可以使用 ADO 中的 NextRecordset 方法获取此第二个记录集,但如果总能够首先返回该记录集且只返回该记录集,则会更方便,也更有效率。
  此方法虽然有效,但需要在 SQL 语句中额外添加一些代码。获得相同结果的另一方法是在 INSERT 之前使用 SET NOCOUNT ON 语句,并将 SELECT @@IDENTITY 语句放在表中的 FOR INSERT 触发器中,如下面的代码片段所示。这样,任何进入该表的 INSERT 语句都将自动返回 IDENTITY 值。
  CREATE TRIGGER trProducts_Insert ON Products FOR INSERT AS
  SELECT @@IDENTITY
  触发器只在 Products 表上发生 INSERT 时启动,所以它总是会在成功 INSERT 之后返回一个 IDENTITY。使用此技术,您可以始终以相同的方式在应用程序中检索 IDENTITY 值。
内嵌视图与临时表
  某些时候,查询需要将数据与其他一些可能只能通过执行 GROUP BY 然后执行标准查询才能收集的数据进行联接。例如,如果要查询最新五个定单的有关信息,您首先需要知道是哪些定单。这可以使用返回定单 ID 的 SQL 查询来检索。此数据就会存储在临时表(这是一个常用技术)中,然后与 Products 表进行联接,以返回这些定单售出的产品数量:
  CREATE TABLE #Temp1 (OrderID INT NOT NULL, _
  OrderDate DATETIME NOT NULL)
  INSERT INTO #Temp1 (OrderID, OrderDate)
  SELECT TOP 5 o.OrderID, o.OrderDate
  FROM Orders o ORDER BY o.OrderDate DESC
  SELECT p.ProductName, SUM(od.Quantity) AS ProductQuantity
  FROM #Temp1 t
  INNER JOIN [Order Details] od ON t.OrderID = od.OrderID
  INNER JOIN Products p ON od.ProductID = p.ProductID
  GROUP BY p.ProductName
  ORDER BY p.ProductName
  DROP TABLE #Temp1
  这些 SQL 语句会创建一个临时表,将数据插入该表中,将其他数据与该表进行联接,然后除去该临时表。这会导致此查询进行大量 I/O 操作,因此,可以重新编写查询,使用内嵌视图取代临时表。内嵌视图只是一个可以联接到 FROM 子句中的查询。所以,您不用在 tempdb 中的临时表上耗费大量 I/O 和磁盘访问,而可以使用内嵌视图得到同样的结果:
  SELECT p.ProductName,
  SUM(od.Quantity) AS ProductQuantity
  FROM (
  SELECT TOP 5 o.OrderID, o.OrderDate
  FROM Orders o
  ORDER BY o.OrderDate DESC
  INNER JOIN [Order Details] od ON t.OrderID = od.OrderID
  INNER JOIN Products p ON od.ProductID = p.ProductID
  GROUP BY
  p.ProductName
  ORDER BY
  p.ProductName
  此查询不仅比前面的查询效率更高,而且长度更短。临时表会消耗大量资源。如果只需要将数据联接到其他查询,则可以试试使用内嵌视图,以节省资源。
  避免 LEFT JOIN 和 NULL
  当然,有很多时候您需要执行 LEFT JOIN 和使用 NULL 值。但是,它们并不适用于所有情况。改变 SQL 查询的构建方式可能会产生将一个花几分钟运行的报告缩短到只花几秒钟这样的天壤之别的效果。有时,必须在查询中调整数据的形态,使之适应应用程序所要求的显示方式。虽然 TABLE 数据类型会减少大量占用资源的情况,但在查询中还有许多区域可以进行优化。SQL 的一个有价值的常用功能是 LEFT JOIN。它可以用于检索第一个表中的所有行、第二个表中所有匹配的行、以及第二个表中与第一个表不匹配的所有行。例如,如果希望返回每个客户及其定单,使用 LEFT JOIN 则可以显示有定单和没有定单的客户。
  此工具可能会被过度使用。LEFT JOIN 消耗的资源非常之多,因为它们包含与 NULL(不存在)数据匹配的数据。在某些情况下,这是不可避免的,但是代价可能非常高。LEFT JOIN 比 INNER JOIN 消耗资源更多,所以如果您可以重新编写查询以使得该查询不使用任何 LEFT JOIN,则会得到非常可观的回报。
  加快使用 LEFT JOIN 的查询速度的一项技术涉及创建一个 TABLE 数据类型,插入第一个表(LEFT JOIN 左侧的表)中的所有行,然后使用第二个表中的值更新 TABLE 数据类型。此技术是一个两步的过程,但与标准的 LEFT JOIN 相比,可以节省大量时间。一个很好的规则是尝试各种不同的技术并记录每种技术所需的时间,直到获得用于您的应用程序的执行性能最佳的查询。
  测试查询的速度时,有必要多次运行此查询,然后取一个平均值。因为查询(或存储过程)可能会存储在 SQL Server 内存中的过程缓存中,因此第一次尝试耗费的时间好像稍长一些,而所有后续尝试耗费的时间都较短。另外,运行您的查询时,可能正在针对相同的表运行其他查询。当其他查询锁定和解锁这些表时,可能会导致您的查询要排队等待。例如,如果您进行查询时某人正在更新此表中的数据,则在更新提交时您的查询可能需要耗费更长时间来执行。
  避免使用 LEFT JOIN 时速度降低的最简单方法是尽可能多地围绕它们设计数据库。例如,假设某一产品可能具有类别也可能没有类别。如果 Products 表存储了其类别的 ID,而没有用于某个特定产品的类别,则您可以在字段中存储 NULL 值。然后您必须执行 LEFT JOIN 来获取所有产品及其类别。您可以创建一个值为&No Category&的类别,从而指定外键关系不允许 NULL 值。通过执行上述操作,现在您就可以使用 INNER JOIN 检索所有产品及其类别了。虽然这看起来好像是一个带有多余数据的变通方法,但可能是一个很有价值的技术,因为它可以消除 SQL 批处理语句中消耗资源较多的 LEFT JOIN。在数据库中全部使用此概念可以为您节省大量的处理时间。请记住,对于您的用户而言,即使几秒钟的时间也非常重要,因为当您有许多用户正在访问同一个联机数据库应用程序时,这几秒钟实际上的意义会非常重大。
灵活使用笛卡尔乘积
  对于此技巧,我将进行非常详细的介绍,并提倡在某些情况下使用笛卡尔乘积。出于某些原因,笛卡尔乘积 (CROSS JOIN) 遭到了很多谴责,开发人员通常会被警告根本就不要使用它们。在许多情况下,它们消耗的资源太多,从而无法高效使用。但是像 SQL 中的任何工具一样,如果正确使用,它们也会很有价值。例如,如果您想运行一个返回每月数据(即使某一特定月份客户没有定单也要返回)的查询,您就可以很方便地使用笛卡尔乘积。
  虽然这看起来好像没什么神奇的,但是请考虑一下,如果您从客户到定单(这些定单按月份进行分组并对销售额进行小计)进行了标准的 INNER JOIN,则只会获得客户有定单的月份。因此,对于客户未订购任何产品的月份,您不会获得 0 值。如果您想为每个客户都绘制一个图,以显示每个月和该月销售额,则可能希望此图包括月销售额为 0 的月份,以便直观标识出这些月份。如果使用 Figure 2(最后一页) 中的 SQL,数据则会跳过销售额为 0 美元的月份,因为在定单表中对于零销售额不会包含任何行(假设您只存储发生的事件)。
  Figure 3(最后一页)中的代码虽然较长,但是可以达到获取所有销售数据(甚至包括没有销售额的月份)的目标。首先,它会提取去年所有月份的列表,然后将它们放入第一个 TABLE 数据类型表 (@tblMonths) 中。下一步,此代码会获取在该时间段内有销售额的所有客户公司的名称列表,然后将它们放入另一个 TABLE 数据类型表 (@tblCus-tomers) 中。这两个表存储了创建结果集所必需的所有基本数据,但实际销售数量除外。 第一个表中列出了所有月份(12 行),第二个表中列出了这个时间段内有销售额的所有客户(对于我是 81 个)。并非每个客户在过去 12 个月中的每个月都购买了产品,所以,执行 INNER JOIN 或 LEFT JOIN 不会返回每个月的每个客户。这些操作只会返回购买产品的客户和月份。
  笛卡尔乘积则可以返回所有月份的所有客户。笛卡尔乘积基本上是将第一个表与第二个表相乘,生成一个行集合,其中包含第一个表中的行数与第二个表中的行数相乘的结果。因此,笛卡尔乘积会向表 @tblFinal 返回 972 行。最后的步骤是使用此日期范围内每个客户的月销售额总计更新 @tblFinal 表,以及选择最终的行集。
  如果由于笛卡尔乘积占用的资源可能会很多,而不需要真正的笛卡尔乘积,则可以谨慎地使用 CROSS JOIN。例如,如果对产品和类别执行了 CROSS JOIN,然后使用 WHERE 子句、DISTINCT 或 GROUP BY 来筛选出大多数行,那么使用 INNER JOIN 会获得同样的结果,而且效率高得多。如果需要为所有的可能性都返回数据(例如在您希望使用每月销售日期填充一个图表时),则笛卡尔乘积可能会非常有帮助。但是,您不应该将它们用于其他用途,因为在大多数方案中 INNER JOIN 的效率要高得多。
  拾遗补零
  这里介绍其他一些可帮助提高 SQL 查询效率的常用技术。假设您将按区域对所有销售人员进行分组并将他们的销售额进行小计,但是您只想要那些数据库中标记为处于活动状态的销售人员。您可以按区域对销售人员分组,并使用 HAVING 子句消除那些未处于活动状态的销售人员,也可以在 WHERE 子句中执行此操作。在 WHERE 子句中执行此操作会减少需要分组的行数,所以比在 HAVING 子句中执行此操作效率更高。HAVING 子句中基于行的条件的筛选会强制查询对那些在 WHERE 子句中会被去除的数据进行分组。
  另一个提高效率的技巧是使用 DISTINCT 关键字查找数据行的单独报表,来代替使用 GROUP BY 子句。在这种情况下,使用 DISTINCT 关键字的 SQL 效率更高。请在需要计算聚合函数(SUM、COUNT、MAX 等)的情况下再使用 GROUP BY。另外,如果您的查询总是自己返回一个唯一的行,则不要使用 DISTINCT 关键字。在这种情况下,DISTINCT 关键字只会增加系统开销。
  您已经看到了,有大量技术都可用于优化查询和实现特定的业务规则,技巧就是进行一些尝试,然后比较它们的性能。最重要的是要测试、测试、再测试。
Figure 2 Returning All Customers and Their Sales
set nocount on
DECLARE @dtStartDate DATETIME,
@dtEndDate DATETIME,
@dtDate DATETIME
SET @dtEndDate = '5/5/1997'
SET @dtEndDate = DATEADD(DD, -1, CAST(CAST((MONTH(@dtEndDate) + 1)
AS VARCHAR(2)) + '/01/' + CAST(YEAR(@dtEndDate) AS VARCHAR(4)) + '
23:59:59' AS DATETIME))
SET @dtStartDate = DATEADD(MM, -1 * 12, @dtEndDate)
SELECT CAST(YEAR(o.OrderDate) AS VARCHAR(4)) + '-' +
WHEN MONTH(o.OrderDate) & 10
THEN '0' + CAST(MONTH(o.OrderDate) AS VARCHAR(2))
ELSE CAST(MONTH(o.OrderDate) AS VARCHAR(2))
END AS sMonth,
c.CustomerID,
c.CompanyName,
c.ContactName,
SUM(od.Quantity * od.UnitPrice) AS mSales
FROM Customers c
INNER JOIN Orders o ON c.CustomerID = o.CustomerID
INNER JOIN [Order Details] od ON o.OrderID = od.OrderID
WHERE o.OrderDate BETWEEN @dtStartDate AND @dtEndDate
CAST(YEAR(o.OrderDate) AS VARCHAR(4)) + '-' +
WHEN MONTH(o.OrderDate) & 10
THEN '0' + CAST(MONTH(o.OrderDate) AS VARCHAR(2))
ELSE CAST(MONTH(o.OrderDate) AS VARCHAR(2))
c.CustomerID,
c.CompanyName,
c.ContactName
c.CompanyName,
sMonth-------------------------------------------------------------------------------------------------------------------------------------
Figure 3 Cartesian Product at Work
DECLARE @tblMonths TABLE (sMonth VARCHAR(7))
DECLARE @tblCustomers TABLE ( CustomerID CHAR(10),
CompanyName VARCHAR(50),
ContactName VARCHAR(50))
DECLARE @tblFinal TABLE ( sMonth VARCHAR(7),
CustomerID CHAR(10),
CompanyName VARCHAR(50),
ContactName VARCHAR(50),
mSales MONEY)
DECLARE @dtStartDate DATETIME,
@dtEndDate DATETIME,
@dtDate DATETIME,
@i INTEGER
SET @dtEndDate = '5/5/1997'
SET @dtEndDate = DATEADD(DD, -1, CAST(CAST((MONTH(@dtEndDate) + 1) AS
VARCHAR(2)) + '/01/' + CAST(YEAR(@dtEndDate) AS VARCHAR(4)) + '
23:59:59' AS DATETIME))
SET @dtStartDate = DATEADD(MM, -1 * 12, @dtEndDate)
& Get all months into the first table
SET @i = 0
WHILE (@i & 12)
SET @dtDate = DATEADD(mm, -1 * @i, @dtEndDate)
INSERT INTO @tblMonths SELECT CAST(YEAR(@dtDate) AS VARCHAR(4)) + '-' +
WHEN MONTH(@dtDate) & 10
THEN '0' + CAST(MONTH(@dtDate) AS VARCHAR(2))
ELSE CAST(MONTH(@dtDate) AS VARCHAR(2))
END AS sMonth
SET @i = @i + 1
& Get all clients who had sales during that period into the "y" table
INSERT INTO @tblCustomers
SELECT DISTINCT
c.CustomerID,
c.CompanyName,
c.ContactName
FROM Customers c
INNER JOIN Orders o ON c.CustomerID = o.CustomerID
WHERE o.OrderDate BETWEEN @dtStartDate AND @dtEndDate
INSERT INTO @tblFinal
SELECT m.sMonth,
c.CustomerID,
c.CompanyName,
c.ContactName,
FROM @tblMonths m CROSS JOIN @tblCustomers c
UPDATE @tblFinal SET
mSales = mydata.mSales
FROM @tblFinal f INNER JOIN
SELECT c.CustomerID,
CAST(YEAR(o.OrderDate) AS VARCHAR(4)) + '-' +
CASE WHEN MONTH(o.OrderDate) & 10
THEN '0' + CAST(MONTH(o.OrderDate) AS VARCHAR(2))
ELSE CAST(MONTH(o.OrderDate) AS VARCHAR(2))
END AS sMonth,
SUM(od.Quantity * od.UnitPrice) AS mSales
FROM Customers c
INNER JOIN Orders o ON c.CustomerID = o.CustomerID
INNER JOIN [Order Details] od ON o.OrderID = od.OrderID
WHERE o.OrderDate BETWEEN @dtStartDate AND @dtEndDate
c.CustomerID,
CAST(YEAR(o.OrderDate) AS VARCHAR(4)) + '-' +
CASE WHEN MONTH(o.OrderDate) & 10
THEN '0' + CAST(MONTH(o.OrderDate) AS VARCHAR(2))
ELSE CAST(MONTH(o.OrderDate) AS VARCHAR(2))
) mydata on f.CustomerID = mydata.CustomerID AND f.sMonth =
mydata.sMonth
SELECT f.sMonth,
f.CustomerID,
f.CompanyName,
f.ContactName,
FROM @tblFinal f
f.CompanyName,
首先介绍一下什么是存储过程:存储过程就是将常用的或很复杂的工作,预先用SQL语句写好并用一个指定的名称存储起来,并且这样的语句是放在数据库中的,还可以根据条件执行不同SQL语句,那么以后要叫数据库提供与已定义好的存储过程的功能相同的服务时,只需调用execute,即可自动完成命令。  请大家来了解一下存储过程的语法。  CREATE PROC [ EDURE ] procedure_name [ ; number ][ { @parameter data_type }[ VARYING ] [ = default ] [ OUTPUT ]] [ ,...n ]  [ WITH{ RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION } ]  [ FOR REPLICATION ]  AS sql_statement [ ...n ]  参数:  procedure_name  新存储过程的名称。过程名必须符合标识符规则,且对于数据库及其所有者必须唯一。  要创建局部临时过程,可以在 procedure_name 前面加一个编号符 (#procedure_name),要创建全局临时过程,可以在 procedure_name 前面加两个编号符 (##procedure_name)。完整的名称(包括 # 或 ##)不能超过 128 个字符。指定过程所有者的名称是可选的。  ;number  是可选的整数,用来对同名的过程分组,以便用一条 DROP PROCEDURE 语句即可将同组的过程一起除去。例如,名为 orders 的应用程序使用的过程可以命名为1、2 等。DROP PROCEDURE orderproc 语句将除去整个组。如果名称中包含定界标识符,则数字不应包含在标识符中,只应在 procedure_name 前后使用适当的定界符。  @parameter  过程中的参数。在 CREATE PROCEDURE 语句中可以声明一个或多个参数。用户必须在执行过程时提供每个所声明参数的值(除非定义了该参数的默认值)。存储过程最多可以有 2100 个参数。  使用@符号作为第一个字符来指定参数名称。参数名称必须符合标识符的规则。每个过程的参数仅用于该过程本身;相同的参数名称可以用在其它过程中。默认情况下,参数只能代替常量,而不能用于代替表名、列名或其它数据库对象的名称。  data_type  参数的数据类型。所有数据类型(包括 text、ntext 和 image)均可以用作存储过程的参数。不过,cursor 数据类型只能用于 OUTPUT 参数。如果指定的数据类型为 cursor,也必须同时指定 VARYING 和 OUTPUT 关键字。  说明:对于可以是cursor 数据类型的输出参数,没有最大数目的限制。VARYING  指定作为输出参数支持的结果集(由存储过程动态构造,内容可以变化)。仅适用于游标参数。  default  参数的默认值。如果定义了默认值,不必指定该参数的值即可执行过程。默认值必须是常量或 NULL。如果过程将对该参数使用 LIKE 关键字,那么默认值中可以包含通配符(%、_、[] 和 [^])。  OUTPUT  表明参数是返回参数。该选项的值可以返回给 EXEC[UTE]。使用 OUTPUT 参数可将信息返回给调用过程。Text、ntext 和 image 参数可用作 OUTPU}

我要回帖

更多关于 物理层接口特性 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信