发布日期:2006年07月30日,更新日期:2006年07月30日
1996年初,欧洲安全电子市场(EU SEMPER)项目组决定编写自己的日志记录API,后来这个API演变成了Log4j。Log4j是一个开放源码项目,一个非常流行的Java日志记录包。它允许开发者向代码中插入日志记录语句,还允许在不修改应用程序源码的情况下修改记录日志的行为。
1996年初,欧洲安全电子市场(EU SEMPER)项目组决定编写自己的日志记录API,后来这个API演变成了Log4j。Log4j是一个开放源码项目,一个非常流行的Java日志记录包。它允许开发者向代码中插入日志记录语句,还允许在不修改应用程序源码的情况下修改日志记录的行为。
几乎每一个项目都会使用日志记录,但是由于日志记录不是项目的核心,因此受重视的程度一般不是很高。我们认为使用日志记录是一件非常严肃的事情,而且做好使用日志记录的规划比单纯记录日志本身更加重要。
本文将比较全面的阐述Log4j的设计原理和使用方法。
日志记录记录的是应用程序运行的轨迹。我们可以通过查看这些轨迹来调试应用程序,这可能也是日志记录最为流行的用法了。但是我们必须意识到规划良好的日志记录中还含有丰富的信息,通过手工的方式或借助一些工具(大多数时候需要自己来书写这些工具)来分析挖掘这些信息。
例如,如果我们在规划中指出必须记录用户的每一次操作,记录的样式为 [日志信息]-[操作开始的时间]-[日志级别]-[日志类别]-[用户名]-[操作名]-[消息],这只是我们假设的一种样式,实际的日志中一般会含有比这更加丰富的信息。为了更好的理解,我们根据该样式构造了一些日志记录(其中日志类别org.solol.Main、org.solol.Parser和org.solol.UserOperator使用了不同的样式):
[日志信息]-[2006-07-30 08:54:20]-[INFO]-[org.solol.Main]-[具体的消息]
[日志信息]-[2006-07-30 08:55:20]-[INFO]-[org.solol.UserOperator]-[User1]-[查询报表1]-[具体的消息]
[日志信息]-[2006-07-30 08:55:30]-[INFO]-[org.solol.UserOperator]-[User1]-[查询报表2]-[具体的消息]
[日志信息]-[2006-07-30 08:56:01]-[INFO]-[org.solol.Parser]-[具体的消息]
[日志信息]-[2006-07-30 08:57:26]-[INFO]-[org.solol.UserOperator]-[User2]-[添加用户User3]-[具体的消息]
[日志信息]-[2006-07-30 08:58:20]-[INFO]-[org.solol.UserOperator]-[User1]-[查询报表3]-[具体的消息]
[日志信息]-[2006-07-30 08:59:38]-[INFO]-[org.solol.UserOperator]-[User3]-[查询报表1]-[具体的消息]
[日志信息]-[2006-07-30 08:59:39]-[INFO]-[org.solol.UserOperator]-[User2]-[退出系统]-[具体的消息]
从上面的日志记录中我们很容易抽取出某一用户的操作列表,如对于用户User1我们的结果为:
[日志信息]-[2006-07-30 08:55:20]-[INFO]-[org.solol.UserOperator]-[User1]-[查询报表1]-[具体的消息]
[日志信息]-[2006-07-30 08:55:30]-[INFO]-[org.solol.UserOperator]-[User1]-[查询报表2]-[具体的消息]
[日志信息]-[2006-07-30 08:58:20]-[INFO]-[org.solol.UserOperator]-[User1]-[查询报表3]-[具体的消息]
这样我们就得到了某一时间段中User1的操作列表,可以利用这一列表来进行安全分析。
我们还可以从另外的角度来分析上面的日志记录,如我们很容易统计出操作(日志类别为org.solol.UserOperator)发生的总次数(6次),其中操作[查询报表1]为2次,[查询报表2]为1次,[查询报表3]为1次,[添加用户User3]为1次,[退出系统]为1次。这样我们就可以得出系统中的那些操作用户使用的比较频繁。
以上我们从两个角度对日记记录中的信息进行了简单的挖掘,实际中待挖掘的方面要丰富的多,这取决于您的意图和您的想象力。
这里我们还要特别强调一下:所有这一切都需要有使用日志记录的良好规划。如果规划不好(即日志记录没有规律性),那么我们挖掘时的任务就会非常繁重或者使挖掘成为一个不可能的任务。
文章到了这里我们要来描述日志记录的最为流行的用法了,即调试应用程序。我们在调试应用程序时一般会使用两种方法,除了日志记录之外,还有debugger调试器。
我们不想把他们放到一起来描述,因为这是两个完全不同的问题,虽然他们都用来调试应用程序。使用debugger调试器我们可以清楚的知道引发错误的上下文及其相关信息,也可以使用单步执行、设置断点、检查变量以及暂挂和恢复线程等等比较高级的能力,但是尽管这样它也不能替代日志记录,同样日志记录也不能替代debugger调试器。我们要结合使用这两种方法,不同的场景使用不同的方法会有更好的效果。
我们认为使用日志记录来调试应用程也应该充分考虑软件的开发周期。这里我们只考虑软件开发周期中的与日志记录有关的两个阶段:
- 开发阶段,用来记录应用程序的方方面面和各种细节,非常详细,使得一看到它就知道那里出了问题,出了什么样的问题。
- 出品阶段,要能够记录各种级别的错误和警告,同时也要适度记录应用程序正常运行的关键信息,这些信息可以给相关人员(开发人员、测试人员、用户等)极大的信心,使他们可以毫不犹豫的告诉您--瞧我们的软件在正常的运行。如一个好的web服务器的启动日志记录不仅要包含错误和警告,还要包含服务器正在启动,正在加载某某组件等等,最后还要提示启动是成功还是失败。
阅读到这里我们就应该着手实现我们的日志记录了。比较幸运的是我们有好多日志记录软件包可选,这就使我们不必关心日志记录的细节,只要把主要的精力放到日志记录的规划上就好了。我们选择的是Log4j,文章的余下部分将主要介绍这个Java日志记录软件包。
log4j的特性列表:
- 在运行速度方面进行了优化
- 使用基于名称的日志(logger)层次结构
- 是fail-stop的
- 是线程安全的
- 不受限于预定义的实用工具集
- 可以在运行时使用property和xml两种格式的文件来配置日志记录的行为
- 在一开始就设计为能够处理Java异常
- 能够定向输出到文件(file)、控制台(console)、java.io.OutputStream、java.io.Writer、远程服务器、远程Unix Syslog守护者、远程JMS监听者、NT EventLog或者发送e-mail
- 使用DEBUG、INFO、WARN、ERROR和FATAL五5个级别
- 可以容易的改变日志记录的布局(Layout)
- 输出日志记录的目的地和写策略可以通过实现Appender接口来改变
- 支持为每个日志(logger)附加多个目的地(appender)
- 提供国际化支持
Log4j有三个主要的组件:Logger、Appender和Layout。这三个组件相互配合使得我们可以获得非常强大的日志记录的能力。
Logger的名称是区分大小写的,依据名称可以确定其层次结构(即父子关系),规则如下:
- 如果Logger A的名称后跟一个点(.)是Logger B的名称的前缀就认为Logger A是Logger B的祖先。
- 如果在Logger A和Logger B之间,Logger B没有任何其它的祖先就认为Logger A是Logger B的父亲。
在Logger的层次结构的最顶层是root logger,它会永远存在,而且不能通过名字取到。
上面文字的描述可能不好的理解,为此我们给出了一张图,Logger的层次结构图,从中可以非常直观的看出三种主要组件的关系和各自所起的作用。
图示 1. Logger的层次结构图
Loger x.y是Logger x.y.z的祖先,因为x.y.是x.y.z的前缀,这符合规则的前一条。另外在Logger x.y和Logger x.y.z之间,Logger x.y.z没有其它的祖先,因此Logger x.y是Logger x.y.z的父亲,这符合规则的后一条。这样我们依据上面的规则就可以构造出如图1所示的Logger的层次结构。
从图1中我们还可以看到每一个Logger都有一个Level,根据该Level的值Logger决定是否处理对应的日志请求。如果Level没有被设置,就象图1中的Logger x.y一样,又该怎么办呢?答案是可以从祖先那里继承。
如果Logger C没有被设置Level,那么它将沿着它的层次结构向上查找,如果找到就继承并结束,否则会一直查找到root logger结束。因为log4j在设计时保证root logger会被设置一个默认的Level,所以任何logger都可以继承到Level。
图1中的Logger x.y没有被设置Level,但是根据上面的继承规则,Logger x.y继承了root logger的Level。
我们在来看看Logger选择日志记录请求(log request)的规则:
假设Logger M具有q级的Level,这个Level可能是设置的也可能是继承到的。
如果向Logger M发出一个Level为p的日志记录请求,那么只有满足p>=q时这个日志记录请求才会被处理。
org.apache.log4j.Logger中的不同方法发出不同Level的日志记录请求,如下:
- public void debug(Object message),发出Level为DEBUG的日志记录请求
- public void info(Object message),发出Level为INFO的日志记录请求
- public void warn(Object message),发出Level为WARN的日志记录请求
- public void error(Object message),发出Level为ERROR日志记录请求
- public void fatal(Object message),发出Level为FATAL的日志请求
- public void log(Level l, Object message),发出指定Level的日志记录请求
其中的静态常量DEBUG、INFO、WARN、ERROR、FATAL是在org.apache.log4j.Level中定义的,除了使用这些预定义的Level之外,Log4j还支持自定义Level。
注:org.apache.log4j.Level中还预定义了一些其它的Level。
在Log4j中,Appender指的是日志记录输出的目的地。当前支持的Appender(目的地)有文件(file)、控制台(console)、java.io.OutputStream、java.io.Writer、远程服务器、远程Unix Syslog守护者、远程JMS监听者、NT EventLog或者发送e-mail。如果您在上面没有找到适合的Appender,那就需要考虑实现自己的自定义Appender了。
每个Logger可以有多个Appender,但是相同的Appender只会被添加一次。
Appender的附加性意味着Logger C会将日志记录发给它的和它祖先的所有Appender。在图1中Logger a会将日志记录发给它自己的JDBCAppender和它的祖先root logger的ConsoleAppender和FileAppender。Logger x.y.z自己没有Appender,它将把日志记录发给它的祖先root logger的ConsoleAppender和FileAppender,如果Logger x.y也含有Appender,那么它们也会包括在内。
Appender的附加性是可以被中断的。假设Logger C的一个祖先为Logger P,如果Logger P的附加性标志(additivity flag)设置为假,那么Logger C会将日志记录只发给它的和在它和Logger P之间的祖先(包括Logger P)的Appender,而不会发给Logger P的祖先的Appender。Logger的附加性标志(additivity flag)默认值为ture。
在图1中如果没有设置Logger a的附加性标志(additivity flag),而是使用默认值true,那么Logger a会将日志记录发给它自己的JDBCAppender和它祖先root logger的ConsoleAppender和FileAppender,这和上面的描述相同。如果设置Logger a的附加性标志(additivity flag)的值false,那么Logger a会将日志记录发给它自己的JDBCAppender而不会在发给它祖先root logger的ConsoleAppender和FileAppender了。
Appender定制了输出目的地,通常我们还需要定制日志记录的输出格式,在Log4j中是通过将Layout和Appender关联到一起来实现的。Layout依据用户的要求来格式化日志记录。PatternLayout(标准Log4j组件)让用户依据类似于C语言printf函数的转换模式来指定输出格式。
例如,转换模式(conversion pattern)为"%r [%t] %-5p %c - %m%n"的PatternLayout将生成类似于以下内容的输出:
176 [main] INFO org.foo.Bar - Located nearest gas station.
在上面的输出中:
- 第一个字段表示自程序开始到发出日志记录请求时所消耗的毫秒数
- 第二个字段表示发出日志记录请求的线程
- 第三个字段表示日志记录请求的Level
- 第四个字段表示发出日志记录请求的Logger的名称
- 第五个字段(-后的文本)表示日志记录请求的消息
Log4j中还提到了一些其它的Layout,包括HTMLLayout、SimpleLayout、XMLLayout、TTCCLayout和DateLayout。如果这些不能满足您的要求,还可以自定义自己的Layout。
依据既有的经验显示用于日志记录的代码大约是全部代码量的4%。如果应用程序具有一定的规模,日志记录语句的数量还是比较巨大的,因此必须有效的管理这些语句。
在Log4j中我们可以通过配置Log4j环境来有效的管理日志记录。配置的方式有三种:
- 通过程序配置
- 通过Property文件配置
- 通过XML文件配置
通过程序配置Log4j环境实际上就是在应用程序的代码中改变Logger的Level或增加减少Appender等等。
Log4j提供了BasicConfigurator,它只是为root logger添加Appender。其中,
- BasicConfigurator.configure()为root logger添加一个关联着PatternLayout.TTCC_CONVERSION_PATTERN的ConsoleAppender
- BasicConfigurator.configure(Appender appender)为root logger添加指定的Appender
我们可以把BasicConfigurator看成是一个简单的使用程序配置Log4j环境的示例。例如,要给root logger添加两个Appender(A和B),下面的代码分别完成了这个要求。
不使用BasicConfigurator:
//示例代码,不能直接使用
Logger root = Logger.getRootLogger();
root.addAppender(A);
root.addAppender(B);
使用BasicConfigurator:
//示例代码,不能直接使用
BasicConfigurator.configure(A);
BasicConfigurator.configure(B);
这里要使用PropertyConfigurator来分析配置文件并设置日志记录,但是要注意日志记录先前的配置不会被清除和重设。
Property文件是由key=value这样的键值对所组成的,可以使用#或!作为注释行的开始。下面给出了两个简单的示例:
非常简单的示例1:
log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
稍显复杂的示例2:
log4j.rootLogger=, A1, A2
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n
log4j.appender.A2=org.apache.log4j.FileAppender
log4j.appender.A2.File=filename.log
log4j.appender.A2.Append=false
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%-5r %-5p [%t] %c{2} - %m%n
上面的两个示例只是让您对配置文件的格式有一个大体的认识,我们将在后面详细的描述各个配置元素的语法。
Repository-wide threshold:
Repository-wide threshold指定的Level的优先级高于Logger本身的Level。语法为log4j.threshold=[level],level可以为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL。也可以使用自定义Level,这时的语法为log4j.threshold=[level#classname]。默认为ALL。
依据上面的规则,我们有这样的结论:如果log4j.threshold=ERROR,Logger C的Level=DEBUG,这时只有高于等于ERROR的日志记录请求会被Logger C处理。
Appender的配置:
Appender的配置语法为
# For appender named appenderName, set its class.
# Note: The appender name can contain dots.
log4j.appender.appenderName=fully.qualified.name.of.appender.class
# Set appender specific options.
log4j.appender.appenderName.option1=value1
...
log4j.appender.appenderName.optionN=valueN
#For each named appender you can configure its Layout.
#The syntax for configuring an appender's layout is:
log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1=value1
....
log4j.appender.appenderName.layout.optionN=valueN
Logger的配置:
root logger的配置语法:
log4j.rootLogger=[level], appenderName, appenderName, ...,其中level可以为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL。也可以使用自定义Level,这时的语法为[level#classname]。
如果Level被指定那么root logger的Level将被配置为指定值。如果Level没有被指定那么root logger的Level不会被修改。从上面的语法中我们可以看出通过用,分隔的列表可以为root logger指定多个Appender。
对于root logger之外的logger语法是相似的,为log4j.logger.logger_name=[level|INHERITED|NULL], appenderName, appenderName, ...
上面只有INHERITED和NULL需要说明一下,其它部分和root logger相同。INHERITED和NULL的意义是相同的。如果我们使用了它们,意味着这个logger将不在使用自己的Level而是从它的祖先那里继承。
Logger的附加性标志(additivity flag)可以使用log4j.additivity.logger_name=[false|true]来配置。
ObjectRenderer配置:
我们可以通过ObjectRenderer来定义将消息对象转换成字符串的方式。语法为log4j.renderer.fully.qualified.name.of.rendered.class=fully.qualified.name.of.rendering.class。如:
//my.Fruit类型的消息对象将由my.FruitRenderer转换成字符串
log4j.renderer.my.Fruit=my.FruitRenderer
对上面的各个配置元素的语法理解之后,在来看示例1和2就很容易了。
PropertyConfigurator不支持Filter的配置。如果要支持Filter您可以使用DOMConfigurator,即使用XML文件的方式配置。
要使用DOMConfigurator.configure()来读取XML格式的配置文件。XML文件格式的定义是通过org/apache/log4j/xml/log4j.dtd来完成的,各个配置元素的嵌套关系如下:
<!ELEMENT log4j:configuration (renderer*, appender*,(category|logger)*,root?,categoryFactory?)>
这里没有给出更为详细的内容,要了解详细的内容需要查阅log4j.dtd。
下面这个简单的示例可以使您对XML配置文件的格式有一个基本的认识:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j SYSTEM "log4j.dtd">
<log4j>
<appender name="A1" class="org.apache.log4j.FileAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %c{2} - %m\n"/>
</layout>
</appender>
<appender name="A2" class="org.apache.log4j.FileAppender">
<layout class="org.apache.log4j.TTCCLayout">
<param name="DateFormat" value="ISO8601" />
</layout>
<param name="File" value="warning.log" />
<param name="Append" value="false" />
</appender>
<category name="org.apache.log4j.xml" priority="debug">
<appender-ref ref="A1" />
</category>
<root priority="debug">
<appender-ref ref="A1" />
<appender-ref ref="A2" />
</root>
</log4j>
默认初始化过程在LogManager类的静态初始化器中完成。具体步骤如下:
- 检查系统属性log4j.defaultInitOverride,如果值为false则执行初始化过程,否则跳过初始化过程。
- 将系统属性log4j.configuration的值赋给变量resource。如果log4j.configuration没有被定义则使用默认值log4j.properties。
- 试图转换变量resource到一个url。
- 如果变量resource不能转换成一个url,那么将使用org.apache.log4j.helpers.Loader.getResource(resource, Logger.class)得到一个url。
- 如果还是得不到url,将忽略默认初始化过程。如果得到url将使用PropertyConfigurator或DOMConfigurator来配置,也可以使用自定义的XXXConfigurator。
posted @
2008-05-21 10:20 xzc 阅读(1960) |
评论 (0) |
编辑 收藏
摘要: 转自:http://www.blogjava.net/fastzch/archive/2007/12/03/164912.html
1,读入图片的方式:
发现网上讲的很多读取图片的方式都不对,按下面提供的这个方法来读取,保证成功。
1 private byte[] getImageBytes(String ...
阅读全文
posted @
2007-12-04 11:37 xzc 阅读(1278) |
评论 (0) |
编辑 收藏
GBK的文字编码是双字节来表示的,即不论中、英文字符均使用双字节来表示,只不过为区分中文,将其最高位都定成1。
至于UTF-8编码则是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24位(三个字节)来编码。对于英文字符较多的论坛则用UTF-8节省空间。
GBK包含全部中文字符,
UTF-8则包含全世界所有国家需要用到的字符。
GBK是在国家标准GB2312基础上扩容后兼容GB2312的标准(好像还不是国家标准)
UTF-8编码的文字可以在各国各种支持UTF8字符集的浏览器上显示。
比如,如果是UTF8编码,则在外国人的英文IE上也能显示中文,而无需他们下载IE的中文语言支持包。
所以,对于英文比较多的论坛 ,使用GBK则每个字符占用2个字节,而使用UTF-8英文却只占一个字节。
posted @
2007-11-21 17:35 xzc 阅读(289) |
评论 (0) |
编辑 收藏
转自:http://blog.csdn.net/annicybc/archive/2006/06/24/829662.aspx
索引是建立在表的一列或多个列上的辅助对象,目的是加快访问表中的数据;
Oracle存储索引的数据结构是B*树,位图索引也是如此,只不过是叶子节点不同B*数索引;
索引由根节点、分支节点和叶子节点组成,上级索引块包含下级索引块的索引数据,叶节点包含索引数据和确定行实际位置的rowid。
使用索引的目的
加快查询速度
减少I/O操作
消除磁盘排序
何时使用索引
查询返回的记录数
排序表<40%
非排序表 <7%
表的碎片较多(频繁增加、删除)
索引的种类
非唯一索引(最常用)
唯一索引
位图索引
局部有前缀分区索引
局部无前缀分区索引
全局有前缀分区索引
散列分区索引
基于函数的索引
管理索引的准则
在表中插入数据后创建索引
。在用SQL*Loader或import工具插入或装载数据后,建立索引比较有效;
索引正确的表和列
。经常检索排序大表中40%或非排序表7%的行,建议建索引;
。为了改善多表关联,索引列用于联结;
。列中的值相对比较唯一;
。取值范围(大:B*树索引,小:位图索引);
。Date型列一般适合基于函数的索引;
。列中有许多空值,不适合建立索引
为性能而安排索引列
。经常一起使用多个字段检索记录,组合索引比单索引更有效;
。把最常用的列放在最前面,例:dx_groupid_serv_id(groupid,serv_id),在where条件中使用groupid或groupid,serv_id,查询将使用索引,若仅用到serv_id字段,则索引无效;
。合并/拆分不必要的索引。
限制每个表索引的数量
。一个表可以有几百个索引(你会这样做吗?),但是对于频繁插入和更新表,索引越多系统CPU,I/O负担就越重;
。建议每张表不超过5个索引。
删除不再需要的索引
。索引无效,集中表现在该使用基于函数的索引或位图索引,而使用了B*树索引;
。应用中的查询不使用索引;
。重建索引之前必须先删除索引,若用alter index … rebuild重建索引,则不必删除索引。
索引数据块空间使用
。创建索引时指定表空间,特别是在建立主键时,应明确指定表空间;
。合理设定pctfress,注意:不能给索引指定pctused;
。估计索引的大小和合理地设置存储参数,默认为表空间大小,或initial与next设置成一样大。
考虑并行创建索引
。对大表可以采用并行创建索引,在并行创建索引时,存储参数被每个查询服务器进程分别使用,例如:initial为1M,并行度为8,则创建索引期间至少要消耗8M空间;
考虑用nologging创建索引
。对大表创建索引可以使用nologging来减少重做日志;
。节省重做日志文件的空间;
。缩短创建索引的时间;
。改善了并行创建大索引时的性能。
怎样建立最佳索引
明确地创建索引
create index index_name on table_name(field_name)
tablespace tablespace_name
pctfree 5
initrans 2
maxtrans 255
storage
(
minextents 1
maxextents 16382
pctincrease 0
);
创建基于函数的索引
。常用与UPPER、LOWER、TO_CHAR(date)等函数分类上,例:
create index idx_func on emp (UPPER(ename)) tablespace tablespace_name;
创建位图索引
。对基数较小,且基数相对稳定的列建立索引时,首先应该考虑位图索引,例:
create bitmap index idx_bitm on class (classno) tablespace tablespace_name;
明确地创建唯一索引
。可以用create unique index语句来创建唯一索引,例:
create unique index dept_unique_idx on dept(dept_no) tablespace idx_1;
创建与约束相关的索引
。可以用using index字句,为与unique和primary key约束相关的索引,例如:
alter table table_name
add constraint PK_primary_keyname primary key (field_name)
using index tablespace tablespace_name;
如何创建局部分区索引
。基础表必须是分区表;
。分区数量与基础表相同;
。每个索引分区的子分区数量与相应的基础表分区相同;
。基础表的子分区中的行的索引项,被存储在该索引的相应的子分区中,例如:
Create Index TG_CDR04_SERV_ID_IDX On TG_CDR04(SERV_ID)
Pctfree 5
Tablespace TBS_AK01_IDX
Storage (
MaxExtents 32768
PctIncrease 0
FreeLists 1
FreeList Groups 1
)
local
/
如何创建范围分区的全局索引
。基础表可以是全局表和分区表。
create index idx_start_date on tg_cdr01(start_date)
global partition by range(start_date)
(partition p01_idx vlaues less than (‘0106’)
partition p01_idx vlaues less than (‘0111’)
…
partition p01_idx vlaues less than (‘0401’ ))
/
重建现存的索引
重建现存的索引的当前时刻不会影响查询;
重建索引可以删除额外的数据块;
提高索引查询效率;
alter index idx_name rebuild nologging;
对于分区索引:
alter index idx_name rebuild partition partiton_name nologging;
要删除索引的原因
。不再需要的索引;
。索引没有针对其相关的表所发布的查询提供所期望的性能改善;
。应用没有用该索引来查询数据;
。该索引无效,必须在重建之前删除该索引;
。该索引已经变的太碎了,必须在重建之前删除该索引;
。语句:drop index idx_name;drop index idx_name drop partition partition_name;
建立索引的代价
基础表维护时,系统要同时维护索引,不合理的索引将严重影响系统资源,主要表现在CPU和I/O上;
插入、更新、删除数据产生大量db file sequential read锁等待;
SQL优化器简介
基于规则的优化器
。总是使用索引
。总是从驱动表开始(from子句最右边的表)
。只有在不可避免的情况下,才使用全表扫描
。任何索引都可以
基于成本的优化器
。需要表、索引的统计资料
Analyze table customer compute statistics;
Analyze table customer estimate statistics sample 5000 rows;
。表中设置并行度、表分区
优化器模式
rule模式
。总忽略CBO和统计信息而基于规则
choose模式
。Oracle根据情况选择rule or first_rows or all_rows
first_rows 模式
。基于成本,以最快的速度返回记录,会造成总体查询速度的下降或消耗更多的资源,倾向索引扫描,适合OLTP系统
all_rows模式
。基于成本,确保总体查询时间最短,倾向并行全表扫描
例如:
Select last_name from customer order by last_name;用first_rows时,迅速返回记录,但I/O量大,用all_rows时,返回记录慢,但使用资源少。
调整SQL表访问
全表扫描
。返回记录:未排序表>40%,排序表>7%,建议采用并行机制来提高访问速度,DDS;
索引访问
。最常用的方法,包括索引唯一扫描和索引范围扫描,OLTP;
快速完全索引扫描
。访问索引中所有数据块,结果相当于全表扫描,可以用索引扫描代替全表扫描,例如:
Select serv_id,count(* ) from tg_cdr01 group by serv_id;
评估全表扫描的合法性
如何实现并行扫描
。永久并行化(不推荐)
alter table customer parallel degree 8;
。单个查询并行化
select /*+ full(emp) parallel(emp,8)*/ * from emp;
分区表效果明显
优化SQL语句排序
排序的操作:
。order by 子句
。group by 子句
。select distinct子句
。创建索引时
。union或minus
。排序合并连接
如何避免排序
。添加索引
。在索引中使用distinct子句
。避免排序合并连接
使用提示进行调整
使用提示的原则
。语法:/*+ hint */
。使用表别名:select /*+ index(e dept_idx)*/ * from emp e
。检验提示
常用的提示
。rule
。all_rows
。first_rows
。use_nl
。use_hash
。use_merge
。index
。index_asc
。no_index
。index_desc(常用于使用max内置函数)
。index_combine(强制使用位图索引)
。index_ffs(索引快速完全扫描)
。use_concat(将查询中所有or条件使用union all)
。parallel
。noparallel
。full
。ordered(基于成本)
调整表连接
表连接的类型
。等连接
where 条件中用等式连接;
。外部连接(左、右连接)
在where条件子句的等式谓词放置一个(+)来实现,例如:
select a.ename,b.comm from emp a,bonus b where a.ename=b.ename(+);
该语句返回所有emp表的记录;
。自连接
Select a.value total, B.value hard, (A.value - b.value) soft ,
Round((b.value/a.value)*100,1) perc
From v$sysstat a,v$sysstat b
Where a.statistic# = 179
and B.statistic# = 180;
反连接
反连接常用于not in or not exists中,是指在查询中找到的任何记录都不包含在结果集中的子查询;不建议使用not in or not exists;
。半连接
查询中使用exists,含义:即使在子查询中返回多条重复的记录,外部查询也只返回一条记录。
嵌套循环连接
。被连接表中存在索引的情况下使用;
。使用use_nl。
hash连接
。Hash连接将驱动表加载在内存中,并使用hash技术连接第二个表,提高等连接速度。
。适合于大表和小表连接;
。使用use_hash。
排序合并连接
。排序合并连接不使用索引
。使用原则:
连接表子段中不存在可用索引;
查询返回两个表中大部分的数据快;
CBO认为全表扫描比索引扫描执行的更快。
。使用use_merge
使用临时/中间表
多个大表关联时,可以分别把满足条件的结果集存放到中间表,然后用中间表关联;
SQL子查询的调整
关联与非关联子查询
。关联:子查询的内部引用的是外部表,每行执行一次;
。非关联:子查询只执行一次,存放在内存中。
调整not in 和not exists语句
。可以使用外部连接优化not in子句,例如:
select ename from emp where dept_no not in
(select dept_no from dept where dept_name =‘Math’);
改为:
select ename from emp,dept
where emp.dept_no=dept.dept_no
and dept.dept_name is null;
使用索引调整SQL
Oracle 为什么不使用索引
。检查被索引的列或组合索引的首列是否出现在PL/SQL语句的WHERE子句中,这是“执行计划”能用到相关索引的必要条件。
。看采用了哪种类型的连接方式。ORACLE的共有Sort Merge Join(SMJ)、Hash Join(HJ)和Nested Loop Join(NL)。在两张表连接,且内表的目标列上建有索引时,只有Nested Loop才能有效地利用到该索引。SMJ即使相关列上建有索引,最多只能因索引的存在,避免数据排序过程。HJ由于须做HASH运算,索引的存在对数据查询速度几乎没有影响。
。看连接顺序是否允许使用相关索引。假设表emp的deptno列上有索引,表dept的列deptno上无索引,WHERE语句有emp.deptno=dept.deptno条件。在做NL连接时,emp做为外表,先被访问,由于连接机制原因,外表的数据访问方式是全表扫描,emp.deptno上的索引显然是用不上,最多在其上做索引全扫描或索引快速全扫描。
。是否用到系统数据字典表或视图。由于系统数据字典表都未被分析过,可能导致极差的“执行计划”。但是不要擅自对数据字典表做分析,否则可能导致死锁,或系统性能下降。
。索引列是否函数的参数。如是,索引在查询时用不上。
。是否存在潜在的数据类型转换。如将字符型数据与数值型数据比较,ORACLE会自动将字符型用to_number()函数进行转换,从而导致上一种现象的发生。
。是否为表和相关的索引搜集足够的统计数据。对数据经常有增、删、改的表最好定期对表和索引进行分析,可用SQL语句“analyze table xxxx compute statistics for all indexes;”。ORACLE掌握了充分反映实际的统计数据,才有可能做出正确的选择。
。索引列的选择性不高。 我们假设典型情况,有表emp,共有一百万行数据,但其中的emp.deptno列,数据只有4种不同的值,如10、20、30、40。虽然emp数据行有很多,ORACLE缺省认定表中列的值是在所有数据行均匀分布的,也就是说每种deptno值各有25万数据行与之对应。假设SQL搜索条件DEPTNO=10,利用deptno列上的索引进行数据搜索效率,往往不比全表扫描的高。
。索引列值是否可为空(NULL)。如果索引列值可以是空值,在SQL语句中那些要返回NULL值的操作,将不会用到索引,如COUNT(*),而是用全表扫描。这是因为索引中存储值不能为全空。
。看是否有用到并行查询(PQO)。并行查询将不会用到索引。
。如果从以上几个方面都查不出原因的话,我们只好用采用在语句中加hint的方式强制ORACLE使用最优的“执行计划”。 hint采用注释的方式,有行注释和段注释两种方式。 如我们想要用到A表的IND_COL1索引的话,可采用以下方式: “SELECT /*+ INDEX(A IND_COL1)*/ * FROM A WHERE COL1 = XXX;"
如何屏蔽索引
语句的执行计划中有不良索引时,可以人为地屏蔽该索引,方法:
。数值型:在索引字段上加0,例如
select * from emp where emp_no+0 = v_emp_no;
。字符型:在索引字段上加‘’,例如
select * from tg_cdr01 where msisdn||’’=v_msisdn;
posted @
2007-11-21 15:05 xzc 阅读(643) |
评论 (1) |
编辑 收藏
转自:http://tb.blog.csdn.net/TrackBack.aspx?PostId=1729625
1、各种索引的创建方法
(1)*tree索引
create index indexname on tablename(columnname);
(2)反向索引
create index indexname on tablename(columnname) reverse;
(3)降序索引
create index indexname on tablename(columnname DESC);
(4)位图索引
create BITMAP index indexname on tablename(columnname);
(5)函数索引
create index indexname on tablename(functionname(columnname));
创建索引后要分析才能使用
analyze table test compute statistics for table for all indexed columns for all indexes;
analyze index test validate structure;
select name,lf_rows from index_stats;用这条语句可以查询保存了多少条索引
analyze index test compute statistics;
从字面理解validate structure 主要在于校验对象的有效性. compute statistics在于统计相关的信息..
查询索引
select index_name,index_type from user_indexes where table_name='TEST';
2、打开autotrace功能
执行$ORACLE_HOME/rdbms/admin/utlxplan.sql和$ORACLE_HOME/sqlplus/admin/plustrce.sql
然后给相关用户授予plustrace角色,然后这些用户就可以使用autotrace功能了
3、无效索引
(1)类型不匹配
create table test(a varchar(2),b number);
insert into test values('1',1);
create index test_index on test(a);
analyze table test compute statistics for table for all indexed columns for all indexes;
set autotrace on;
类型匹配的情况
select /*+ RULE */ * from test where a='1';
A B
-- ----------
1 1
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=HINT: RULE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TEST'
2 1 INDEX (RANGE SCAN) OF 'TEST_INDEX' (NON-UNIQUE) 使用了索引
类型不匹配的情况
select /*+ RULE */ * from test where a=1;
A B
-- ----------
1 1
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=HINT: RULE
1 0 TABLE ACCESS (FULL) OF 'TEST' 选择了全表扫描
(2)条件包含函数但没有创建函数索引
alter system set QUERY_REWRITE_ENABLED=true;
alter system set query_rewrite_integrity=enforced;
insert into test values('a',2);
select /*+ RULE */ * from test where upper(a) = 'A';
A B
-- ----------
a 2
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=HINT: RULE
1 0 TABLE ACCESS (FULL) OF 'TEST'
由于没有创建函数索引,所以选择全表扫描
create index test_index_fun on test(upper(a));
analyze table test compute statistics for table for all indexed columns for all indexes;
select /*+ RULE */ * from test where upper(a) = 'A';
A B
-------------------------------------------------- ----------
a 2
a 3
a 4
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=HINT: RULE
1 0 TABLE ACCESS (FULL) OF 'TEST'
虽然创建了函数索引,但由于工作于RBO模式,所以函数索引没用,选择了全表扫描
select * from test where upper(a) = 'A';
A B
-------------------------------------------------- ----------
a 2
a 3
a 4
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=9)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TEST' (Cost=2 Card=1 Byt
es=9)
2 1 INDEX (RANGE SCAN) OF 'TEST_INDEX_FUN' (NON-UNIQUE) (Cos
t=1 Card=1)
当函数索引工作于CBO模式下,选择了基于函数的索引,上面创建的索引函数TEST_INDEX_FUN已经用到
(3)符合索引中的前导列没有被作为查询条件
create index test_index_com on test(a,b);
select /*+ RULE */ * from test where a = '1';
A B
-- ----------
1 1
前导列a作为了查询条件,但由于之前创建了a的索引,所以使用了TEST_INDEX而没有使用test_index_com
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=HINT: RULE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TEST'
2 1 INDEX (RANGE SCAN) OF 'TEST_INDEX' (NON-UNIQUE)
select /*+ RULE */ * from test where b = '1';
A B
-- ----------
1 1
2 1
3 1
4 1
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=HINT: RULE
1 0 TABLE ACCESS (FULL) OF 'TEST'
前导列a没有作为查询条件,所以选择全部扫描
select /*+ RULE */ * from test where b = '1' and a= '1';
A B
-- ----------
1 1
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=HINT: RULE
1 0 INDEX (RANGE SCAN) OF 'TEST_INDEX_COM' (NON-UNIQUE)
前导列a作为了查询条件,使用了索引
(4)CBO模式下选择的行数比例过大,优化器选择全表扫描
declare
i number;
j number;
begin
for i in 1 .. 10 loop
for j in 1 .. 10000 loop
insert into test values(to_char(j),i);
end loop;
end loop;
end;
/
declare i number;
begin
for i in 1 .. 100 loop
insert into test values(to_char(i),i);
end loop;
end;
/
SQL> select count(*) from test;
COUNT(*)
----------
200000
select * from test where a = '1';
已选择10000行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=27 Card=9333 Bytes=7
4664)
1 0 TABLE ACCESS (FULL) OF 'TEST' (Cost=27 Card=9333 Bytes=746
64)
比例过大,选择全表扫描
select * from test where a = '99';
已选择10行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=2 Bytes=16)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TEST' (Cost=2 Card=2 Byt
es=16)
2 1 INDEX (RANGE SCAN) OF 'TEST_INDEX' (NON-UNIQUE) (Cost=1
Card=2)
比例小,选择索引
select /*+ RULE */ * from test where a = '1';
已选择10000行。
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=HINT: RULE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TEST'
2 1 INDEX (RANGE SCAN) OF 'TEST_INDEX' (NON-UNIQUE)
如果指定为RBO优化器,肯定就用索引了
(5)在CBO模式下表很久没分析,表的增长明显,优化器采取了全表扫描
(6)索引条件中使用了<>、!=、not\not in、not like等操作符,导致查询不使用索引
先做一个测试在一个表中插入130万条数据,其中不等于1的数据有30万条,以下是几种语句执行的结果
序号 语句 时间 代价
1 select * from test where b<>1; 00: 00: 03.04 398
2 select * from test where b not like 1; 00: 00: 03.03 398
3 select * from test where b !=1; 00: 00: 03.01 398
4 select * from test where b not in(1); 00: 00: 03.00 398
5 select * from test where b<1 union select * from test where b>1; 00: 00: 03.01 264
6 select * from test where b<1 union all select * from test where b>1; 00: 00: 02.09 132
7 select * from test where b<1 or b>1; 00: 00: 02.08 96
从以上可以看出最优化的语句是7,在查询过程中使用索引的有5、6、7
所以,如果建立了索引,在语句中尽量不要使用<>、!=、not、not in、not like操作,如果非要使用,请尽量用or和union操作替换
(7)索引对空值的影响
我们首先做一些测试数据:
SQL> create table t(x int, y int);
请注意,这里我对表t做了一个唯一(联合)索引:
SQL> create unique index t_idx on t(x,y);
SQL> insert into t values(1,1);
SQL> insert into t values(1,NULL);
SQL> insert into t values(NULL,1);
SQL> insert into t values(NULL,NULL);
SQL> commit;
下面我们分析一下索引:
SQL> analyze index t_idx validate structure;
SQL> select name,lf_rows from index_stats;
NAME LF_ROWS
------------------------------ ----------
T_IDX 3
然后,我们就可以看到,当前的索引中仅仅保存了3行数据。
请注意,上面我们插入并提交了四行数据。
所以,这里就有一个结论:
Oracle的索引不保存该索引包含的列中全部为空的行。
这同时也带来个好处,但当一个表中的某一列大部分为空值,至少90%以上是空值的时候,就可以为该列建立索引。
比如该表为t,该列为x
select * from t where x is null;
此时会选择全表扫描
select * from t where x=1;
此时就会使用索引,而且索引中不保存值为空的行,所以索引中只有10%左右的行,因此在这10%的行中找出x=1的行比在全表中找出x=1的行要快的多
我们继续插入数据,现在再插入几行全部为空的行:
SQL> insert into t values(NULL,NULL);
SQL> insert into t values(NULL,NULL);
我们看到这样的插入,居然没有违反前面我们设定的唯一约束(unique on t(x,y)),
所以,这里我们又得出一个结论:
Oracle认为 NULL<>NULL ,进而 (NULL,NULL)<>(NULL,NULL)
换句话说,Oracle认为空值(NULL)不等于任何值,包括空值也不等于空值。
我们看到下面的插入会违反唯一约束(DEMO.T_IDX),这个很好理解了,因为它不是全部为空的值,即它不是(NULL,NULL),只有全部为空的行才被认为是不同的行:
SQL> insert into t values(1,null);
ORA-00001: 违反唯一约束条件 (DEMO.T_IDX)
SQL> insert into t values(null,1);
ORA-00001: 违反唯一约束条件 (DEMO.T_IDX)
SQL>
请看下面的例子:
SQL> select x,y,count(*) from t group by x,y;
X Y COUNT(*)
----- -------- ----------
3
1 1
1 1
1 1 1
Executed in 0.03 seconds
SQL> select x,y,count(*) from t where x is null and y is null group by x,y;
X Y COUNT(*)
---- ------- ----------
3
Executed in 0.01 seconds
SQL>
SQL> select x,y,count(*) from t group by x,y having count(*)>1;
X Y COUNT(*)
------ -------------------- ----------
3
Executed in 0.02 seconds
SQL>
可以看见,完全为空的行有三行,这里我们又可以得出一个结论:
oracle在group by子句中认为完全为空的行是相同的行
换句话说,在group by子句中,oracle认为(NULL,NULL)=(NULL,NULL)
SQL> select * from t where x is null;
X Y
---------- ----------
1
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=4 Bytes=8)
1 0 TABLE ACCESS (FULL) OF 'T' (Cost=2 Card=4 Bytes=8)
SQL> select * from t where x=1;
X Y
---------- ----------
1 1
1
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=2 Bytes=4)
1 0 INDEX (RANGE SCAN) OF 'T_IDX' (UNIQUE) (Cost=1 Card=2 Byte
s=4)
从以上可以看出,在使用IS NULL 和 IS NOT NULL条件的时候,Oracle不使用索引
那么我们如何使用空值的比较条件呢?
首先,尽量不在前导列上使用空值,其次我们在创建表的时候,为每个列都指定为非空约束(NOT NULL),并且在必要的列上使用default值
8、不要为所有的列建立索引
我们知道,建立索引是为了提高查询的效率,但是同时也应该注意到,索引增加了对DML操作(insert, update, delete)的代价,而且,一给中的索引如果太多,那么多数的索引是根本不会被使用到的,而另一方面我们维护这些不被使用的所以还要大幅度降低系统的性能。所以,索引不是越多越好,而是要恰到好处的使用。
比如说,有些列由于使用了函数,我们要使用已有的索引(如一些复合索引)是不可能的,那么就必须建立单独的函数索引,如果说这个函数索引很少会被应用(仅仅在几个特别的sql中会用到),我们就可以尝试改写查询,而不去建立和维护那个函数索引,例如:
1,trunc函数
SQL> select empno,ename,deptno from emp where trunc(hiredate)='2004-01-01';
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'EMP'
将上面的查询转换为:
SQL> select empno,ename,deptno from emp
2 where hiredate >= to_date('2004-01-01','yyyy-mm-dd')
3 and hiredate<to_date('2004-01-01','yyyy-mm-dd')+0.999;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP'
2 1 INDEX (RANGE SCAN) OF 'EMP_ID3' (NON-UNIQUE)
2,to_char函数
SQL> select empno,ename,deptno from emp
2 where to_char(hiredate,'yyyy-mm-dd')='2003-09-05';
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'EMP'
SQL> select empno,ename,deptno from emp
2 where hiredate=to_date('2003-09-05','yyyy-mm-dd');
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP'
2 1 INDEX (RANGE SCAN) OF 'EMP_ID3' (NON-UNIQUE)
3,substr函数
SQL> select dname from dept where substr(dname,1,3)='abc';
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'DEPT'
SQL> select dname from dept where dname like 'abc%';
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 INDEX (RANGE SCAN) OF 'DEPT_ID1' (NON-UNIQUE)
通常,为了均衡查询的效率和DML的效率,我们要仔细的分析应用,找出来出现频率相对较多、字段内容较少(比如varchar2(1000)就不适合建立索引,而varchar2(10)相对来说就适合建立索引)的列,合理的建立索引,比如有时候我们希望建立复合索引,有时候我们更希望建立单键索引。
posted @
2007-11-21 10:20 xzc 阅读(416) |
评论 (0) |
编辑 收藏
转自:http://www.blogjava.net/hadeslee/archive/2007/11/20/161770.html
2. <body onselectstart="return false"> 取消选取、防止复制
3. onpaste="return false" 不准粘贴
4. oncopy="return false;" oncut="return false;" 防止复制
5. <link rel="Shortcut Icon" href="favicon.ico"> IE地址栏前换成自己的图标
6. <link rel="Bookmark" href="favicon.ico"> 可以在收藏夹中显示出你的图标
7. <input style="ime-mode:disabled"> 关闭输入法
8. 永远都会带着框架
<script language="JavaScript"><!--
if (window == top)top.location.href = "frames.htm"; //frames.htm为框架网页
// --></script>
9. 防止被人frame
<SCRIPT LANGUAGE=JAVASCRIPT><!--
if (top.location != self.location)top.location=self.location;
// --></SCRIPT>
10. 网页将不能被另存为
<noscript><iframe src="/*.html>";</iframe></noscript>
11. <input type=button value=查看网页源代码
onclick="window.location = "view-source:"+ "http://www.pconline.com.cn"">
12.删除时确认
<a href="javascript:if(confirm("确实要删除吗?"))location="boos.asp?&areyou=删除&page=1"">删除</a>
13. 取得控件的绝对位置
//Javascript
<script language="Javascript">
function getIE(e){
var t=e.offsetTop;
var l=e.offsetLeft;
while(e=e.offsetParent){
t+=e.offsetTop;
l+=e.offsetLeft;
}
alert("top="+t+"/nleft="+l);
}
</script>
//VBScript
<script language="VBScript"><!--
function getIE()
dim t,l,a,b
set a=document.all.img1
t=document.all.img1.offsetTop
l=document.all.img1.offsetLeft
while a.tagName<>"BODY"
set a = a.offsetParent
t=t+a.offsetTop
l=l+a.offsetLeft
wend
msgbox "top="&t&chr(13)&"left="&l,64,"得到控件的位置"
end function
--></script>
14. 光标是停在文本框文字的最后
<script language="javascript">
function cc()
{
var e = event.srcElement;
var r =e.createTextRange();
r.moveStart("character",e.value.length);
r.collapse(true);
r.select();
}
</script>
<input type=text name=text1 value="123" onfocus="cc()">
15. 判断上一页的来源
javascript:
document.referrer
16. 最小化、最大化、关闭窗口
<object id=hh1 classid="clsid:ADB880A6-D8FF-11CF-9377-00AA003B7A11">
<param name="Command" value="Minimize"></object>
<object id=hh2 classid="clsid:ADB880A6-D8FF-11CF-9377-00AA003B7A11">
<param name="Command" value="Maximize"></object>
<OBJECT id=hh3 classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11">
<PARAM NAME="Command" VALUE="Close"></OBJECT>
<input type=button value=最小化 onclick=hh1.Click()>
<input type=button value=最大化 onclick=hh2.Click()>
<input type=button value=关闭 onclick=hh3.Click()>
本例适用于IE
17.屏蔽功能键Shift,Alt,Ctrl
<script>
function look(){
if(event.shiftKey)
alert("禁止按Shift键!"); //可以换成ALT CTRL
}
document.onkeydown=look;
</script>
18. 网页不会被缓存
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
<META HTTP-EQUIV="expires" CONTENT="Wed, 26 Feb 1997 08:21:57 GMT">
或者<META HTTP-EQUIV="expires" CONTENT="0">
19.怎样让表单没有凹凸感?
<input type=text style="border:1 solid #000000">
或
<input type=text style="border-left:none; border-right:none; border-top:none; border-bottom:
1 solid #000000"></textarea>
20.<div><span>&<layer>的区别?
<div>(division)用来定义大段的页面元素,会产生转行
<span>用来定义同一行内的元素,跟<div>的唯一区别是不产生转行
<layer>是ns的标记,ie不支持,相当于<div>
21.让弹出窗口总是在最上面:
<body onblur="this.focus();">
22.不要滚动条?
让竖条没有:
<body style="overflow:scroll;overflow-y:hidden">
</body>
让横条没有:
<body style="overflow:scroll;overflow-x:hidden">
</body>
两个都去掉?更简单了
<body scroll="no">
</body>
23.怎样去掉图片链接点击后,图片周围的虚线?
<a href="#" onFocus="this.blur()"><img src="/logo.jpg" border=0></a>
24.电子邮件处理提交表单
<form name="form1" method="post" action="mailto:****@***.com" enctype="text/plain">
<input type=submit>
</form>
25.在打开的子窗口刷新父窗口的代码里如何写?
window.opener.location.reload()
26.如何设定打开页面的大小
<body onload="top.resizeTo(300,200);">
打开页面的位置<body onload="top.moveBy(300,200);">
27.在页面中如何加入不是满铺的背景图片,拉动页面时背景图不动
<STYLE>
body
{background-image:url(/logo.gif); background-repeat:no-repeat;
background-position:center;background-attachment: fixed}
</STYLE>
28. 检查一段字符串是否全由数字组成
<script language="Javascript"><!--
function checkNum(str){return str.match(//D/)==null}
alert(checkNum("1232142141"))
alert(checkNum("123214214a1"))
// --></script>
29. 获得一个窗口的大小
document.body.clientWidth; document.body.clientHeight
30. 怎么判断是否是字符
if (/[^/x00-/xff]/g.test(s)) alert("含有汉字");
else alert("全是字符");
31.TEXTAREA自适应文字行数的多少
<textarea rows=1 name=s1 cols=27 onpropertychange="this.style.posHeight=this.scrollHeight">
</textarea>
32. 日期减去天数等于第二个日期
<script language=Javascript>
function cc(dd,dadd)
{
//可以加上错误处理
var a = new Date(dd)
a = a.valueOf()
a = a - dadd * 24 * 60 * 60 * 1000
a = new Date(a)
alert(a.getFullYear() + "年" + (a.getMonth() + 1) + "月" + a.getDate() + "日")
}
cc("12/23/2002",2)
</script>
33. 选择了哪一个Radio
<HTML><script language="vbscript">
function checkme()
for each ob in radio1
if ob.checked then
window.alert ob.value
next
end function
</script><BODY>
<INPUT name="radio1" type="radio" value="style" checked>Style
<INPUT name="radio1" type="radio" value="barcode">Barcode
<INPUT type="button" value="check" onclick="checkme()">
</BODY></HTML>
34.脚本永不出错
<SCRIPT LANGUAGE="JavaScript">
<!-- Hide
function killErrors() {
return true;
}
window.onerror = killErrors;
// -->
</SCRIPT>
35.ENTER键可以让光标移到下一个输入框
<input onkeydown="if(event.keyCode==13)event.keyCode=9">
36. 检测某个网站的链接速度:
把如下代码加入<body>区域中:
<script language=Javascript>
tim=1
setInterval("tim++",100)
b=1
var autourl=new Array()
autourl[1]="www.njcatv.net"
autourl[2]="javacool.3322.net"
autourl[3]="www.sina.com.cn"
autourl[4]="www.nuaa.edu.cn"
autourl[5]="www.cctv.com"
function butt(){
document.write("<form name=autof>")
for(var i=1;i<autourl.length;i++)
document.write("<input type=text name=txt"+i+" size=10 value=测试中……> =》<input type=text
name=url"+i+" size=40> =》<input type=button value=GO
onclick=window.open(this.form.url"+i+".value)><br>")
document.write("<input type=submit value=刷新></form>")
}
butt()
function auto(url){
document.forms[0]["url"+b].value="/url
if(tim>200)
{document.forms[0]["txt"+b].value="/链接超时"}
else
{document.forms[0]["txt"+b].value=""时间"+tim/10+"秒"}
b++
}
function run(){for(var i=1;i<autourl.length;i++)document.write("<img src=http://"+autourl+"/"+Math.random()+" width=1 height=1
onerror=auto("http://"+autourl+"")>")}
run()</script>
37. 各种样式的光标
auto :标准光标
default :标准箭头
hand :手形光标
wait :等待光标
text :I形光标
vertical-text :水平I形光标
no-drop :不可拖动光标
not-allowed :无效光标
help :?帮助光标
all-scroll :三角方向标
move :移动标
crosshair :十字标
e-resize
n-resize
nw-resize
w-resize
s-resize
se-resize
sw-resize
38.页面进入和退出的特效
进入页面<meta http-equiv="Page-Enter" content="revealTrans(duration=x, transition=y)">
推出页面<meta http-equiv="Page-Exit" content="revealTrans(duration=x, transition=y)">
这个是页面被载入和调出时的一些特效。duration表示特效的持续时间,以秒为单位。transition表示使用哪种特效,取值为1-23:
0 矩形缩小
1 矩形扩大
2 圆形缩小
3 圆形扩大
4 下到上刷新
5 上到下刷新
6 左到右刷新
7 右到左刷新
8 竖百叶窗
9 横百叶窗
10 错位横百叶窗
11 错位竖百叶窗
12 点扩散
13 左右到中间刷新
14 中间到左右刷新
15 中间到上下
16 上下到中间
17 右下到左上
18 右上到左下
19 左上到右下
20 左下到右上
21 横条
22 竖条
23 以上22种随机选择一种
39.在规定时间内跳转
<META http-equiv=V="REFRESH" content="5;URL=http://www.51js.com">
40.网页是否被检索
<meta name="ROBOTS" content="属性值">
其中属性值有以下一些:
属性值为"all": 文件将被检索,且页上链接可被查询;
属性值为"none": 文件不被检索,而且不查询页上的链接;
属性值为"index": 文件将被检索;
属性值为"follow": 查询页上的链接;
属性值为"noindex": 文件不检索,但可被查询链接;
属性值为"nofollow": 文件不被检索,但可查询页上的链接。
41、email地址的分割
把如下代码加入<body>区域中
<a href="webmaster@sina.commailto:webmaster@sina.com">webmaster@sina.com</a>
42、流动边框效果的表格
把如下代码加入<body>区域中
<SCRIPT>
l=Array(6,7,8,9,'a','b','b','c','d','e','f')
Nx=5;Ny=35
t="<table border=0 cellspacing=0 cellpadding=0 height="+((Nx+2)*16)+"><tr>"
for(x=Nx;x<Nx+Ny;x++)
t+="<td width=16 id=a_mo"+x+"> </td>"
t+="</tr><tr><td width=10 id=a_mo"+(Nx-1)+"> </td><td colspan="+(Ny-2)+" rowspan="+(Nx)+"> </td><td width=16 id=a_mo"+(Nx+Ny)+"></td></tr>"
for(x=2;x<=Nx;x++)
t+="<tr><td width=16 id=a_mo"+(Nx-x)+"> </td><td width=16 id=a_mo"+(Ny+Nx+x-1)+"> </td></tr>"
t+="<tr>"
for(x=Ny;x>0;x--)
t+="<td width=16 id=a_mo"+(x+Nx*2+Ny-1)+"> </td>"
document.write(t+"</tr></table>")
var N=Nx*2+Ny*2
function f1(y){
for(i=0;i<N;i++){
c=(i+y)%20;if(c>10)c=20-c
document.all["a_mo"+(i)].bgColor="'#0000"+l[c]+l[c]+"'"}
y++
setTimeout('f1('+y+')','1')}
f1(1)
</SCRIPT>
43、JavaScript主页弹出窗口技巧
窗口中间弹出
<script>
window.open("http://www.cctv.com","","width=400,height=240,top="+(screen.availHeight-240)/2+",left="+(screen.availWidth-400)/2);
</script>
============
<html>
<head>
<script language="LiveScript">
function WinOpen() {
msg=open("","DisplayWindow","toolbar=no,directories=no,menubar=no");
msg.document.write("<HEAD><TITLE>哈 罗!</TITLE></HEAD>");
msg.document.write("<CENTER><H1>酷 毙了!</H1><h2>这 是<B>JavaScript</B>所 开 的 视窗!</h2></CENTER>");
}
</script>
</head>
<body>
<form>
<input type="button" name="Button1" value="Push me" onclick="WinOpen()">
</form>
</body>
</html>
==============
一、在下面的代码中,你只要单击打开一个窗口,即可链接到赛迪网。而当你想关闭时,只要单击一下即可关闭刚才打开的窗口。
代码如下:
<SCRIPT language="JavaScript">
<!--
function openclk() {
another=open('http://www.ccidnet.com','NewWindow');
}
function closeclk() {
another.close();
}
//-->
</SCRIPT>
<FORM>
<INPUT TYPE="BUTTON" NAME="open" value="打开一个窗口" onClick="openclk()">
<BR>
<INPUT TYPE="BUTTON" NAME="close" value="关闭这个窗口" onClick="closeclk()">
</FORM>
二、上面的代码也太静了,为何不来点动感呢?如果能给页面来个降落效果那该多好啊!
代码如下:
<script>
function drop(n) {
if(self.moveBy){
self.moveBy (0,-900);
for(i = n; i > 0; i--){
self.moveBy(0,3);
}
for(j = 8; j > 0; j--){
self.moveBy(0,j);
self.moveBy(j,0);
self.moveBy(0,-j);
self.moveBy(-j,0);
}
}
}
</script>
<body onLoad="drop(300)">
三、讨厌很多网站总是按照默认窗口打开,如果你能随心所欲控制打开的窗口那该多好。
代码如下:
<SCRIPT LANGUAGE="JavaScript">
<!-- Begin
function popupPage(l, t, w, h) {
var windowprops = "location=no,scrollbars=no,menubars=no,toolbars=no,resizable=yes" +
",left=" + l + ",top=" + t + ",width=" + w + ",height=" + h;
var URL = "http://www.80cn.com";
popup = window.open(URL,"MenuPopup",windowprops);
}
// End -->
</script>
<table>
<tr>
<td>
<form name=popupform>
<pre>
打开页面的参数<br>
离开左边的距离: <input type=text name=left size=2 maxlength=4> pixels
离开右边的距离: <input type=text name=top size=2 maxlength=4> pixels
窗口的宽度: <input type=text name=width size=2 maxlength=4> pixels
窗口的高度: <input type=text name=height size=2 maxlength=4> pixels
</pre>
<center>
<input type=button value="打开这个窗口!" onClick="popupPage(this.form.left.value, this.form.top.value, this.form.width.value, this.form.height.value)">
</center>
</form>
</td>
</tr>
</table>你只要在相对应的对话框中输入一个数值即可,将要打开的页面的窗口控制得很好。
44、页面的打开移动
把如下代码加入<body>区域中
<SCRIPT LANGUAGE="JavaScript">
<!-- Begin
for (t = 2; t > 0; t--) {
for (x = 20; x > 0; x--) {
for (y = 10; y > 0; y--) {
parent.moveBy(0,-x);
}
}
for (x = 20; x > 0; x--) {
for (y = 10; y > 0; y--) {
parent.moveBy(0,x);
}
}
for (x = 20; x > 0; x--) {
for (y = 10; y > 0; y--) {
parent.moveBy(x,0);
}
}
for (x = 20; x > 0; x--) {
for (y = 10; y > 0; y--) {
parent.moveBy(-x,0);
}
}
}
//-->
// End -->
</script>
45、显示个人客户端机器的日期和时间
<script language="LiveScript">
<!-- Hiding
today = new Date()
document.write("现 在 时 间 是: ",today.getHours(),":",today.getMinutes())
document.write("<br>今 天 日 期 为: ", today.getMonth()+1,"/",today.getDate(),"/",today.getYear());
// end hiding contents -->
</script>
46、自动的为你每次产生最後修改的日期了:
<html>
<body>
This is a simple HTML- page.
<br>
Last changes:
<script language="LiveScript">
<!-- hide script from old browsers
document.write(document.lastModified)
// end hiding contents -->
</script>
</body>
</html>
47、不能为空和邮件地址的约束:
<html>
<head>
<script language="JavaScript">
<!-- Hide
function test1(form) {
if (form.text1.value == "")
alert("您 没 写 上 任 何 东 西, 请 再 输 入 一 次 !")
else {
alert("嗨 "+form.text1.value+"! 您 已 输 入 完 成 !");
}
}
function test2(form) {
if (form.text2.value == "" ||
form.text2.value.indexOf('@', 0) == -1)
alert("这 不 是 正 确 的 e-mail address! 请 再 输 入 一 次 !");
else alert("您 已 输 入 完 成 !");
}
// -->
</script>
</head>
<body>
<form name="first">
Enter your name:<br>
<input type="text" name="text1">
<input type="button" name="button1" value="输 入 测 试" onClick="test1(this.form)">
<P>
Enter your e-mail address:<br>
<input type="text" name="text2">
<input type="button" name="button2" value="输 入 测 试" onClick="test2(this.form)">
</body>
48、跑马灯
<html>
<head>
<script language="JavaScript">
<!-- Hide
var scrtxt="怎麽样 ! 很酷吧 ! 您也可以试试."+"Here goes your message the visitors to your page will "+"look at for hours in pure fascination...";
var lentxt=scrtxt.length;
var width=100;
var pos=1-width;
function scroll() {
pos++;
var scroller="";
if (pos==lentxt) {
pos=1-width;
}
if (pos<0) {
for (var i=1; i<=Math.abs(pos); i++) {
scroller=scroller+" ";}
scroller=scroller+scrtxt.substring(0,width-i+1);
}
else {
scroller=scroller+scrtxt.substring(pos,width+pos);
}
window.status = scroller;
setTimeout("scroll()",150);
}
//-->
</script>
</head>
<body onLoad="scroll();return true;">
这里可显示您的网页 !
</body>
</html>
49、在网页中用按钮来控制前页,后页和主页的显示。
<html>
<body>
<FORM NAME="buttonbar">
<INPUT TYPE="button" VALUE="Back" onClick="history.back()">
<INPUT TYPE="button" VALUE="JS- Home" onClick="location='script.html'">
<INPUT TYPE="button" VALUE="Next" onCLick="history.forward()">
</FORM>
</body>
</html>
50、查看某网址的源代码
把如下代码加入<body>区域中
<SCRIPT>
function add()
{
var ress=document.forms[0].luxiaoqing.value
window.location="view-source:"+ress;
}
</SCRIPT>
输入要查看源代码的URL地址:
<FORM><input type="text" name="luxiaoqing" size=40 value="http://"></FORM>
<FORM><br>
<INPUT type="button" value="查看源代码" onClick=add()>
</FORM>
51、title显示日期
把如下代码加入<body>区域中:
<script language="JavaScript1.2">
<!--hide
var isnMonth = new
Array("1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月");
var isnDay = new
Array("星期日","星期一","星期二","星期三","星期四","星期五","星期六","星期日");
today = new Date () ;
Year=today.getYear();
Date=today.getDate();
if (document.all)
document.title="今天是: "+Year+"年"+isnMonth[today.getMonth()]+Date+"日"+isnDay[today.getDay()]
//--hide-->
</script>
52、显示所有链接
把如下代码加入<body>区域中
<script language="JavaScript1.2">
<!--
function extractlinks(){
var links=document.all.tags("A")
var total=links.length
var win2=window.open("","","menubar,scrollbars,toolbar")
win2.document.write("<font size='2'>一共有"+total+"个连接</font><br>")
for (i=0;i<total;i++){
win2.document.write("<font size='2'>"+links[i].outerHTML+"</font><br>")
}
}
//-->
</script>
<input type="button" onClick="extractlinks()" value="显示所有的连接">
53、回车键换行
把如下代码加入<body>区域中
<script type="text/javascript">
function handleEnter (field, event) {
var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
if (keyCode == 13) {
var i;
for (i = 0; i < field.form.elements.length; i++)
if (field == field.form.elements[i])
break;
i = (i + 1) % field.form.elements.length;
field.form.elements[i].focus();
return false;
}
else
return true;
}
</script>
<form>
<input type="text" onkeypress="return handleEnter(this, event)"><br>
<input type="text" onkeypress="return handleEnter(this, event)"><br>
<textarea>回车换行
54、确认后提交
把如下代码加入<body>区域中
<SCRIPT LANGUAGE="JavaScript">
<!--
function msg(){
if (confirm("你确认要提交嘛!"))
document.lnman.submit()
}
//-->
</SCRIPT>
<form name="lnman" method="post" action="">
<p>
<input type="text" name="textfield" value="确认后提交">
</p>
<p>
<input type="button" name="Submit" value="提交" onclick="msg();">
</p>
</form>
55、改变表格的内容
把如下代码加入<body>区域中
<script language=javascript>
var arr=new Array()
arr[0]="一一一一一";
arr[1]="二二二二二";
arr[2]="三三三三三";
</script>
<select onchange="zz.cells[this.selectedIndex].innerHTML=arr[this.selectedIndex]">
<option value=a>改变第一格</option>
<option value=a>改变第二格</option>
<option value=a>改变第三格</option>
</select>
<table id=zz border=1>
<tr height=20>
<td width=150>第一格</td>
<td width=150>第二格</td>
<td width=150>第三格</td>
</tr>
</table>
posted @
2007-11-20 16:44 xzc 阅读(322) |
评论 (0) |
编辑 收藏
CREATE OR REPLACE Procedure Create_Synonym Authid Current_User Is
Sun Varchar2(1000);
i Number;
Begin
For i In (Select Table_Name From Dba_Tables Where Owner = 'NEWWSS') Loop
Begin
Sun := i.Table_Name;
Execute Immediate 'create or replace synonym WSS_' || Sun ||
' for NEWWSS.' || Sun || '@WSS_LINK.US.ORACLE.COM';
Exception
When Others Then
Null;
End;
End Loop;
End Create_Synonym;
posted @
2007-10-24 11:05 xzc 阅读(2192) |
评论 (0) |
编辑 收藏
JSP动作利用XML语法格式的标记来控制Servlet引擎的行为。利用JSP动作可以动态地插入文件、重用JavaBean组件、把用户重定向到另外的页面、为Java插件生成HTML代码。
JSP动作包括:
jsp:include:在页面被请求的时候引入一个文件。
jsp:useBean:寻找或者实例化一个JavaBean。
jsp:setProperty:设置JavaBean的属性。
jsp:getProperty:输出某个JavaBean的属性。
jsp:forward:把请求转到一个新的页面。
jsp:plugin:根据浏览器类型为Java插件生成OBJECT或EMBED标记。
13.1 jsp:include动作
该动作把指定文件插入正在生成的页面。其语法如下:
<jsp:include page="relative URL" flush="true" />
前面已经介绍过include指令,它是在JSP文件被转换成Servlet的时候引入文件,而这里的jsp:include动作不同,插入文件的时间是在页面被请求的时候。jsp:include动作的文件引入时间决定了它的效率要稍微差一点,而且被引用文件不能包含某些JSP代码(例如不能设置HTTP头),但它的灵活性却要好得多。
例如,下面的JSP页面把4则新闻摘要插入一个“What s New ?”页面。改变新闻摘要时只需改变这四个文件,而主JSP页面却可以不作修改:
WhatsNew.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>What s New</TITLE>
</HEAD>
<BODY BGCOLOR="#FDF5E6" TEXT="#000000" LINK="#0000EE"
VLINK="#551A8B" ALINK="#FF0000">
<CENTER>
<TABLE BORDER=5 BGCOLOR="#EF8429">
<TR><TH CLASS="TITLE">
What s New at JspNews.com</TABLE>
</CENTER>
<P>
Here is a summary of our four most recent news stories:
<OL>
<LI><jsp:include page="news/Item1.html" flush="true"/>
<LI><jsp:include page="news/Item2.html" flush="true"/>
<LI><jsp:include page="news/Item3.html" flush="true"/>
<LI><jsp:include page="news/Item4.html" flush="true"/>
</OL>
</BODY>
</HTML>
13.2 jsp:useBean动作
jsp:useBean动作用来装载一个将在JSP页面中使用的JavaBean。这个功能非常有用,因为它使得我们既可以发挥Java组件重用的优势,同时也避免了损失JSP区别于Servlet的方便性。jsp:useBean动作最简单的语法为:
<jsp:useBean id="name" class="package.class" />
这行代码的含义是:“创建一个由class属性指定的类的实例,然后把它绑定到其名字由id属性给出的变量上”。不过,就象我们接下来会看到的,定义一个scope属性可以让Bean关联到更多的页面。此时,jsp:useBean动作只有在不存在同样id和scope的Bean时才创建新的对象实例,同时,获得现有Bean的引用就变得很有必要。
获得Bean实例之后,要修改Bean的属性既可以通过jsp:setProperty动作进行,也可以在Scriptlet中利用id属性所命名的对象变量,通过调用该对象的方法显式地修改其属性。这使我们想起,当我们说“某个Bean有一个类型为X的属性foo”时,就意味着“这个类有一个返回值类型为X的getFoo方法,还有一个setFoo方法以X类型的值为参数”。
有关jsp:setProperty动作的详细情况在后面讨论。但现在必须了解的是,我们既可以通过jsp:setProperty动作的value属性直接提供一个值,也可以通过param属性声明Bean的属性值来自指定的请求参数,还可以列出Bean属性表明它的值
1Y0-327 应该来自请求参数中的同名变量。
在JSP表达式或Scriptlet中读取Bean属性通过调用相应的getXXX方法实现,或者更一般地,使用jsp:getProperty动作。
注意包含Bean的类文件应该放到服务器正式存放Java类的目录下,而不是保留给修改后能够自动装载的类的目录。例如,对于Java Web Server来说,Bean和所有Bean用到的类都应该放入classes目录,或者封装进jar文件后放入lib目录,但不应该放到servlets下。
下面是一个很简单的例子,它的功能是装载一个Bean,然后设置/读取它的message属性。
BeanTest.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Reusing JavaBeans in JSP</TITLE>
</HEAD>
<BODY>
<CENTER>
<TABLE BORDER=5>
<TR><TH CLASS="TITLE">
Reusing JavaBeans in JSP</TABLE>
</CENTER>
<P>
<jsp:useBean id="test" class="hall.SimpleBean" />
<jsp:setProperty name="test"
property="message"
value="Hello WWW" />
<H1>Message: <I>
<jsp:getProperty name="test" property="message" />
</I></H1>
</BODY>
</HTML>
SimpleBean.java
BeanTest页面用到了一个SimpleBean。SimpleBean的代码如下:
package hall;
public class SimpleBean {
private String message = "No message specified";
public String getMessage() {
return(message);
}
public void setMessage(String message) {
this.message = message;
}
}
13.3 关于jsp:useBean的进一步说明
使用Bean最简单的方法是先用下面的代码装载Bean:
<jsp:useBean id="name" class="package.class" />
然后通过jsp:setProperty和jsp:getProperty修改和提取Bean的属性。不过有两点必须注意。第一,我们还可以用下面这种格式实例化Bean:
<jsp:useBean ...>
Body
</jsp:useBean>
它的意思是,只有当第一次实例化Bean时才执行Body部分,如果是利用现有的Bean实例则不执行Body部分。正如
jn0-140 下面将要介绍的,jsp:useBean并非总是意味着创建一个新的Bean实例。
第二,除了id和class外,jsp:useBean还有其他三个属性,即:scope,type,beanName。下表简要说明这些属性的用法。 属性 用法
id 命名引用该Bean的变量。如果能够找到id和scope相同的Bean实例,jsp:useBean动作将使用已有的Bean实例而不是创建新的实例。
class 指定Bean的完整包名。
scope 指定Bean在哪种上下文内可用,可以取下面的四个值之一:page,request,session和application。
默认值是page,表示该Bean只在当前页面内可用(保存在当前页面的PageContext内)。
request表示该Bean在当前的客户请求内有效(保存在ServletRequest对象内)。
session表示该Bean对当前HttpSession内的所有页面都有效。
最后,如果取值application,则表示该Bean对所有具有相同ServletContext的页面都有效。
scope之所以很重要,是因为jsp:useBean只有在不存在具有相同id和scope的对象时才会实例化新的对象;如果已有id和scope都相同的对象则直接使用已有的对象,此时jsp:useBean开始标记和结束标记之间的任何内容都将被忽略。
type 指定引用该对象的变量的类型,它必须是Bean类的名字、超类名字、该类所实现的接口名字之一。请记住变量的名字是由id属性指定的。
beanName 指定Bean的名字。如果提供了type属性和beanName属性,允许省略class属性。
13.4 jsp:setProperty动作
jsp:setProperty用来设置已经实例化的Bean对象的属性,有两种用法。首先,你可以在jsp:useBean元素的外面(后面)使用jsp:setProperty,如下所示:
<jsp:useBean id="myName" ... />
...
<jsp:setProperty name="myName"
property="someProperty" ... />
此时,不管jsp:useBean是找到了一个现有的Bean,还是新创建了一个Bean实例,jsp:setProperty都会执行。第二种用法是把jsp:setProperty放入jsp:useBean元素的内部,如下所示:
<jsp:useBean id="myName" ... >
...
<jsp:setProperty name="myName"
property="someProperty" ... />
</jsp:useBean>
此时,jsp:setProperty只有在新建Bean实例时才会执行,如果是使用现有实例则不执行jsp:setProperty。
jsp:setProperty动作有下面四个属性: 属性 说明
name name属性是必需的。它表示要设置属性的是哪个Bean。
property property属性是必需的。它表示要设置哪个属性。有一个特殊用法:如果property的值是“*”,表示所有名字和Bean属性名字匹配的请求参数都将被传递给相应的属性set方法。
value value属性是可选的。该属性用来指定Bean属性的值。字符串数据会在目标类中通过标准的valueOf方法自动转换成数字、boolean、Boolean、byte、Byte、char、Character。例如,boolean和Boolean类型的属性值(比如“true”)通过Boolean.valueOf转换,int和Integer类型的属性值(比如“42”)通过Integer.valueOf转换。
value和param不能同时使用,但可以使用其中任意一个。
param param是可选的。它指定用哪个请求参数作为Bean属性的值。如果当前请求没有参数,则什么事情也不做,系统不会把null传递给Bean属性的set方法。因此,你可以让Bean自己提供默认属性值,只有当请求参数明确指定了新值时才修改默认属性值。
例如,下面的代码片断表示:如果存在numItems请求参数的话,把numberOfItems属性的值设置为请求参数numItems的值;否则什么也不做。
<jsp:setProperty name="orderBean"
property="numberOfItems"
param="numItems" />
如果同时省略value和param,其效果相当于提供一个param且其值等于property的值。进一步利用这种借助请求参数和属性名字相同进行自动赋值的思想,你还可以在property(Bean属性的名字)中指定“*”,然后省略value和param。此时,服务器会查看所有的Bean属性和请求参数,如果两者名字相同则自动赋值。
下面是一个利用JavaBean计算素数的例子。如果请求中有一个numDigits参数,则该值被传递给Bean的numDigits属性;numPrimes也类似。
JspPrimes.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>在JSP中使用JavaBean</TITLE>
</HEAD>
<BODY>
<CENTER>
<TABLE BORDER=5>
<TR><TH CLASS="TITLE">
在JSP中使用JavaBean</TABLE>
</CENTER>
<P>
<jsp:useBean id="primeTable" class="hall.NumberedPrimes" />
<jsp:setProperty name="primeTable" property="numDigits" />
<jsp:setProperty name="primeTable" property="numPrimes" />
Some <jsp:getProperty name="primeTable" property="numDigits" />
digit primes:
<jsp:getProperty name="primeTable" property="numberedList" />
</BODY>
</HTML>
注:NumberedPrimes的代码略。
13.5 jsp:getProperty动作
jsp:getProperty动作提取指定Bean属性的值,转换成字符串,然后输出。jsp:getProperty有两个必需的属性,即:name,表示Bean的名字;property,表示要提取哪个属性的值。下面是一个例子,更多的例子可以在前文找到。
<jsp:useBean id="itemBean" ... />
...
<UL>
<LI>Number of items:
<jsp:getProperty name="itemBean" property="numItems" />
<LI>Cost of each:
<jsp:getProperty name="itemBean" property="unitCost" />
</UL>
13.6 jsp:forward动作
jsp:forward动作把请求转到另外的页面。jsp:forward标记只有一个属性page。page属性包含的是一个相对URL。page的值既可以直接给出,也可以在请求的时候动态计算,如下面的例子所示:
<jsp:forward page="/utils/errorReporter.jsp" />
<jsp:forward page="<%= someJavaExpression %>" />
13.7 jsp:plugin动作
jsp:plugin动作用来根据浏览器的类型,插入通过Java插件 运行Java Applet所必需的OBJECT或EMBED元素。
附录:JSP注释和字符引用约定
下面是一些特殊的标记或字符,你可以利用它们插入注释或可能被视为具有特殊含义的字符。 语法 用途
<%-- comment --%> JSP注释,也称为“隐藏注释”。JSP引擎将忽略它。标记内的所有JSP脚本元素、指令和动作都将不起作用。
<!-- comment --> HTML注释,也称为“输出的注释”,直接出现在结果HTML文档中。标记内的所有JSP脚本元素、指令和动作正常执行。
<\% 在模板文本(静态HTML)中实际上希望出现“<%”的地方使用。
%\> 在脚本元素内实际上希望出现“%>”的地方使用。
\ 使用单引号的属性内的单引号。不过,你既可以使用单引号也可以使用双引号,而另外一种引号将具有普通含义。
\" 使用双引号的属性内的双引号。参见“\ ”的说明。
posted @
2007-10-19 12:57 xzc 阅读(341) |
评论 (0) |
编辑 收藏
网络收集:PLSQL常用方法汇总
在SQLPLUS下,实现中-英字符集转换
alter session set nls_language='AMERICAN';
alter session set nls_language='SIMPLIFIED CHINESE';
主要知识点:
一、有关表的操作
1)建表
create table test as select * from dept; --从已知表复制数据和结构
create table test as select * from dept where 1=2; --从已知表复制结构但不包括数据
2)插入数据:
insert into test select * from dept;
二、运算符
算术运算符:+ - * / 可以在select 语句中使用
连接运算符:|| select deptno|| dname from dept;
比较运算符:> >= = != < <= like between is null in
逻辑运算符:not and or
集合运算符: intersect(交),union(并 不重复), union all(并 重复), minus(差)
要求:对应集合的列数和数据类型相同
查询中不能包含long 列
列的标签是第一个集合的标签
使用order by时,必须使用位置序号,不能使用列名
例:集合运算符的使用:
intersect ,union, union all, minus
select * from emp intersect select * from emp where deptno=10 ;
select * from emp minus select * from emp where deptno=10;
select * from emp where deptno=10 union select * from emp where deptno in (10,20); --不包括重复行
select * from emp where deptno=10 union all select * from emp where deptno in (10,20); --包括重复行三,常用 ORACLE 函数
sysdate为系统日期 dual为虚表
一)日期函数[重点掌握前四个日期函数]
-----------------------------------------
TO_DATE格式
Day:
dd number 12
dy abbreviated fri
day spelled out friday
ddspth spelled out, ordinal twelfth
Month:
mm number 03
mon abbreviated mar
month spelled out march
Year:
yy two digits 98
yyyy four digits 1998
Time:
HH24:MI:SS
HH12:MI:SS
24小时格式下时间范围为: 0:00:00 - 23:59:59....
12小时格式下时间范围为: 1:00:00 - 12:59:59 ....
-----------------------------------------
1,add_months[返回日期加(减)指定月份后(前)的日期]
select sysdate S1, add_months(sysdate, 10) S2, add_months(sysdate, 5) S3
from dual;
2,last_day [返回该月最后一天的日期]
select sysdate,last_day(sysdate) from dual;
3,months_between[返回日期之间的月份数]
select sysdate S1,
months_between('1-4月-04', sysdate) S2,
months_between('1-4月-04', '1-2月-04') S3
from dual
4,next_day(d,day): 返回下个星期的日期,day为1-7或星期日-星期六,1表示星期日
select sysdate S1, next_day(sysdate, 1) S2, next_day(sysdate, '星期日') S3
FROM DUAL
5,round[舍入到最接近的日期](day:舍入到最接近的星期日)
select sysdate S1,
round(sysdate) S2,
round(sysdate, 'year') YEAR,
round(sysdate, 'month') MONTH,
round(sysdate, 'day') DAY
from dual
6,trunc[截断到最接近的日期]
select sysdate S1,
trunc(sysdate) S2,
trunc(sysdate, 'year') YEAR,
trunc(sysdate, 'month') MONTH,
trunc(sysdate, 'day') DAY
from dual
7,返回日期列表中最晚日期
select greatest('01-1月-04', '04-1月-04', '10-2月-04') from dual
二)字符函数(可用于字面字符或数据库列)
1,字符串截取
select substr('abcdef',1,3) from dual
2,查找子串位置
select instr('abcfdgfdhd','fd') from dual
3,字符串连接
select 'HELLO'||'hello world' from dual;
4, 1)去掉字符串中的空格
select ltrim(' abc') s1, rtrim('zhang ') s2, trim(' zhang ') s3 from dual
2)去掉前导和后缀
select trim(leading 9 from 9998767999) s1,
trim(trailing 9 from 9998767999) s2,
trim(9 from 9998767999) s3
from dual;
5,返回字符串首字母的Ascii值
select ascii('a') from dual
6,返回ascii值对应的字母
select chr(97) from dual
7,计算字符串长度
select length('abcdef') from dual
8,initcap(首字母变大写) ,lower(变小写),upper(变大写)
select lower('ABC') s1,
upper('def') s2,
initcap('efg') s3 from dual;
9,Replace
select replace('abc','b','xy') from dual;
10,translate
select translate('abc','b','xx') from dual; -- x是1位
11,lpad [左添充] rpad [右填充](用于控制输出格式)
select lpad('func',15,'=') s1, rpad('func',15,'-') s2 from dual;
select lpad(dname,14,'=') from dept;
12, decode[实现if ..then 逻辑]
select deptno,decode(deptno,10,'1',20,'2',30,'3','其他') from dept;
三)数字函数
1,取整函数(ceil 向上取整,floor 向下取整)
select ceil(66.6) N1,floor(66.6) N2 from dual;
2, 取幂(power) 和 求平方根(sqrt)
select power(3,2) N1,sqrt(9) N2 from dual;
3,求余
select mod(9,5) from dual;
4,返回固定小数位数 (round:四舍五入,trunc:直接截断)
select round(66.667,2) N1,trunc(66.667,2) N2 from dual;
5,返回值的符号(正数返回为1,负数为-1)
select sign(-32),sign(293) from dual;
四)转换函数
1,to_char()[将日期和数字类型转换成字符类型]
1) select to_char(sysdate) s1,
to_char(sysdate,'yyyy-mm-dd') s2,
to_char(sysdate,'yyyy') s3,
to_char(sysdate,'yyyy-mm-dd hh12:mi:ss') s4,
to_char(sysdate, 'hh24:mi:ss') s5,
to_char(sysdate,'DAY') s6 from dual;
2) select sal,to_char(sal,'$99999') n1,to_char(sal,'$99,999') n2 from emp
2, to_date()[将字符类型转换为日期类型]
insert into emp(empno,hiredate) values(8000,to_date('2004-10-10','yyyy-mm-dd'));
3, to_number() 转换为数字类型
select to_number(to_char(sysdate,'hh12')) from dual; //以数字显示的小时数
五)其他函数
user:
返回登录的用户名称
select user from dual;
vsize:
返回表达式所需的字节数
select vsize('HELLO') from dual;
nvl(ex1,ex2):
ex1值为空则返回ex2,否则返回该值本身ex1(常用)
例:如果雇员没有佣金,将显示0,否则显示佣金
select comm,nvl(comm,0) from emp;
nullif(ex1,ex2):
值相等返空,否则返回第一个值
例:如果工资和佣金相等,则显示空,否则显示工资
select nullif(sal,comm),sal,comm from emp;
coalesce:
返回列表中第一个非空表达式
select comm,sal,coalesce(comm,sal,sal*10) from emp;
nvl2(ex1,ex2,ex3) :
如果ex1不为空,显示ex2,否则显示ex3
如:查看有佣金的雇员姓名以及他们的佣金
select nvl2(comm,ename,'') as HaveCommName,comm from emp;
六)分组函数
max min avg count sum
1,整个结果集是一个组
1) 求部门30 的最高工资,最低工资,平均工资,总人数,有工作的人数,工种数量及工资总和
select max(ename),max(sal),
min(ename),min(sal),
avg(sal),
count(*) ,count(job),count(distinct(job)) ,
sum(sal) from emp where deptno=30;
2, 带group by 和 having 的分组
1)按部门分组求最高工资,最低工资,总人数,有工作的人数,工种数量及工资总和
select deptno, max(ename),max(sal),
min(ename),min(sal),
avg(sal),
count(*) ,count(job),count(distinct(job)) ,
sum(sal) from emp group by deptno;
2)部门30的最高工资,最低工资,总人数,有工作的人数,工种数量及工资总和
select deptno, max(ename),max(sal),
min(ename),min(sal),
avg(sal),
count(*) ,count(job),count(distinct(job)) ,
sum(sal) from emp group by deptno having deptno=30;
3, stddev 返回一组值的标准偏差
select deptno,stddev(sal) from emp group by deptno;
variance 返回一组值的方差差
select deptno,variance(sal) from emp group by deptno;
4, 带有rollup和cube操作符的Group By
rollup 按分组的第一个列进行统计和最后的小计
cube 按分组的所有列的进行统计和最后的小计
select deptno,job ,sum(sal) from emp group by deptno,job;
select deptno,job ,sum(sal) from emp group by rollup(deptno,job);
cube 产生组内所有列的统计和最后的小计
select deptno,job ,sum(sal) from emp group by cube(deptno,job);七、临时表
只在会话期间或在事务处理期间存在的表.
临时表在插入数据时,动态分配空间
create global temporary table temp_dept
(dno number,
dname varchar2(10))
on commit delete rows;
insert into temp_dept values(10,'ABC');
commit;
select * from temp_dept; --无数据显示,数据自动清除
on commit preserve rows:在会话期间表一直可以存在(保留数据)
on commit delete rows:事务结束清除数据(在事务结束时自动删除表的数据)
Oracle时间日期操作
sysdate+(5/24/60/60) 在系统时间基础上延迟5秒
sysdate+5/24/60 在系统时间基础上延迟5分钟
sysdate+5/24 在系统时间基础上延迟5小时
sysdate+5 在系统时间基础上延迟5天
add_months(sysdate,-5) 在系统时间基础上延迟5月
add_months(sysdate,-5*12) 在系统时间基础上延迟5年
上月末的日期:select last_day(add_months(sysdate, -1)) from dual;
本月的最后一秒:select trunc(add_months(sysdate,1),'MM') - 1/24/60/60 from dual
本周星期一的日期:select trunc(sysdate,'day')+1 from dual
年初至今的天数:select ceil(sysdate - trunc(sysdate, 'year')) from dual;
今天是今年的第几周 :select to_char(sysdate,'fmww') from dual
今天是本月的第几周:SELECT TO_CHAR(SYSDATE,'WW') - TO_CHAR(TRUNC(SYSDATE,'MM'),'WW') + 1 AS "weekOfMon" FROM dual
本月的天数
SELECT to_char(last_day(SYSDATE),'dd') days FROM dual
今年的天数
select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual
下个星期一的日期
SELECT Next_day(SYSDATE,'monday') FROM dual
============================================
--计算工作日方法
create table t(s date,e date);
alter session set nls_date_format = 'yyyy-mm-dd';
insert into t values('2003-03-01','2003-03-03');
insert into t values('2003-03-02','2003-03-03');
insert into t values('2003-03-07','2003-03-08');
insert into t values('2003-03-07','2003-03-09');
insert into t values('2003-03-05','2003-03-07');
insert into t values('2003-02-01','2003-03-31');
-- 这里假定日期都是不带时间的,否则在所有日期前加trunc即可。
select s,e,e-s+1 total_days,
trunc((e-s+1)/7)*5 + length(replace(substr('01111100111110',to_char(s,'d'),mod(e-s+1,7)),'0','')) work_days
from t;
-- drop table t;
引此:http://www.itpub.net/showthread.php?s=1635506cd5f48b1bc3adbe4cde96f227&threadid=104060&perpage=15&pagenumber=1
================================================================================
判断当前时间是上午下午还是晚上
SELECT CASE
WHEN to_number(to_char(SYSDATE,'hh24')) BETWEEN 6 AND 11 THEN '上午'
WHEN to_number(to_char(SYSDATE,'hh24')) BETWEEN 11 AND 17 THEN '下午'
WHEN to_number(to_char(SYSDATE,'hh24')) BETWEEN 17 AND 21 THEN '晚上'
END
FROM dual;
================================================================================
Oracle 中的一些处理日期
将数字转换为任意时间格式.如秒:需要转换为天/小时
SELECT to_char(floor(TRUNC(936000/(60*60))/24))||'天'||to_char(mod(TRUNC(936000/(60*60)),24))||'小时' FROM DUAL
TO_DATE格式
Day:
dd number 12
dy abbreviated fri
day spelled out friday
ddspth spelled out, ordinal twelfth
Month:
mm number 03
mon abbreviated mar
month spelled out march
Year:
yy two digits 98
yyyy four digits 1998
24小时格式下时间范围为: 0:00:00 - 23:59:59....
12小时格式下时间范围为: 1:00:00 - 12:59:59 ....
1.
日期和字符转换函数用法(to_date,to_char)
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.
获得小时数
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) 作为月
mod(mod(date2-date1, 365), 30)作为日.
23.next_day函数
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 dual
日期 返回的是天 然后 转换为ss
转此:http://www.onlinedatabase.cn/leadbbs/Announce/Announce.asp?BoardID=42&ID=1769
将数字转换为任意时间格式.如秒:需要转换为天/小时
SELECT to_char(floor(TRUNC(936000/(60*60))/24))||'天'||to_char(mod(TRUNC(936000/(60*60)),24))||'小时' FROM DUAL
TO_DATE格式
Day:
dd number 12
dy abbreviated fri
day spelled out friday
ddspth spelled out, ordinal twelfth
Month:
mm number 03
mon abbreviated mar
month spelled out march
Year:
yy two digits 98
yyyy four digits 1998
24小时格式下时间范围为: 0:00:00 - 23:59:59....
12小时格式下时间范围为: 1:00:00 - 12:59:59 ....
1.
日期和字符转换函数用法(to_date,to_char)
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.
获得小时数
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) 作为月
mod(mod(date2-date1, 365), 30)作为日.
23.next_day函数
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 dual
日期 返回的是天 然后 转换为ss
转此:http://www.onlinedatabase.cn/leadbbs/Announce/Announce.asp?BoardID=42&ID=1769
将数字转换为任意时间格式.如秒:需要转换为天/小时
SELECT to_char(floor(TRUNC(936000/(60*60))/24))||'天'||to_char(mod(TRUNC(936000/(60*60)),24))||'小时' FROM DUAL
TO_DATE格式
Day:
dd number 12
dy abbreviated fri
day spelled out friday
ddspth spelled out, ordinal twelfth
Month:
mm number 03
mon abbreviated mar
month spelled out march
Year:
yy two digits 98
yyyy four digits 1998
24小时格式下时间范围为: 0:00:00 - 23:59:59....
12小时格式下时间范围为: 1:00:00 - 12:59:59 ....
1.
日期和字符转换函数用法(to_date,to_char)
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.
获得小时数
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) 作为月
mod(mod(date2-date1, 365), 30)作为日.
23.next_day函数
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 dual
日期 返回的是天 然后 转换为ss
转此:http://www.onlinedatabase.cn/leadbbs/Announce/Announce.asp?BoardID=42&ID=1769
将数字转换为任意时间格式.如秒:需要转换为天/小时
SELECT to_char(floor(TRUNC(936000/(60*60))/24))||'天'||to_char(mod(TRUNC(936000/(60*60)),24))||'小时' FROM DUAL
TO_DATE格式
Day:
dd number 12
dy abbreviated fri
day spelled out friday
ddspth spelled out, ordinal twelfth
Month:
mm number 03
mon abbreviated mar
month spelled out march
Year:
yy two digits 98
yyyy four digits 1998
24小时格式下时间范围为: 0:00:00 - 23:59:59....
12小时格式下时间范围为: 1:00:00 - 12:59:59 ....
1.
日期和字符转换函数用法(to_date,to_char)
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.
获得小时数
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) 作为月
mod(mod(date2-date1, 365), 30)作为日.
23.next_day函数
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 dual
日期 返回的是天 然后 转换为ss
posted @
2007-10-18 14:03 xzc 阅读(2162) |
评论 (2) |
编辑 收藏
import java.util.Calendar;
import java.util.GregorianCalendar;
public class Date{
public static void main(String[] args){
//获取今天的年月日星期
Calendar dt = new GregorianCalendar();
int year = dt.get(Calendar.YEAR);
int month = dt.get(Calendar.MONTH)+1;
int day= dt.get(Calendar.DAY_OF_MONTH);
int dayOfWeek= dt.get(Calendar.DAY_OF_WEEK)-1;
System.out.println("今天是"+year+"年"+month+"月"+day+"
日,星期"+dayOfWeek);
//获取指定月份的最大天数
int days = dt.getActualMaximum(month);
System.out.println("本月共有"+days+"天");
//判断是否是闰年
GregorianCalendar da = new GregorianCalendar();
boolean b = da.isLeapYear(2004);
System.out.println(b);
}
}
import java.util.Properties;
import java.io.FileInputStream;
import java.io.IOException;
public class Files{
public static void main(String[] args){
try{
Properties files = new Properties();
files.load(new FileInputStream("Files.Properties"));
String a = files.getProperty("a");
System.out.println(a);
}catch (IOException e) {
}
}
}
//求昨天的当前时间
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Date;
import java.text.SimpleDateFormat;
public class Date1{
public static void main(String[] args){
Calendar date = new GregorianCalendar();
date.add(Calendar.DAY_OF_MONTH,-1);
Date yesterday= date.getTime();
String yesterday2 = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(yesterday);
System.out.println(yesterday2);
}
}
posted @
2007-09-14 09:43 xzc 阅读(579) |
评论 (1) |
编辑 收藏