發(fā)布日期:2006年07月30日,更新日期:2006年07月30日
1996年初,歐洲安全電子市場(EU SEMPER)項目組決定編寫自己的日志記錄API,后來這個API演變成了Log4j。Log4j是一個開放源碼項目,一個非常流行的Java日志記錄包。它允許開發(fā)者向代碼中插入日志記錄語句,還允許在不修改應(yīng)用程序源碼的情況下修改記錄日志的行為。
1996年初,歐洲安全電子市場(EU SEMPER)項目組決定編寫自己的日志記錄API,后來這個API演變成了Log4j。Log4j是一個開放源碼項目,一個非常流行的Java日志記錄包。它允許開發(fā)者向代碼中插入日志記錄語句,還允許在不修改應(yīng)用程序源碼的情況下修改日志記錄的行為。
幾乎每一個項目都會使用日志記錄,但是由于日志記錄不是項目的核心,因此受重視的程度一般不是很高。我們認為使用日志記錄是一件非常嚴肅的事情,而且做好使用日志記錄的規(guī)劃比單純記錄日志本身更加重要。
本文將比較全面的闡述Log4j的設(shè)計原理和使用方法。
日志記錄記錄的是應(yīng)用程序運行的軌跡。我們可以通過查看這些軌跡來調(diào)試應(yīng)用程序,這可能也是日志記錄最為流行的用法了。但是我們必須意識到規(guī)劃良好的日志記錄中還含有豐富的信息,通過手工的方式或借助一些工具(大多數(shù)時候需要自己來書寫這些工具)來分析挖掘這些信息。
例如,如果我們在規(guī)劃中指出必須記錄用戶的每一次操作,記錄的樣式為 [日志信息]-[操作開始的時間]-[日志級別]-[日志類別]-[用戶名]-[操作名]-[消息],這只是我們假設(shè)的一種樣式,實際的日志中一般會含有比這更加豐富的信息。為了更好的理解,我們根據(jù)該樣式構(gòu)造了一些日志記錄(其中日志類別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]-[退出系統(tǒng)]-[具體的消息]
從上面的日志記錄中我們很容易抽取出某一用戶的操作列表,如對于用戶User1我們的結(jié)果為:
[日志信息]-[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的操作列表,可以利用這一列表來進行安全分析。
我們還可以從另外的角度來分析上面的日志記錄,如我們很容易統(tǒng)計出操作(日志類別為org.solol.UserOperator)發(fā)生的總次數(shù)(6次),其中操作[查詢報表1]為2次,[查詢報表2]為1次,[查詢報表3]為1次,[添加用戶User3]為1次,[退出系統(tǒng)]為1次。這樣我們就可以得出系統(tǒng)中的那些操作用戶使用的比較頻繁。
以上我們從兩個角度對日記記錄中的信息進行了簡單的挖掘,實際中待挖掘的方面要豐富的多,這取決于您的意圖和您的想象力。
這里我們還要特別強調(diào)一下:所有這一切都需要有使用日志記錄的良好規(guī)劃。如果規(guī)劃不好(即日志記錄沒有規(guī)律性),那么我們挖掘時的任務(wù)就會非常繁重或者使挖掘成為一個不可能的任務(wù)。
文章到了這里我們要來描述日志記錄的最為流行的用法了,即調(diào)試應(yīng)用程序。我們在調(diào)試應(yīng)用程序時一般會使用兩種方法,除了日志記錄之外,還有debugger調(diào)試器。
我們不想把他們放到一起來描述,因為這是兩個完全不同的問題,雖然他們都用來調(diào)試應(yīng)用程序。使用debugger調(diào)試器我們可以清楚的知道引發(fā)錯誤的上下文及其相關(guān)信息,也可以使用單步執(zhí)行、設(shè)置斷點、檢查變量以及暫掛和恢復(fù)線程等等比較高級的能力,但是盡管這樣它也不能替代日志記錄,同樣日志記錄也不能替代debugger調(diào)試器。我們要結(jié)合使用這兩種方法,不同的場景使用不同的方法會有更好的效果。
我們認為使用日志記錄來調(diào)試應(yīng)用程也應(yīng)該充分考慮軟件的開發(fā)周期。這里我們只考慮軟件開發(fā)周期中的與日志記錄有關(guān)的兩個階段:
- 開發(fā)階段,用來記錄應(yīng)用程序的方方面面和各種細節(jié),非常詳細,使得一看到它就知道那里出了問題,出了什么樣的問題。
- 出品階段,要能夠記錄各種級別的錯誤和警告,同時也要適度記錄應(yīng)用程序正常運行的關(guān)鍵信息,這些信息可以給相關(guān)人員(開發(fā)人員、測試人員、用戶等)極大的信心,使他們可以毫不猶豫的告訴您--瞧我們的軟件在正常的運行。如一個好的web服務(wù)器的啟動日志記錄不僅要包含錯誤和警告,還要包含服務(wù)器正在啟動,正在加載某某組件等等,最后還要提示啟動是成功還是失敗。
閱讀到這里我們就應(yīng)該著手實現(xiàn)我們的日志記錄了。比較幸運的是我們有好多日志記錄軟件包可選,這就使我們不必關(guān)心日志記錄的細節(jié),只要把主要的精力放到日志記錄的規(guī)劃上就好了。我們選擇的是Log4j,文章的余下部分將主要介紹這個Java日志記錄軟件包。
log4j的特性列表:
- 在運行速度方面進行了優(yōu)化
- 使用基于名稱的日志(logger)層次結(jié)構(gòu)
- 是fail-stop的
- 是線程安全的
- 不受限于預(yù)定義的實用工具集
- 可以在運行時使用property和xml兩種格式的文件來配置日志記錄的行為
- 在一開始就設(shè)計為能夠處理Java異常
- 能夠定向輸出到文件(file)、控制臺(console)、java.io.OutputStream、java.io.Writer、遠程服務(wù)器、遠程Unix Syslog守護者、遠程JMS監(jiān)聽者、NT EventLog或者發(fā)送e-mail
- 使用DEBUG、INFO、WARN、ERROR和FATAL五5個級別
- 可以容易的改變?nèi)罩居涗浀牟季?Layout)
- 輸出日志記錄的目的地和寫策略可以通過實現(xiàn)Appender接口來改變
- 支持為每個日志(logger)附加多個目的地(appender)
- 提供國際化支持
Log4j有三個主要的組件:Logger、Appender和Layout。這三個組件相互配合使得我們可以獲得非常強大的日志記錄的能力。
Logger的名稱是區(qū)分大小寫的,依據(jù)名稱可以確定其層次結(jié)構(gòu)(即父子關(guān)系),規(guī)則如下:
- 如果Logger A的名稱后跟一個點(.)是Logger B的名稱的前綴就認為Logger A是Logger B的祖先。
- 如果在Logger A和Logger B之間,Logger B沒有任何其它的祖先就認為Logger A是Logger B的父親。
在Logger的層次結(jié)構(gòu)的最頂層是root logger,它會永遠存在,而且不能通過名字取到。
上面文字的描述可能不好的理解,為此我們給出了一張圖,Logger的層次結(jié)構(gòu)圖,從中可以非常直觀的看出三種主要組件的關(guān)系和各自所起的作用。
圖示 1. Logger的層次結(jié)構(gòu)圖
Loger x.y是Logger x.y.z的祖先,因為x.y.是x.y.z的前綴,這符合規(guī)則的前一條。另外在Logger x.y和Logger x.y.z之間,Logger x.y.z沒有其它的祖先,因此Logger x.y是Logger x.y.z的父親,這符合規(guī)則的后一條。這樣我們依據(jù)上面的規(guī)則就可以構(gòu)造出如圖1所示的Logger的層次結(jié)構(gòu)。
從圖1中我們還可以看到每一個Logger都有一個Level,根據(jù)該Level的值Logger決定是否處理對應(yīng)的日志請求。如果Level沒有被設(shè)置,就象圖1中的Logger x.y一樣,又該怎么辦呢?答案是可以從祖先那里繼承。
如果Logger C沒有被設(shè)置Level,那么它將沿著它的層次結(jié)構(gòu)向上查找,如果找到就繼承并結(jié)束,否則會一直查找到root logger結(jié)束。因為log4j在設(shè)計時保證root logger會被設(shè)置一個默認的Level,所以任何logger都可以繼承到Level。
圖1中的Logger x.y沒有被設(shè)置Level,但是根據(jù)上面的繼承規(guī)則,Logger x.y繼承了root logger的Level。
我們在來看看Logger選擇日志記錄請求(log request)的規(guī)則:
假設(shè)Logger M具有q級的Level,這個Level可能是設(shè)置的也可能是繼承到的。
如果向Logger M發(fā)出一個Level為p的日志記錄請求,那么只有滿足p>=q時這個日志記錄請求才會被處理。
org.apache.log4j.Logger中的不同方法發(fā)出不同Level的日志記錄請求,如下:
- public void debug(Object message),發(fā)出Level為DEBUG的日志記錄請求
- public void info(Object message),發(fā)出Level為INFO的日志記錄請求
- public void warn(Object message),發(fā)出Level為WARN的日志記錄請求
- public void error(Object message),發(fā)出Level為ERROR日志記錄請求
- public void fatal(Object message),發(fā)出Level為FATAL的日志請求
- public void log(Level l, Object message),發(fā)出指定Level的日志記錄請求
其中的靜態(tài)常量DEBUG、INFO、WARN、ERROR、FATAL是在org.apache.log4j.Level中定義的,除了使用這些預(yù)定義的Level之外,Log4j還支持自定義Level。
注:org.apache.log4j.Level中還預(yù)定義了一些其它的Level。
在Log4j中,Appender指的是日志記錄輸出的目的地。當前支持的Appender(目的地)有文件(file)、控制臺(console)、java.io.OutputStream、java.io.Writer、遠程服務(wù)器、遠程Unix Syslog守護者、遠程JMS監(jiān)聽者、NT EventLog或者發(fā)送e-mail。如果您在上面沒有找到適合的Appender,那就需要考慮實現(xiàn)自己的自定義Appender了。
每個Logger可以有多個Appender,但是相同的Appender只會被添加一次。
Appender的附加性意味著Logger C會將日志記錄發(fā)給它的和它祖先的所有Appender。在圖1中Logger a會將日志記錄發(fā)給它自己的JDBCAppender和它的祖先root logger的ConsoleAppender和FileAppender。Logger x.y.z自己沒有Appender,它將把日志記錄發(fā)給它的祖先root logger的ConsoleAppender和FileAppender,如果Logger x.y也含有Appender,那么它們也會包括在內(nèi)。
Appender的附加性是可以被中斷的。假設(shè)Logger C的一個祖先為Logger P,如果Logger P的附加性標志(additivity flag)設(shè)置為假,那么Logger C會將日志記錄只發(fā)給它的和在它和Logger P之間的祖先(包括Logger P)的Appender,而不會發(fā)給Logger P的祖先的Appender。Logger的附加性標志(additivity flag)默認值為ture。
在圖1中如果沒有設(shè)置Logger a的附加性標志(additivity flag),而是使用默認值true,那么Logger a會將日志記錄發(fā)給它自己的JDBCAppender和它祖先root logger的ConsoleAppender和FileAppender,這和上面的描述相同。如果設(shè)置Logger a的附加性標志(additivity flag)的值false,那么Logger a會將日志記錄發(fā)給它自己的JDBCAppender而不會在發(fā)給它祖先root logger的ConsoleAppender和FileAppender了。
Appender定制了輸出目的地,通常我們還需要定制日志記錄的輸出格式,在Log4j中是通過將Layout和Appender關(guān)聯(lián)到一起來實現(xiàn)的。Layout依據(jù)用戶的要求來格式化日志記錄。PatternLayout(標準Log4j組件)讓用戶依據(jù)類似于C語言printf函數(shù)的轉(zhuǎn)換模式來指定輸出格式。
例如,轉(zhuǎn)換模式(conversion pattern)為"%r [%t] %-5p %c - %m%n"的PatternLayout將生成類似于以下內(nèi)容的輸出:
176 [main] INFO org.foo.Bar - Located nearest gas station.
在上面的輸出中:
- 第一個字段表示自程序開始到發(fā)出日志記錄請求時所消耗的毫秒數(shù)
- 第二個字段表示發(fā)出日志記錄請求的線程
- 第三個字段表示日志記錄請求的Level
- 第四個字段表示發(fā)出日志記錄請求的Logger的名稱
- 第五個字段(-后的文本)表示日志記錄請求的消息
Log4j中還提到了一些其它的Layout,包括HTMLLayout、SimpleLayout、XMLLayout、TTCCLayout和DateLayout。如果這些不能滿足您的要求,還可以自定義自己的Layout。
依據(jù)既有的經(jīng)驗顯示用于日志記錄的代碼大約是全部代碼量的4%。如果應(yīng)用程序具有一定的規(guī)模,日志記錄語句的數(shù)量還是比較巨大的,因此必須有效的管理這些語句。
在Log4j中我們可以通過配置Log4j環(huán)境來有效的管理日志記錄。配置的方式有三種:
- 通過程序配置
- 通過Property文件配置
- 通過XML文件配置
通過程序配置Log4j環(huán)境實際上就是在應(yīng)用程序的代碼中改變Logger的Level或增加減少Appender等等。
Log4j提供了BasicConfigurator,它只是為root logger添加Appender。其中,
- BasicConfigurator.configure()為root logger添加一個關(guān)聯(lián)著PatternLayout.TTCC_CONVERSION_PATTERN的ConsoleAppender
- BasicConfigurator.configure(Appender appender)為root logger添加指定的Appender
我們可以把BasicConfigurator看成是一個簡單的使用程序配置Log4j環(huán)境的示例。例如,要給root logger添加兩個Appender(A和B),下面的代碼分別完成了這個要求。
不使用BasicConfigurator:
//示例代碼,不能直接使用
Logger root = Logger.getRootLogger();
root.addAppender(A);
root.addAppender(B);
使用BasicConfigurator:
//示例代碼,不能直接使用
BasicConfigurator.configure(A);
BasicConfigurator.configure(B);
這里要使用PropertyConfigurator來分析配置文件并設(shè)置日志記錄,但是要注意日志記錄先前的配置不會被清除和重設(shè)。
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
稍顯復(fù)雜的示例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的優(yōu)先級高于Logger本身的Level。語法為log4j.threshold=[level],level可以為OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL。也可以使用自定義Level,這時的語法為log4j.threshold=[level#classname]。默認為ALL。
依據(jù)上面的規(guī)則,我們有這樣的結(jié)論:如果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, ...,其中l(wèi)evel可以為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來定義將消息對象轉(zhuǎn)換成字符串的方式。語法為log4j.renderer.fully.qualified.name.of.rendered.class=fully.qualified.name.of.rendering.class。如:
//my.Fruit類型的消息對象將由my.FruitRenderer轉(zhuǎn)換成字符串
log4j.renderer.my.Fruit=my.FruitRenderer
對上面的各個配置元素的語法理解之后,在來看示例1和2就很容易了。
PropertyConfigurator不支持Filter的配置。如果要支持Filter您可以使用DOMConfigurator,即使用XML文件的方式配置。
要使用DOMConfigurator.configure()來讀取XML格式的配置文件。XML文件格式的定義是通過org/apache/log4j/xml/log4j.dtd來完成的,各個配置元素的嵌套關(guān)系如下:
<!ELEMENT log4j:configuration (renderer*, appender*,(category|logger)*,root?,categoryFactory?)>
這里沒有給出更為詳細的內(nèi)容,要了解詳細的內(nèi)容需要查閱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類的靜態(tài)初始化器中完成。具體步驟如下:
- 檢查系統(tǒng)屬性log4j.defaultInitOverride,如果值為false則執(zhí)行初始化過程,否則跳過初始化過程。
- 將系統(tǒng)屬性log4j.configuration的值賦給變量resource。如果log4j.configuration沒有被定義則使用默認值log4j.properties。
- 試圖轉(zhuǎn)換變量resource到一個url。
- 如果變量resource不能轉(zhuǎn)換成一個url,那么將使用org.apache.log4j.helpers.Loader.getResource(resource, Logger.class)得到一個url。
- 如果還是得不到url,將忽略默認初始化過程。如果得到url將使用PropertyConfigurator或DOMConfigurator來配置,也可以使用自定義的XXXConfigurator。
posted @
2008-05-21 10:20 xzc 閱讀(1978) |
評論 (0) |
編輯 收藏
摘要: 轉(zhuǎn)自:http://www.tkk7.com/fastzch/archive/2007/12/03/164912.html
1,讀入圖片的方式:
發(fā)現(xiàn)網(wǎng)上講的很多讀取圖片的方式都不對,按下面提供的這個方法來讀取,保證成功。
1 private byte[] getImageBytes(String ...
閱讀全文
posted @
2007-12-04 11:37 xzc 閱讀(1287) |
評論 (0) |
編輯 收藏
GBK的文字編碼是雙字節(jié)來表示的,即不論中、英文字符均使用雙字節(jié)來表示,只不過為區(qū)分中文,將其最高位都定成1。
至于UTF-8編碼則是用以解決國際上字符的一種多字節(jié)編碼,它對英文使用8位(即一個字節(jié)),中文使用24位(三個字節(jié))來編碼。對于英文字符較多的論壇則用UTF-8節(jié)省空間。
GBK包含全部中文字符,
UTF-8則包含全世界所有國家需要用到的字符。
GBK是在國家標準GB2312基礎(chǔ)上擴容后兼容GB2312的標準(好像還不是國家標準)
UTF-8編碼的文字可以在各國各種支持UTF8字符集的瀏覽器上顯示。
比如,如果是UTF8編碼,則在外國人的英文IE上也能顯示中文,而無需他們下載IE的中文語言支持包。
所以,對于英文比較多的論壇 ,使用GBK則每個字符占用2個字節(jié),而使用UTF-8英文卻只占一個字節(jié)。
posted @
2007-11-21 17:35 xzc 閱讀(301) |
評論 (0) |
編輯 收藏
轉(zhuǎn)自:http://blog.csdn.net/annicybc/archive/2006/06/24/829662.aspx
索引是建立在表的一列或多個列上的輔助對象,目的是加快訪問表中的數(shù)據(jù);
Oracle存儲索引的數(shù)據(jù)結(jié)構(gòu)是B*樹,位圖索引也是如此,只不過是葉子節(jié)點不同B*數(shù)索引;
索引由根節(jié)點、分支節(jié)點和葉子節(jié)點組成,上級索引塊包含下級索引塊的索引數(shù)據(jù),葉節(jié)點包含索引數(shù)據(jù)和確定行實際位置的rowid。
使用索引的目的
加快查詢速度
減少I/O操作
消除磁盤排序
何時使用索引
查詢返回的記錄數(shù)
排序表<40%
非排序表 <7%
表的碎片較多(頻繁增加、刪除)
索引的種類
非唯一索引(最常用)
唯一索引
位圖索引
局部有前綴分區(qū)索引
局部無前綴分區(qū)索引
全局有前綴分區(qū)索引
散列分區(qū)索引
基于函數(shù)的索引
管理索引的準則
在表中插入數(shù)據(jù)后創(chuàng)建索引
。在用SQL*Loader或import工具插入或裝載數(shù)據(jù)后,建立索引比較有效;
索引正確的表和列
。經(jīng)常檢索排序大表中40%或非排序表7%的行,建議建索引;
。為了改善多表關(guān)聯(lián),索引列用于聯(lián)結(jié);
。列中的值相對比較唯一;
。取值范圍(大:B*樹索引,小:位圖索引);
。Date型列一般適合基于函數(shù)的索引;
。列中有許多空值,不適合建立索引
為性能而安排索引列
。經(jīng)常一起使用多個字段檢索記錄,組合索引比單索引更有效;
。把最常用的列放在最前面,例:dx_groupid_serv_id(groupid,serv_id),在where條件中使用groupid或groupid,serv_id,查詢將使用索引,若僅用到serv_id字段,則索引無效;
。合并/拆分不必要的索引。
限制每個表索引的數(shù)量
。一個表可以有幾百個索引(你會這樣做嗎?),但是對于頻繁插入和更新表,索引越多系統(tǒng)CPU,I/O負擔就越重;
。建議每張表不超過5個索引。
刪除不再需要的索引
。索引無效,集中表現(xiàn)在該使用基于函數(shù)的索引或位圖索引,而使用了B*樹索引;
。應(yīng)用中的查詢不使用索引;
。重建索引之前必須先刪除索引,若用alter index … rebuild重建索引,則不必刪除索引。
索引數(shù)據(jù)塊空間使用
。創(chuàng)建索引時指定表空間,特別是在建立主鍵時,應(yīng)明確指定表空間;
。合理設(shè)定pctfress,注意:不能給索引指定pctused;
。估計索引的大小和合理地設(shè)置存儲參數(shù),默認為表空間大小,或initial與next設(shè)置成一樣大。
考慮并行創(chuàng)建索引
。對大表可以采用并行創(chuàng)建索引,在并行創(chuàng)建索引時,存儲參數(shù)被每個查詢服務(wù)器進程分別使用,例如:initial為1M,并行度為8,則創(chuàng)建索引期間至少要消耗8M空間;
考慮用nologging創(chuàng)建索引
。對大表創(chuàng)建索引可以使用nologging來減少重做日志;
。節(jié)省重做日志文件的空間;
。縮短創(chuàng)建索引的時間;
。改善了并行創(chuàng)建大索引時的性能。
怎樣建立最佳索引
明確地創(chuàng)建索引
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
);
創(chuàng)建基于函數(shù)的索引
。常用與UPPER、LOWER、TO_CHAR(date)等函數(shù)分類上,例:
create index idx_func on emp (UPPER(ename)) tablespace tablespace_name;
創(chuàng)建位圖索引
。對基數(shù)較小,且基數(shù)相對穩(wěn)定的列建立索引時,首先應(yīng)該考慮位圖索引,例:
create bitmap index idx_bitm on class (classno) tablespace tablespace_name;
明確地創(chuàng)建唯一索引
。可以用create unique index語句來創(chuàng)建唯一索引,例:
create unique index dept_unique_idx on dept(dept_no) tablespace idx_1;
創(chuàng)建與約束相關(guān)的索引
。可以用using index字句,為與unique和primary key約束相關(guān)的索引,例如:
alter table table_name
add constraint PK_primary_keyname primary key (field_name)
using index tablespace tablespace_name;
如何創(chuàng)建局部分區(qū)索引
。基礎(chǔ)表必須是分區(qū)表;
。分區(qū)數(shù)量與基礎(chǔ)表相同;
。每個索引分區(qū)的子分區(qū)數(shù)量與相應(yīng)的基礎(chǔ)表分區(qū)相同;
。基礎(chǔ)表的子分區(qū)中的行的索引項,被存儲在該索引的相應(yīng)的子分區(qū)中,例如:
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
/
如何創(chuàng)建范圍分區(qū)的全局索引
。基礎(chǔ)表可以是全局表和分區(qū)表。
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’ ))
/
重建現(xiàn)存的索引
重建現(xiàn)存的索引的當前時刻不會影響查詢;
重建索引可以刪除額外的數(shù)據(jù)塊;
提高索引查詢效率;
alter index idx_name rebuild nologging;
對于分區(qū)索引:
alter index idx_name rebuild partition partiton_name nologging;
要刪除索引的原因
。不再需要的索引;
。索引沒有針對其相關(guān)的表所發(fā)布的查詢提供所期望的性能改善;
。應(yīng)用沒有用該索引來查詢數(shù)據(jù);
。該索引無效,必須在重建之前刪除該索引;
。該索引已經(jīng)變的太碎了,必須在重建之前刪除該索引;
。語句:drop index idx_name;drop index idx_name drop partition partition_name;
建立索引的代價
基礎(chǔ)表維護時,系統(tǒng)要同時維護索引,不合理的索引將嚴重影響系統(tǒng)資源,主要表現(xiàn)在CPU和I/O上;
插入、更新、刪除數(shù)據(jù)產(chǎn)生大量db file sequential read鎖等待;
SQL優(yōu)化器簡介
基于規(guī)則的優(yōu)化器
。總是使用索引
。總是從驅(qū)動表開始(from子句最右邊的表)
。只有在不可避免的情況下,才使用全表掃描
。任何索引都可以
基于成本的優(yōu)化器
。需要表、索引的統(tǒng)計資料
Analyze table customer compute statistics;
Analyze table customer estimate statistics sample 5000 rows;
。表中設(shè)置并行度、表分區(qū)
優(yōu)化器模式
rule模式
。總忽略CBO和統(tǒng)計信息而基于規(guī)則
choose模式
。Oracle根據(jù)情況選擇rule or first_rows or all_rows
first_rows 模式
。基于成本,以最快的速度返回記錄,會造成總體查詢速度的下降或消耗更多的資源,傾向索引掃描,適合OLTP系統(tǒng)
all_rows模式
。基于成本,確保總體查詢時間最短,傾向并行全表掃描
例如:
Select last_name from customer order by last_name;用first_rows時,迅速返回記錄,但I/O量大,用all_rows時,返回記錄慢,但使用資源少。
調(diào)整SQL表訪問
全表掃描
。返回記錄:未排序表>40%,排序表>7%,建議采用并行機制來提高訪問速度,DDS;
索引訪問
。最常用的方法,包括索引唯一掃描和索引范圍掃描,OLTP;
快速完全索引掃描
。訪問索引中所有數(shù)據(jù)塊,結(jié)果相當于全表掃描,可以用索引掃描代替全表掃描,例如:
Select serv_id,count(* ) from tg_cdr01 group by serv_id;
評估全表掃描的合法性
如何實現(xiàn)并行掃描
。永久并行化(不推薦)
alter table customer parallel degree 8;
。單個查詢并行化
select /*+ full(emp) parallel(emp,8)*/ * from emp;
分區(qū)表效果明顯
優(yōu)化SQL語句排序
排序的操作:
。order by 子句
。group by 子句
。select distinct子句
。創(chuàng)建索引時
。union或minus
。排序合并連接
如何避免排序
。添加索引
。在索引中使用distinct子句
。避免排序合并連接
使用提示進行調(diào)整
使用提示的原則
。語法:/*+ 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內(nèi)置函數(shù))
。index_combine(強制使用位圖索引)
。index_ffs(索引快速完全掃描)
。use_concat(將查詢中所有or條件使用union all)
。parallel
。noparallel
。full
。ordered(基于成本)
調(diào)整表連接
表連接的類型
。等連接
where 條件中用等式連接;
。外部連接(左、右連接)
在where條件子句的等式謂詞放置一個(+)來實現(xiàn),例如:
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中,是指在查詢中找到的任何記錄都不包含在結(jié)果集中的子查詢;不建議使用not in or not exists;
。半連接
查詢中使用exists,含義:即使在子查詢中返回多條重復(fù)的記錄,外部查詢也只返回一條記錄。
嵌套循環(huán)連接
。被連接表中存在索引的情況下使用;
。使用use_nl。
hash連接
。Hash連接將驅(qū)動表加載在內(nèi)存中,并使用hash技術(shù)連接第二個表,提高等連接速度。
。適合于大表和小表連接;
。使用use_hash。
排序合并連接
。排序合并連接不使用索引
。使用原則:
連接表子段中不存在可用索引;
查詢返回兩個表中大部分的數(shù)據(jù)快;
CBO認為全表掃描比索引掃描執(zhí)行的更快。
。使用use_merge
使用臨時/中間表
多個大表關(guān)聯(lián)時,可以分別把滿足條件的結(jié)果集存放到中間表,然后用中間表關(guān)聯(lián);
SQL子查詢的調(diào)整
關(guān)聯(lián)與非關(guān)聯(lián)子查詢
。關(guān)聯(lián):子查詢的內(nèi)部引用的是外部表,每行執(zhí)行一次;
。非關(guān)聯(lián):子查詢只執(zhí)行一次,存放在內(nèi)存中。
調(diào)整not in 和not exists語句
。可以使用外部連接優(yōu)化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;
使用索引調(diào)整SQL
Oracle 為什么不使用索引
。檢查被索引的列或組合索引的首列是否出現(xiàn)在PL/SQL語句的WHERE子句中,這是“執(zhí)行計劃”能用到相關(guān)索引的必要條件。
。看采用了哪種類型的連接方式。ORACLE的共有Sort Merge Join(SMJ)、Hash Join(HJ)和Nested Loop Join(NL)。在兩張表連接,且內(nèi)表的目標列上建有索引時,只有Nested Loop才能有效地利用到該索引。SMJ即使相關(guān)列上建有索引,最多只能因索引的存在,避免數(shù)據(jù)排序過程。HJ由于須做HASH運算,索引的存在對數(shù)據(jù)查詢速度幾乎沒有影響。
。看連接順序是否允許使用相關(guān)索引。假設(shè)表emp的deptno列上有索引,表dept的列deptno上無索引,WHERE語句有emp.deptno=dept.deptno條件。在做NL連接時,emp做為外表,先被訪問,由于連接機制原因,外表的數(shù)據(jù)訪問方式是全表掃描,emp.deptno上的索引顯然是用不上,最多在其上做索引全掃描或索引快速全掃描。
。是否用到系統(tǒng)數(shù)據(jù)字典表或視圖。由于系統(tǒng)數(shù)據(jù)字典表都未被分析過,可能導(dǎo)致極差的“執(zhí)行計劃”。但是不要擅自對數(shù)據(jù)字典表做分析,否則可能導(dǎo)致死鎖,或系統(tǒng)性能下降。
。索引列是否函數(shù)的參數(shù)。如是,索引在查詢時用不上。
。是否存在潛在的數(shù)據(jù)類型轉(zhuǎn)換。如將字符型數(shù)據(jù)與數(shù)值型數(shù)據(jù)比較,ORACLE會自動將字符型用to_number()函數(shù)進行轉(zhuǎn)換,從而導(dǎo)致上一種現(xiàn)象的發(fā)生。
。是否為表和相關(guān)的索引搜集足夠的統(tǒng)計數(shù)據(jù)。對數(shù)據(jù)經(jīng)常有增、刪、改的表最好定期對表和索引進行分析,可用SQL語句“analyze table xxxx compute statistics for all indexes;”。ORACLE掌握了充分反映實際的統(tǒng)計數(shù)據(jù),才有可能做出正確的選擇。
。索引列的選擇性不高。 我們假設(shè)典型情況,有表emp,共有一百萬行數(shù)據(jù),但其中的emp.deptno列,數(shù)據(jù)只有4種不同的值,如10、20、30、40。雖然emp數(shù)據(jù)行有很多,ORACLE缺省認定表中列的值是在所有數(shù)據(jù)行均勻分布的,也就是說每種deptno值各有25萬數(shù)據(jù)行與之對應(yīng)。假設(shè)SQL搜索條件DEPTNO=10,利用deptno列上的索引進行數(shù)據(jù)搜索效率,往往不比全表掃描的高。
。索引列值是否可為空(NULL)。如果索引列值可以是空值,在SQL語句中那些要返回NULL值的操作,將不會用到索引,如COUNT(*),而是用全表掃描。這是因為索引中存儲值不能為全空。
。看是否有用到并行查詢(PQO)。并行查詢將不會用到索引。
。如果從以上幾個方面都查不出原因的話,我們只好用采用在語句中加hint的方式強制ORACLE使用最優(yōu)的“執(zhí)行計劃”。 hint采用注釋的方式,有行注釋和段注釋兩種方式。 如我們想要用到A表的IND_COL1索引的話,可采用以下方式: “SELECT /*+ INDEX(A IND_COL1)*/ * FROM A WHERE COL1 = XXX;"
如何屏蔽索引
語句的執(zhí)行計劃中有不良索引時,可以人為地屏蔽該索引,方法:
。數(shù)值型:在索引字段上加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 閱讀(654) |
評論 (1) |
編輯 收藏
轉(zhuǎn)自:http://tb.blog.csdn.net/TrackBack.aspx?PostId=1729625
1、各種索引的創(chuàng)建方法
(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)函數(shù)索引
create index indexname on tablename(functionname(columnname));
創(chuàng)建索引后要分析才能使用
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在于統(tǒng)計相關(guān)的信息..
查詢索引
select index_name,index_type from user_indexes where table_name='TEST';
2、打開autotrace功能
執(zhí)行$ORACLE_HOME/rdbms/admin/utlxplan.sql和$ORACLE_HOME/sqlplus/admin/plustrce.sql
然后給相關(guān)用戶授予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)條件包含函數(shù)但沒有創(chuàng)建函數(shù)索引
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'
由于沒有創(chuàng)建函數(shù)索引,所以選擇全表掃描
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'
雖然創(chuàng)建了函數(shù)索引,但由于工作于RBO模式,所以函數(shù)索引沒用,選擇了全表掃描
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)
當函數(shù)索引工作于CBO模式下,選擇了基于函數(shù)的索引,上面創(chuàng)建的索引函數(shù)TEST_INDEX_FUN已經(jīng)用到
(3)符合索引中的前導(dǎo)列沒有被作為查詢條件
create index test_index_com on test(a,b);
select /*+ RULE */ * from test where a = '1';
A B
-- ----------
1 1
前導(dǎo)列a作為了查詢條件,但由于之前創(chuàng)建了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'
前導(dǎo)列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)
前導(dǎo)列a作為了查詢條件,使用了索引
(4)CBO模式下選擇的行數(shù)比例過大,優(yōu)化器選擇全表掃描
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優(yōu)化器,肯定就用索引了
(5)在CBO模式下表很久沒分析,表的增長明顯,優(yōu)化器采取了全表掃描
(6)索引條件中使用了<>、!=、not\not in、not like等操作符,導(dǎo)致查詢不使用索引
先做一個測試在一個表中插入130萬條數(shù)據(jù),其中不等于1的數(shù)據(jù)有30萬條,以下是幾種語句執(zhí)行的結(jié)果
序號 語句 時間 代價
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
從以上可以看出最優(yōu)化的語句是7,在查詢過程中使用索引的有5、6、7
所以,如果建立了索引,在語句中盡量不要使用<>、!=、not、not in、not like操作,如果非要使用,請盡量用or和union操作替換
(7)索引對空值的影響
我們首先做一些測試數(shù)據(jù):
SQL> create table t(x int, y int);
請注意,這里我對表t做了一個唯一(聯(lián)合)索引:
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行數(shù)據(jù)。
請注意,上面我們插入并提交了四行數(shù)據(jù)。
所以,這里就有一個結(jié)論:
Oracle的索引不保存該索引包含的列中全部為空的行。
這同時也帶來個好處,但當一個表中的某一列大部分為空值,至少90%以上是空值的時候,就可以為該列建立索引。
比如該表為t,該列為x
select * from t where x is null;
此時會選擇全表掃描
select * from t where x=1;
此時就會使用索引,而且索引中不保存值為空的行,所以索引中只有10%左右的行,因此在這10%的行中找出x=1的行比在全表中找出x=1的行要快的多
我們繼續(xù)插入數(shù)據(jù),現(xiàn)在再插入幾行全部為空的行:
SQL> insert into t values(NULL,NULL);
SQL> insert into t values(NULL,NULL);
我們看到這樣的插入,居然沒有違反前面我們設(shè)定的唯一約束(unique on t(x,y)),
所以,這里我們又得出一個結(jié)論:
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>
可以看見,完全為空的行有三行,這里我們又可以得出一個結(jié)論:
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不使用索引
那么我們?nèi)绾问褂每罩档谋容^條件呢?
首先,盡量不在前導(dǎo)列上使用空值,其次我們在創(chuàng)建表的時候,為每個列都指定為非空約束(NOT NULL),并且在必要的列上使用default值
8、不要為所有的列建立索引
我們知道,建立索引是為了提高查詢的效率,但是同時也應(yīng)該注意到,索引增加了對DML操作(insert, update, delete)的代價,而且,一給中的索引如果太多,那么多數(shù)的索引是根本不會被使用到的,而另一方面我們維護這些不被使用的所以還要大幅度降低系統(tǒng)的性能。所以,索引不是越多越好,而是要恰到好處的使用。
比如說,有些列由于使用了函數(shù),我們要使用已有的索引(如一些復(fù)合索引)是不可能的,那么就必須建立單獨的函數(shù)索引,如果說這個函數(shù)索引很少會被應(yīng)用(僅僅在幾個特別的sql中會用到),我們就可以嘗試改寫查詢,而不去建立和維護那個函數(shù)索引,例如:
1,trunc函數(shù)
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'
將上面的查詢轉(zhuǎn)換為:
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函數(shù)
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函數(shù)
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的效率,我們要仔細的分析應(yīng)用,找出來出現(xiàn)頻率相對較多、字段內(nèi)容較少(比如varchar2(1000)就不適合建立索引,而varchar2(10)相對來說就適合建立索引)的列,合理的建立索引,比如有時候我們希望建立復(fù)合索引,有時候我們更希望建立單鍵索引。
posted @
2007-11-21 10:20 xzc 閱讀(457) |
評論 (0) |
編輯 收藏
轉(zhuǎn)自:http://www.tkk7.com/hadeslee/archive/2007/11/20/161770.html
2. <body onselectstart="return false"> 取消選取、防止復(fù)制
3. onpaste="return false" 不準粘貼
4. oncopy="return false;" oncut="return false;" 防止復(fù)制
5. <link rel="Shortcut Icon" href="favicon.ico"> IE地址欄前換成自己的圖標
6. <link rel="Bookmark" href="favicon.ico"> 可以在收藏夾中顯示出你的圖標
7. <input style="ime-mode:disabled"> 關(guān)閉輸入法
8. 永遠都會帶著框架
<script language="JavaScript"><!--
if (window == top)top.location.href = "frames.htm"; //frames.htm為框架網(wǎng)頁
// --></script>
9. 防止被人frame
<SCRIPT LANGUAGE=JAVASCRIPT><!--
if (top.location != self.location)top.location=self.location;
// --></SCRIPT>
10. 網(wǎng)頁將不能被另存為
<noscript><iframe src="/*.html>";</iframe></noscript>
11. <input type=button value=查看網(wǎng)頁源代碼
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. 最小化、最大化、關(guān)閉窗口
<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=關(guān)閉 onclick=hh3.Click()>
本例適用于IE
17.屏蔽功能鍵Shift,Alt,Ctrl
<script>
function look(){
if(event.shiftKey)
alert("禁止按Shift鍵!"); //可以換成ALT CTRL
}
document.onkeydown=look;
</script>
18. 網(wǎng)頁不會被緩存
<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>的區(qū)別?
<div>(division)用來定義大段的頁面元素,會產(chǎn)生轉(zhuǎn)行
<span>用來定義同一行內(nèi)的元素,跟<div>的唯一區(qū)別是不產(chǎn)生轉(zhuǎn)行
<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.如何設(shè)定打開頁面的大小
<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. 檢查一段字符串是否全由數(shù)字組成
<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自適應(yīng)文字行數(shù)的多少
<textarea rows=1 name=s1 cols=27 onpropertychange="this.style.posHeight=this.scrollHeight">
</textarea>
32. 日期減去天數(shù)等于第二個日期
<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. 檢測某個網(wǎng)站的鏈接速度:
把如下代碼加入<body>區(qū)域中:
<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)">
這個是頁面被載入和調(diào)出時的一些特效。duration表示特效的持續(xù)時間,以秒為單位。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.在規(guī)定時間內(nèi)跳轉(zhuǎn)
<META http-equiv=V="REFRESH" content="5;URL=http://www.51js.com">
40.網(wǎng)頁是否被檢索
<meta name="ROBOTS" content="屬性值">
其中屬性值有以下一些:
屬性值為"all": 文件將被檢索,且頁上鏈接可被查詢;
屬性值為"none": 文件不被檢索,而且不查詢頁上的鏈接;
屬性值為"index": 文件將被檢索;
屬性值為"follow": 查詢頁上的鏈接;
屬性值為"noindex": 文件不檢索,但可被查詢鏈接;
屬性值為"nofollow": 文件不被檢索,但可查詢頁上的鏈接。
41、email地址的分割
把如下代碼加入<body>區(qū)域中
<a href="webmaster@sina.commailto:webmaster@sina.com">webmaster@sina.com</a>
42、流動邊框效果的表格
把如下代碼加入<body>區(qū)域中
<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>
==============
一、在下面的代碼中,你只要單擊打開一個窗口,即可鏈接到賽迪網(wǎng)。而當你想關(guān)閉時,只要單擊一下即可關(guān)閉剛才打開的窗口。
代碼如下:
<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="關(guān)閉這個窗口" 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)">
三、討厭很多網(wǎng)站總是按照默認窗口打開,如果你能隨心所欲控制打開的窗口那該多好。
代碼如下:
<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>
打開頁面的參數(shù)<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>你只要在相對應(yīng)的對話框中輸入一個數(shù)值即可,將要打開的頁面的窗口控制得很好。
44、頁面的打開移動
把如下代碼加入<body>區(qū)域中
<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("現(xiàn) 在 時 間 是: ",today.getHours(),":",today.getMinutes())
document.write("<br>今 天 日 期 為: ", today.getMonth()+1,"/",today.getDate(),"/",today.getYear());
// end hiding contents -->
</script>
46、自動的為你每次產(chǎn)生最後修改的日期了:
<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;">
這里可顯示您的網(wǎng)頁 !
</body>
</html>
49、在網(wǎng)頁中用按鈕來控制前頁,后頁和主頁的顯示。
<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、查看某網(wǎng)址的源代碼
把如下代碼加入<body>區(qū)域中
<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>區(qū)域中:
<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>區(qū)域中
<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>區(qū)域中
<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>區(qū)域中
<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、改變表格的內(nèi)容
把如下代碼加入<body>區(qū)域中
<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 閱讀(329) |
評論 (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 閱讀(2201) |
評論 (0) |
編輯 收藏
JSP動作利用XML語法格式的標記來控制Servlet引擎的行為。利用JSP動作可以動態(tài)地插入文件、重用JavaBean組件、把用戶重定向到另外的頁面、為Java插件生成HTML代碼。
JSP動作包括:
jsp:include:在頁面被請求的時候引入一個文件。
jsp:useBean:尋找或者實例化一個JavaBean。
jsp:setProperty:設(shè)置JavaBean的屬性。
jsp:getProperty:輸出某個JavaBean的屬性。
jsp:forward:把請求轉(zhuǎn)到一個新的頁面。
jsp:plugin:根據(jù)瀏覽器類型為Java插件生成OBJECT或EMBED標記。
13.1 jsp:include動作
該動作把指定文件插入正在生成的頁面。其語法如下:
<jsp:include page="relative URL" flush="true" />
前面已經(jīng)介紹過include指令,它是在JSP文件被轉(zhuǎn)換成Servlet的時候引入文件,而這里的jsp:include動作不同,插入文件的時間是在頁面被請求的時候。jsp:include動作的文件引入時間決定了它的效率要稍微差一點,而且被引用文件不能包含某些JSP代碼(例如不能設(shè)置HTTP頭),但它的靈活性卻要好得多。
例如,下面的JSP頁面把4則新聞?wù)迦胍粋€“What s New ?”頁面。改變新聞?wù)獣r只需改變這四個文件,而主JSP頁面卻可以不作修改:
WhatsNew.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>W(wǎng)hat 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。這個功能非常有用,因為它使得我們既可以發(fā)揮Java組件重用的優(yōu)勢,同時也避免了損失JSP區(qū)別于Servlet的方便性。jsp:useBean動作最簡單的語法為:
<jsp:useBean id="name" class="package.class" />
這行代碼的含義是:“創(chuàng)建一個由class屬性指定的類的實例,然后把它綁定到其名字由id屬性給出的變量上”。不過,就象我們接下來會看到的,定義一個scope屬性可以讓Bean關(guān)聯(lián)到更多的頁面。此時,jsp:useBean動作只有在不存在同樣id和scope的Bean時才創(chuàng)建新的對象實例,同時,獲得現(xiàn)有Bean的引用就變得很有必要。
獲得Bean實例之后,要修改Bean的屬性既可以通過jsp:setProperty動作進行,也可以在Scriptlet中利用id屬性所命名的對象變量,通過調(diào)用該對象的方法顯式地修改其屬性。這使我們想起,當我們說“某個Bean有一個類型為X的屬性foo”時,就意味著“這個類有一個返回值類型為X的getFoo方法,還有一個setFoo方法以X類型的值為參數(shù)”。
有關(guān)jsp:setProperty動作的詳細情況在后面討論。但現(xiàn)在必須了解的是,我們既可以通過jsp:setProperty動作的value屬性直接提供一個值,也可以通過param屬性聲明Bean的屬性值來自指定的請求參數(shù),還可以列出Bean屬性表明它的值
1Y0-327 應(yīng)該來自請求參數(shù)中的同名變量。
在JSP表達式或Scriptlet中讀取Bean屬性通過調(diào)用相應(yīng)的getXXX方法實現(xiàn),或者更一般地,使用jsp:getProperty動作。
注意包含Bean的類文件應(yīng)該放到服務(wù)器正式存放Java類的目錄下,而不是保留給修改后能夠自動裝載的類的目錄。例如,對于Java Web Server來說,Bean和所有Bean用到的類都應(yīng)該放入classes目錄,或者封裝進jar文件后放入lib目錄,但不應(yīng)該放到servlets下。
下面是一個很簡單的例子,它的功能是裝載一個Bean,然后設(shè)置/讀取它的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 關(guān)于jsp:useBean的進一步說明
使用Bean最簡單的方法是先用下面的代碼裝載Bean:
<jsp:useBean id="name" class="package.class" />
然后通過jsp:setProperty和jsp:getProperty修改和提取Bean的屬性。不過有兩點必須注意。第一,我們還可以用下面這種格式實例化Bean:
<jsp:useBean ...>
Body
</jsp:useBean>
它的意思是,只有當?shù)谝淮螌嵗疊ean時才執(zhí)行Body部分,如果是利用現(xiàn)有的Bean實例則不執(zhí)行Body部分。正如
jn0-140 下面將要介紹的,jsp:useBean并非總是意味著創(chuàng)建一個新的Bean實例。
第二,除了id和class外,jsp:useBean還有其他三個屬性,即:scope,type,beanName。下表簡要說明這些屬性的用法。 屬性 用法
id 命名引用該Bean的變量。如果能夠找到id和scope相同的Bean實例,jsp:useBean動作將使用已有的Bean實例而不是創(chuàng)建新的實例。
class 指定Bean的完整包名。
scope 指定Bean在哪種上下文內(nèi)可用,可以取下面的四個值之一:page,request,session和application。
默認值是page,表示該Bean只在當前頁面內(nèi)可用(保存在當前頁面的PageContext內(nèi))。
request表示該Bean在當前的客戶請求內(nèi)有效(保存在ServletRequest對象內(nèi))。
session表示該Bean對當前HttpSession內(nèi)的所有頁面都有效。
最后,如果取值application,則表示該Bean對所有具有相同ServletContext的頁面都有效。
scope之所以很重要,是因為jsp:useBean只有在不存在具有相同id和scope的對象時才會實例化新的對象;如果已有id和scope都相同的對象則直接使用已有的對象,此時jsp:useBean開始標記和結(jié)束標記之間的任何內(nèi)容都將被忽略。
type 指定引用該對象的變量的類型,它必須是Bean類的名字、超類名字、該類所實現(xiàn)的接口名字之一。請記住變量的名字是由id屬性指定的。
beanName 指定Bean的名字。如果提供了type屬性和beanName屬性,允許省略class屬性。
13.4 jsp:setProperty動作
jsp:setProperty用來設(shè)置已經(jīng)實例化的Bean對象的屬性,有兩種用法。首先,你可以在jsp:useBean元素的外面(后面)使用jsp:setProperty,如下所示:
<jsp:useBean id="myName" ... />
...
<jsp:setProperty name="myName"
property="someProperty" ... />
此時,不管jsp:useBean是找到了一個現(xiàn)有的Bean,還是新創(chuàng)建了一個Bean實例,jsp:setProperty都會執(zhí)行。第二種用法是把jsp:setProperty放入jsp:useBean元素的內(nèi)部,如下所示:
<jsp:useBean id="myName" ... >
...
<jsp:setProperty name="myName"
property="someProperty" ... />
</jsp:useBean>
此時,jsp:setProperty只有在新建Bean實例時才會執(zhí)行,如果是使用現(xiàn)有實例則不執(zhí)行jsp:setProperty。
jsp:setProperty動作有下面四個屬性: 屬性 說明
name name屬性是必需的。它表示要設(shè)置屬性的是哪個Bean。
property property屬性是必需的。它表示要設(shè)置哪個屬性。有一個特殊用法:如果property的值是“*”,表示所有名字和Bean屬性名字匹配的請求參數(shù)都將被傳遞給相應(yīng)的屬性set方法。
value value屬性是可選的。該屬性用來指定Bean屬性的值。字符串數(shù)據(jù)會在目標類中通過標準的valueOf方法自動轉(zhuǎn)換成數(shù)字、boolean、Boolean、byte、Byte、char、Character。例如,boolean和Boolean類型的屬性值(比如“true”)通過Boolean.valueOf轉(zhuǎn)換,int和Integer類型的屬性值(比如“42”)通過Integer.valueOf轉(zhuǎn)換。
value和param不能同時使用,但可以使用其中任意一個。
param param是可選的。它指定用哪個請求參數(shù)作為Bean屬性的值。如果當前請求沒有參數(shù),則什么事情也不做,系統(tǒng)不會把null傳遞給Bean屬性的set方法。因此,你可以讓Bean自己提供默認屬性值,只有當請求參數(shù)明確指定了新值時才修改默認屬性值。
例如,下面的代碼片斷表示:如果存在numItems請求參數(shù)的話,把numberOfItems屬性的值設(shè)置為請求參數(shù)numItems的值;否則什么也不做。
<jsp:setProperty name="orderBean"
property="numberOfItems"
param="numItems" />
如果同時省略value和param,其效果相當于提供一個param且其值等于property的值。進一步利用這種借助請求參數(shù)和屬性名字相同進行自動賦值的思想,你還可以在property(Bean屬性的名字)中指定“*”,然后省略value和param。此時,服務(wù)器會查看所有的Bean屬性和請求參數(shù),如果兩者名字相同則自動賦值。
下面是一個利用JavaBean計算素數(shù)的例子。如果請求中有一個numDigits參數(shù),則該值被傳遞給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屬性的值,轉(zhuǎn)換成字符串,然后輸出。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動作把請求轉(zhuǎn)到另外的頁面。jsp:forward標記只有一個屬性page。page屬性包含的是一個相對URL。page的值既可以直接給出,也可以在請求的時候動態(tài)計算,如下面的例子所示:
<jsp:forward page="/utils/errorReporter.jsp" />
<jsp:forward page="<%= someJavaExpression %>" />
13.7 jsp:plugin動作
jsp:plugin動作用來根據(jù)瀏覽器的類型,插入通過Java插件 運行Java Applet所必需的OBJECT或EMBED元素。
附錄:JSP注釋和字符引用約定
下面是一些特殊的標記或字符,你可以利用它們插入注釋或可能被視為具有特殊含義的字符。 語法 用途
<%-- comment --%> JSP注釋,也稱為“隱藏注釋”。JSP引擎將忽略它。標記內(nèi)的所有JSP腳本元素、指令和動作都將不起作用。
<!-- comment --> HTML注釋,也稱為“輸出的注釋”,直接出現(xiàn)在結(jié)果HTML文檔中。標記內(nèi)的所有JSP腳本元素、指令和動作正常執(zhí)行。
<\% 在模板文本(靜態(tài)HTML)中實際上希望出現(xiàn)“<%”的地方使用。
%\> 在腳本元素內(nèi)實際上希望出現(xiàn)“%>”的地方使用。
\ 使用單引號的屬性內(nèi)的單引號。不過,你既可以使用單引號也可以使用雙引號,而另外一種引號將具有普通含義。
\" 使用雙引號的屬性內(nèi)的雙引號。參見“\ ”的說明。
posted @
2007-10-19 12:57 xzc 閱讀(346) |
評論 (0) |
編輯 收藏
網(wǎng)絡(luò)收集:PLSQL常用方法匯總
在SQLPLUS下,實現(xiàn)中-英字符集轉(zhuǎn)換
alter session set nls_language='AMERICAN';
alter session set nls_language='SIMPLIFIED CHINESE';
主要知識點:
一、有關(guān)表的操作
1)建表
create table test as select * from dept; --從已知表復(fù)制數(shù)據(jù)和結(jié)構(gòu)
create table test as select * from dept where 1=2; --從已知表復(fù)制結(jié)構(gòu)但不包括數(shù)據(jù)
2)插入數(shù)據(jù):
insert into test select * from dept;
二、運算符
算術(shù)運算符:+ - * / 可以在select 語句中使用
連接運算符:|| select deptno|| dname from dept;
比較運算符:> >= = != < <= like between is null in
邏輯運算符:not and or
集合運算符: intersect(交),union(并 不重復(fù)), union all(并 重復(fù)), minus(差)
要求:對應(yīng)集合的列數(shù)和數(shù)據(jù)類型相同
查詢中不能包含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); --不包括重復(fù)行
select * from emp where deptno=10 union all select * from emp where deptno in (10,20); --包括重復(fù)行三,常用 ORACLE 函數(shù)
sysdate為系統(tǒng)日期 dual為虛表
一)日期函數(shù)[重點掌握前四個日期函數(shù)]
-----------------------------------------
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[返回日期之間的月份數(shù)]
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
二)字符函數(shù)(可用于字面字符或數(shù)據(jù)庫列)
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)去掉前導(dǎo)和后綴
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值對應(yīng)的字母
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[實現(xiàn)if ..then 邏輯]
select deptno,decode(deptno,10,'1',20,'2',30,'3','其他') from dept;
三)數(shù)字函數(shù)
1,取整函數(shù)(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,返回固定小數(shù)位數(shù) (round:四舍五入,trunc:直接截斷)
select round(66.667,2) N1,trunc(66.667,2) N2 from dual;
5,返回值的符號(正數(shù)返回為1,負數(shù)為-1)
select sign(-32),sign(293) from dual;
四)轉(zhuǎn)換函數(shù)
1,to_char()[將日期和數(shù)字類型轉(zhuǎn)換成字符類型]
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()[將字符類型轉(zhuǎn)換為日期類型]
insert into emp(empno,hiredate) values(8000,to_date('2004-10-10','yyyy-mm-dd'));
3, to_number() 轉(zhuǎn)換為數(shù)字類型
select to_number(to_char(sysdate,'hh12')) from dual; //以數(shù)字顯示的小時數(shù)
五)其他函數(shù)
user:
返回登錄的用戶名稱
select user from dual;
vsize:
返回表達式所需的字節(jié)數(shù)
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;
六)分組函數(shù)
max min avg count sum
1,整個結(jié)果集是一個組
1) 求部門30 的最高工資,最低工資,平均工資,總?cè)藬?shù),有工作的人數(shù),工種數(shù)量及工資總和
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)按部門分組求最高工資,最低工資,總?cè)藬?shù),有工作的人數(shù),工種數(shù)量及工資總和
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的最高工資,最低工資,總?cè)藬?shù),有工作的人數(shù),工種數(shù)量及工資總和
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 按分組的第一個列進行統(tǒng)計和最后的小計
cube 按分組的所有列的進行統(tǒng)計和最后的小計
select deptno,job ,sum(sal) from emp group by deptno,job;
select deptno,job ,sum(sal) from emp group by rollup(deptno,job);
cube 產(chǎn)生組內(nèi)所有列的統(tǒng)計和最后的小計
select deptno,job ,sum(sal) from emp group by cube(deptno,job);七、臨時表
只在會話期間或在事務(wù)處理期間存在的表.
臨時表在插入數(shù)據(jù)時,動態(tài)分配空間
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; --無數(shù)據(jù)顯示,數(shù)據(jù)自動清除
on commit preserve rows:在會話期間表一直可以存在(保留數(shù)據(jù))
on commit delete rows:事務(wù)結(jié)束清除數(shù)據(jù)(在事務(wù)結(jié)束時自動刪除表的數(shù)據(jù))
Oracle時間日期操作
sysdate+(5/24/60/60) 在系統(tǒng)時間基礎(chǔ)上延遲5秒
sysdate+5/24/60 在系統(tǒng)時間基礎(chǔ)上延遲5分鐘
sysdate+5/24 在系統(tǒng)時間基礎(chǔ)上延遲5小時
sysdate+5 在系統(tǒng)時間基礎(chǔ)上延遲5天
add_months(sysdate,-5) 在系統(tǒng)時間基礎(chǔ)上延遲5月
add_months(sysdate,-5*12) 在系統(tǒng)時間基礎(chǔ)上延遲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
年初至今的天數(shù):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
本月的天數(shù)
SELECT to_char(last_day(SYSDATE),'dd') days FROM dual
今年的天數(shù)
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 中的一些處理日期
將數(shù)字轉(zhuǎn)換為任意時間格式.如秒:需要轉(zhuǎn)換為天/小時
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.
日期和字符轉(zhuǎn)換函數(shù)用法(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
設(shè)置日期語言
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
也可以這樣
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')
4.
兩個日期間的天數(shù)
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點之前是不包含在這個范圍之內(nèi)的。
所以,當時間需要精確的時候,覺得to_char還是必要的
7. 日期格式?jīng)_突問題
輸入的格式要看你安裝的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間除星期一和七的天數(shù)
在前后分別調(diào)用DBMS_UTILITY.GET_TIME, 讓后將結(jié)果相減(得到的是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 與最后一行是一樣的
可以建立一個函數(shù)來處理這個問題
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.
獲得小時數(shù)
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.
處理月份天數(shù)不定的辦法
select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual
16.
找出今年的天數(shù)
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的區(qū)別
'YYYY99 TO_C
------- ----
yyyy 99 0099
rrrr 99 1999
yyyy 01 0001
rrrr 01 2001
18.不同時區(qū)的處理
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位秒數(shù)
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函數(shù)
next_day(sysdate,6)是從當前開始下一個星期五。后面的數(shù)字是從星期日開始算起。
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
日期 返回的是天 然后 轉(zhuǎn)換為ss
轉(zhuǎn)此:http://www.onlinedatabase.cn/leadbbs/Announce/Announce.asp?BoardID=42&ID=1769
將數(shù)字轉(zhuǎn)換為任意時間格式.如秒:需要轉(zhuǎn)換為天/小時
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.
日期和字符轉(zhuǎn)換函數(shù)用法(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
設(shè)置日期語言
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
也可以這樣
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')
4.
兩個日期間的天數(shù)
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點之前是不包含在這個范圍之內(nèi)的。
所以,當時間需要精確的時候,覺得to_char還是必要的
7. 日期格式?jīng)_突問題
輸入的格式要看你安裝的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間除星期一和七的天數(shù)
在前后分別調(diào)用DBMS_UTILITY.GET_TIME, 讓后將結(jié)果相減(得到的是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 與最后一行是一樣的
可以建立一個函數(shù)來處理這個問題
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.
獲得小時數(shù)
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.
處理月份天數(shù)不定的辦法
select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual
16.
找出今年的天數(shù)
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的區(qū)別
'YYYY99 TO_C
------- ----
yyyy 99 0099
rrrr 99 1999
yyyy 01 0001
rrrr 01 2001
18.不同時區(qū)的處理
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位秒數(shù)
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函數(shù)
next_day(sysdate,6)是從當前開始下一個星期五。后面的數(shù)字是從星期日開始算起。
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
日期 返回的是天 然后 轉(zhuǎn)換為ss
轉(zhuǎn)此:http://www.onlinedatabase.cn/leadbbs/Announce/Announce.asp?BoardID=42&ID=1769
將數(shù)字轉(zhuǎn)換為任意時間格式.如秒:需要轉(zhuǎn)換為天/小時
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.
日期和字符轉(zhuǎn)換函數(shù)用法(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
設(shè)置日期語言
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
也可以這樣
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')
4.
兩個日期間的天數(shù)
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點之前是不包含在這個范圍之內(nèi)的。
所以,當時間需要精確的時候,覺得to_char還是必要的
7. 日期格式?jīng)_突問題
輸入的格式要看你安裝的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間除星期一和七的天數(shù)
在前后分別調(diào)用DBMS_UTILITY.GET_TIME, 讓后將結(jié)果相減(得到的是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 與最后一行是一樣的
可以建立一個函數(shù)來處理這個問題
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.
獲得小時數(shù)
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.
處理月份天數(shù)不定的辦法
select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual
16.
找出今年的天數(shù)
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的區(qū)別
'YYYY99 TO_C
------- ----
yyyy 99 0099
rrrr 99 1999
yyyy 01 0001
rrrr 01 2001
18.不同時區(qū)的處理
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位秒數(shù)
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函數(shù)
next_day(sysdate,6)是從當前開始下一個星期五。后面的數(shù)字是從星期日開始算起。
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
日期 返回的是天 然后 轉(zhuǎn)換為ss
轉(zhuǎn)此:http://www.onlinedatabase.cn/leadbbs/Announce/Announce.asp?BoardID=42&ID=1769
將數(shù)字轉(zhuǎn)換為任意時間格式.如秒:需要轉(zhuǎn)換為天/小時
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.
日期和字符轉(zhuǎn)換函數(shù)用法(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
設(shè)置日期語言
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
也可以這樣
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')
4.
兩個日期間的天數(shù)
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點之前是不包含在這個范圍之內(nèi)的。
所以,當時間需要精確的時候,覺得to_char還是必要的
7. 日期格式?jīng)_突問題
輸入的格式要看你安裝的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間除星期一和七的天數(shù)
在前后分別調(diào)用DBMS_UTILITY.GET_TIME, 讓后將結(jié)果相減(得到的是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 與最后一行是一樣的
可以建立一個函數(shù)來處理這個問題
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.
獲得小時數(shù)
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.
處理月份天數(shù)不定的辦法
select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual
16.
找出今年的天數(shù)
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的區(qū)別
'YYYY99 TO_C
------- ----
yyyy 99 0099
rrrr 99 1999
yyyy 01 0001
rrrr 01 2001
18.不同時區(qū)的處理
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位秒數(shù)
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函數(shù)
next_day(sysdate,6)是從當前開始下一個星期五。后面的數(shù)字是從星期日開始算起。
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
日期 返回的是天 然后 轉(zhuǎn)換為ss
posted @
2007-10-18 14:03 xzc 閱讀(2166) |
評論 (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);
//獲取指定月份的最大天數(shù)
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 閱讀(586) |
評論 (1) |
編輯 收藏