早起的國(guó)內(nèi)互聯(lián)網(wǎng)都使用GBK編碼,久之,所有項(xiàng)目都以GBK來編碼了。對(duì)于J2EE項(xiàng)目,為了減少編碼的干擾通常都是設(shè)置一個(gè)編碼的Filter,強(qiáng)制將Request/Response編碼改為GBK。例如一個(gè)Spring的常見配置如下:
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
毫無疑問,這在GBK編碼的頁(yè)面訪問、提交數(shù)據(jù)時(shí)是沒有亂碼問題的。但是遇到Ajax就不一樣了。Ajax強(qiáng)制將中文內(nèi)容進(jìn)行UTF-8編碼,這樣導(dǎo)致進(jìn)入后端后使用GBK進(jìn)行解碼時(shí)發(fā)生亂碼。網(wǎng)上的所謂的終極解決方案都是扯淡或者過于復(fù)雜,例如下面的文章:
這樣的文章很多,顯然:
- 使用VB進(jìn)行UTF-8轉(zhuǎn)換成GBK提交是完全不可行(多瀏覽器、多平臺(tái)完全不可用)
- 使用復(fù)雜的js函數(shù)進(jìn)行一次、多次編碼,后端進(jìn)行一次、多次解碼也是不靠譜的,成本太高,無法重復(fù)使用
如果提交數(shù)據(jù)的時(shí)候能夠告訴后端傳輸?shù)木幋a信息是否就可以避免這種問題?比如Ajax請(qǐng)求告訴后端是UTF-8,其它請(qǐng)求告訴后端是GBK,這樣后端分別根據(jù)指定的編碼進(jìn)行解碼是不是就解決問題了。
有兩個(gè)問題:
- 如何通過Ajax告訴后端的編碼?Header過于復(fù)雜,Cookie成本太高,使用參數(shù)最方便。
- 后端何時(shí)進(jìn)行解碼?每一個(gè)請(qǐng)求進(jìn)行解碼,過于繁瑣;獲取參數(shù)時(shí)解碼,此時(shí)已經(jīng)亂碼;在Filter里面動(dòng)態(tài)設(shè)置編碼是最完善的方案。
- 如何從參數(shù)中獲取編碼?如果是POST的body顯然無法獲取,因此在獲取之前所有參數(shù)就已經(jīng)按照某種編碼解碼過了,無法還原。所以通過URL傳遞編碼最有效。支持GET/POST,同時(shí)成本很低。
解決了上述問題,來看具體實(shí)現(xiàn)方案。 列一段Java代碼:
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.util.ClassUtils;
import org.springframework.web.filter.OncePerRequestFilter;
/** 自定義編碼過濾器
* @author imxylz (imxylz#gmail.com)
* @sine 2011-6-9
*/
public class MutilCharacterEncodingFilter extends OncePerRequestFilter {
static final Pattern inputPattern = Pattern.compile(".*_input_encode=([\\w-]+).*");
static final Pattern outputPattern = Pattern.compile(".*_output_encode=([\\w-]+).*");
// Determine whether the Servlet 2.4 HttpServletResponse.setCharacterEncoding(String)
// method is available, for use in the "doFilterInternal" implementation.
private final static boolean responseSetCharacterEncodingAvailable = ClassUtils.hasMethod(HttpServletResponse.class,
"setCharacterEncoding", new Class[] { String.class });
private String encoding;
private boolean forceEncoding = false;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String url = request.getQueryString();
Matcher m = null;
if (url != null && (m = inputPattern.matcher(url)).matches()) {//輸入編碼
String inputEncoding = m.group(1);
request.setCharacterEncoding(inputEncoding);
m = outputPattern.matcher(url);
if (m.matches()) {//輸出編碼
response.setCharacterEncoding(m.group(1));
} else {
if (this.forceEncoding && responseSetCharacterEncodingAvailable) {
response.setCharacterEncoding(this.encoding);
}
}
} else {
if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
request.setCharacterEncoding(this.encoding);
if (this.forceEncoding && responseSetCharacterEncodingAvailable) {
response.setCharacterEncoding(this.encoding);
}
}
}
filterChain.doFilter(request, response);
}
public void setEncoding(String encoding) {
this.encoding = encoding;
}
public void setForceEncoding(boolean forceEncoding) {
this.forceEncoding = forceEncoding;
}
}
解釋下:
- 如果URL的QueryString中包含_input_encode就使用此編碼進(jìn)行設(shè)置Request編碼,以后參數(shù)按照此編碼進(jìn)行解析,例如如果是Ajax就傳入U(xiǎn)TF-8,如果是普通的GBK請(qǐng)求則無視此參數(shù)。
- 如果無視此參數(shù),則按照web.xml中配置的編碼規(guī)則進(jìn)行反編碼,如果是GBK就按照GBK規(guī)則解析。
- 對(duì)于輸出編碼同樣使用上述規(guī)則。需要輸出編碼依賴輸入編碼,也就是說如果有一個(gè)_output_encode的輸出編碼,則同時(shí)需要有一個(gè)_input_encode編碼來指定輸入編碼。當(dāng)然你可以改造成不依賴輸入編碼。
- 完全兼容Spring的org.springframework.web.filter.CharacterEncodingFilter編碼規(guī)則,只需要替換類即可。
- 沒有繼承org.springframework.web.filter.CharacterEncodingFilter類的原因是,org.springframework.web.filter.CharacterEncodingFilter里面的encoding參數(shù)和forceEncoding參數(shù)是private,子類無法使用。在有_input_encode而無_output_encode的時(shí)候想依然保持Spring的Response解析規(guī)則的話無法做到,所以將里面的代碼拷貝過來使用。(為了展示方便,注釋都刪掉了)
- 正則表達(dá)式可以改進(jìn)成只需要匹配一次,從而可以提高一點(diǎn)點(diǎn)效率。
- 所有后端請(qǐng)求將無視編碼的存在,前端Ajax的GET/POST請(qǐng)求也將無視編碼的存在,只是在URL地址中加上一個(gè)_input_encode=UTF-8的參數(shù)。僅此而已。
- 如果想輸出的編碼也是UTF-8,比如手機(jī)端請(qǐng)求、跨站請(qǐng)求等,則需要URL地址參數(shù)_input_encode=UTF-8&_output_encode=UTF-8。
- 對(duì)于POST請(qǐng)求,編碼參數(shù)不能寫在body里面,否則無法解析。
- 顯然,這種終極解決方案,在任何編碼中都可以解決,GBK/UTF-8/ISO8859-1等編碼任何組合都可以實(shí)現(xiàn)。
- 唯一局限性是,此解決方案限制在J2EE項(xiàng)目中,其它平臺(tái)不知是否有類似Filter這樣的組件能夠設(shè)置編碼的概念。
buffalo-2.0(國(guó)人開發(fā)的Ajax框架),下載buffalo-2.0-bin就可以了,個(gè)人認(rèn)為也下載buffalo-2.0-src
下載地址:
http://sourceforge.net/project/showfiles.php?group_id=1788671.buffalo-2.0.jar
在buffalo-2.0-bin里,把它加到Web應(yīng)用程序里的lib
2.buffalo.js和prototype.js
我把這兩個(gè)文件放到Web應(yīng)用程序的scripts/目錄下,buffalo.js在buffalo-2.0-bin里,prototype.js在buffalo-demo.war里找
4.web.xml內(nèi)容
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>bfapp</servlet-name>
<servlet-class>net.buffalo.web.servlet.ApplicationServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>bfapp</servlet-name>
<url-pattern>/bfapp/*</url-pattern>
</servlet-mapping>
</web-app>
5.index.jsp文件
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>第一個(gè) buffalo 示例程序</title>
<script language="JavaScript" src="scripts/prototype.js"></script>
<script language="JavaScript" src="scripts/buffalo.js"></script>
<script type="text/javascript">
var endPoint="<%=request.getContextPath()%>/bfapp";
var buffalo = new Buffalo(endPoint);
function hello(me) {
buffalo.remoteCall("demoService.getHello", [me.value], function(reply) {
alert(reply.getResult());
})
}
</script>
</head>
<body>
輸入你的名字:<input type="text" name="myname">
<input type="button" value="Buffao遠(yuǎn)程調(diào)用" onclick="hello($('myname'));"><br>
</body>
</html>
說明:remoteCall是遠(yuǎn)程調(diào)用方法,demoService是buffalo-service.properties文件的鍵,getHello是被調(diào)用java類方法名,me.value是傳給getHello方法的參數(shù),reply.getResult()是getHello返回的值。
6.DemoService.java文件
package demo.buffalo;
/**
*
* @文件名 demo.buffalo.DemoService.java
* @作者 chenlb
* @創(chuàng)建時(shí)間 2007-7-14 下午12:42:17
*/
public class DemoService {
public String getHello(String name) {
return "Hello , "+name +" 這是第一個(gè)buffalo示例程序";
}
}
7.buffalo-service.properties文件放到WEB-INF/classes/目錄下
demoService=demo.buffalo.DemoService
說明:框架是通過此文件來查找遠(yuǎn)程調(diào)用的類的。
8.現(xiàn)在可以運(yùn)行了。
示例下載
注意:Eclipse項(xiàng)目,文件編碼是UTF-8
官方地址:
Buffalo中文論壇:
http://groups.google.com/group/amowahttp://buffalo.sourceforge.net/tutorial.html
http://confluence.redsaga.com/pages/viewpage.action?pageId=1643
JavaScript API :
http://confluence.redsaga.com/display/BUFFALO/JavaScript+APIhttp://www.amowa.net/buffalo/zh/index.html
轉(zhuǎn)自:http://dingyu.me/blog/posts/view/flowchart-howtos
一個(gè)哥們?cè)贛SN上告訴我,他們公司的交互設(shè)計(jì)師只產(chǎn)出流程圖,并問我用什么標(biāo)準(zhǔn)評(píng)價(jià)流程圖的好壞。他的說法把我徹底震了-這分工也太細(xì)了吧!也不知道該說他們那里這樣是好還是不好。
不過仔細(xì)想來,我倒的確沒有仔細(xì)考慮過流程圖的好壞,正好借此機(jī)會(huì)自我總結(jié)一下。
1、各司其職的形狀
在我的流程圖中,適用于不同目的和功能的形狀都有各自確定的規(guī)范。到目前為止,我一共定義了以下一些形狀:
(1)開始和結(jié)束

作為整張流程圖的頭和尾,必須標(biāo)清楚到底具體指哪個(gè)頁(yè)面,以免日后出現(xiàn)歧義。
(2)網(wǎng)頁(yè)

如你所見,網(wǎng)頁(yè)的形狀是一個(gè)帶有漂亮的淡藍(lán)色過渡效果的長(zhǎng)方形,它的邊框?yàn)樯钏{(lán)色,中間寫明了這個(gè)網(wǎng)頁(yè)的用途,括號(hào)中的數(shù)字代表這個(gè)形狀所對(duì)應(yīng)的demo文件的名稱(比如這里是2.html),我有時(shí)會(huì)把流程圖輸出為網(wǎng)頁(yè)的形式,并把每個(gè)網(wǎng)頁(yè)形狀和它所對(duì)應(yīng)的demo文件鏈接起來,這樣查看起來非常方便。對(duì)OmniGraffle來說這是小菜一碟,如果你被迫用Visio,嗯……
另外,所有從形狀出來的線條,都具有和此形狀邊框一樣的顏色。這樣的做法不僅看起來漂亮,在復(fù)雜的流程圖中還能輕易地標(biāo)明各形狀的關(guān)系。我沒有見過類似的做法,所以這是由我首創(chuàng)也說不定,呵。
(3)后臺(tái)判斷

很常見的一個(gè)形狀。我在用法上有一點(diǎn)和其他人的不同在于,我?guī)缀蹩偸亲?#8216;是’的分支往下流動(dòng),讓‘否’的分支向右流動(dòng)。因?yàn)榱鞒虉D一般都是從上向下、從左到右繪制的,遵循上述規(guī)則一方面可以讓繪制者不用為選擇方向操心,另一方面也方便了讀者閱讀。
(4)表單錯(cuò)誤頁(yè)

既然有表單,當(dāng)然會(huì)有錯(cuò)誤信息。其實(shí)這個(gè)信息很重要,用戶出錯(cuò)時(shí)惶恐不安,就靠著錯(cuò)誤提示來解決問題了。你不在流程圖里說什么時(shí)候顯示錯(cuò)誤頁(yè)、不在demo里提供錯(cuò)誤頁(yè),有些程序員會(huì)直接在網(wǎng)頁(yè)上寫個(gè)“錯(cuò)誤,請(qǐng)檢查”,所以UI設(shè)計(jì)師一定要對(duì)這個(gè)東西重視起來。
但一般來說也沒必要把每種錯(cuò)誤都在流程圖中表示出來,因?yàn)楹袃蓚€(gè)文本框的表單就有三種出錯(cuò)情況了,多了就更不用說了。所以我都是把錯(cuò)誤頁(yè)變?yōu)楸韱蔚母綄夙?yè),比如表單頁(yè)的編號(hào)為2,那么此表單錯(cuò)誤頁(yè)的編號(hào)就從2.1開始排下去,每種錯(cuò)誤放到一個(gè)附屬頁(yè)中,這樣程序員在拿到demo時(shí)也能搞清楚什么意思。
結(jié)合網(wǎng)頁(yè)和表單的形狀,一個(gè)表單驗(yàn)證的流程圖就是這樣的:

(5)后臺(tái)動(dòng)作

并非所有后臺(tái)動(dòng)作都繪入流程圖中(否則流程圖就會(huì)變成龐然大物了),只有需要特別強(qiáng)調(diào)的后臺(tái)動(dòng)作(和用戶體驗(yàn)直接相關(guān)的)才使用此形狀。
(6)多重分支

多重分支指的是幾種并列的情況,每種情況都有發(fā)生的可能,發(fā)生哪種取決于分支起始處的判斷結(jié)果。
(7)對(duì)話框

有時(shí)候一些操作可以利用對(duì)話框來完成, 這些對(duì)話框由js生成,顯示在父界面之上。
(8)注釋

這個(gè)形狀(比如頁(yè)面)詳細(xì)的內(nèi)容,或者需要解釋的業(yè)務(wù)邏輯,甚至用戶此處的情況等,我都會(huì)放到注釋中,這樣既降低溝通成本,又可作為備忘。
(9)跳轉(zhuǎn)點(diǎn)

在一個(gè)復(fù)雜的流程圖中,往往出現(xiàn)跳轉(zhuǎn)到另外一個(gè)遠(yuǎn)處結(jié)點(diǎn)的情況,此時(shí)如果直接用線連過去,未免使得流程圖顯得凌亂,用一個(gè)跳轉(zhuǎn)點(diǎn)就解決問題了。在點(diǎn)內(nèi)標(biāo)明跳轉(zhuǎn)到的形狀的編號(hào),畫起來容易,看起來也清楚。
此外,也可以利用跳轉(zhuǎn)點(diǎn)來分割篇幅巨大的流程圖,Yahoo!就這么用。
(10)子流程

分割篇幅巨大的流程圖,更好的辦法是用子流程。
要注意的是,如果你在流程圖中使用了子流程這一形狀,一定記得同時(shí)附上子流程圖,以消除影響項(xiàng)目質(zhì)量的不確定性因素。另外,在子流程圖中也可以標(biāo)明其所屬關(guān)系。
(11)流程塊


可以用流程塊將整張流程圖分隔為幾個(gè)部分,并為每個(gè)部分單獨(dú)命名(比如“流程塊1”等)。這樣做的目的在于從視覺上使復(fù)雜的流程圖變得更為清晰,在溝通時(shí)也方便。
2、圖例和流程圖信息

在團(tuán)隊(duì)合作中,圖例是必須的,否則沒人知道你畫出來的東西到底是什么。即使流程圖只給自己看,也最好養(yǎng)成標(biāo)注圖例的好習(xí)慣。其實(shí)這道理有點(diǎn)類似程序中的注釋。
流程圖信息也是必備的。其內(nèi)容至少應(yīng)包括作者、時(shí)間、流程圖名稱和版本(如下圖)。這一方面可以讓讀者(其他同事)在有問題時(shí)能夠方便地找到作者你,也起到了meta的作用。
3、繪制流程圖的工具
Mac下首選OmniGraffle,Windows下除了Visio,似乎沒有更好的選擇(雖然Visio已經(jīng)很難用了)。
4、評(píng)價(jià)流程圖的好壞
我覺得一個(gè)好的流程圖至少應(yīng)做到以下幾點(diǎn):
- 密切地迎合了用戶的心理狀態(tài)、如實(shí)的反映了用戶的操作習(xí)慣。流程圖是要指導(dǎo)UI設(shè)計(jì)的,是UI設(shè)計(jì)的參照物,如果流程圖本身無法正確描繪出用戶的情況的話,UI十有八九會(huì)出問題;
- 覆蓋了各種可能的情況和細(xì)節(jié)。這非常重要。任何在先期不確定的因素,都會(huì)在項(xiàng)目中成為隨時(shí)引爆的地雷,都會(huì)直接降低最終上線的UI質(zhì)量。此種情況真是屢見不鮮。但同時(shí)這條又很難做到,因?yàn)樗粌H要求設(shè)計(jì)師熟悉用戶,也要設(shè)計(jì)師充分知曉產(chǎn)品的商業(yè)邏輯,還要了解系統(tǒng)的運(yùn)作機(jī)制,落下以上任何一個(gè)方面,都會(huì)在流程圖中留下死角。這個(gè)問題我不知道有沒有更好的解決方案,不過與PD和系分反復(fù)溝通是個(gè)行之有效的方法;
- 考慮到系統(tǒng)的設(shè)計(jì)和承受能力。系統(tǒng)的運(yùn)作機(jī)制和承受能力必須在繪制流程圖過程中考慮進(jìn)去,以免出現(xiàn)流程圖被開發(fā)人員槍斃的情況。我的習(xí)慣是,在繪制流程圖時(shí)和系統(tǒng)分析師頻繁溝通和交流,確保每一個(gè)環(huán)節(jié)都是可行的;
- 確保別人看得懂你的流程圖。別人現(xiàn)在看不懂,你自己以后也一樣看不懂。為了降低溝通成本,把流程圖畫清楚吧。
5、其它
(1)想辦法把流程圖繪制得漂亮些。誰不喜歡漂亮的東西呢?
這是我做過的一些流程圖,當(dāng)然文字全部模糊掉了(放圖之前猶豫了好長(zhǎng)時(shí)間-這樣做不知是否有損我的職業(yè)道德。我特意請(qǐng)教了Fenng,他覺得沒事。如果誰覺得有問題請(qǐng)直言不諱地告訴我)。


(2)如果你在公司里不是一錘定音式的人物的話,你就需要對(duì)你的文檔進(jìn)行版本管理。流程圖也不例外,什么時(shí)間發(fā)布的什么版本,都要清楚地標(biāo)出來,“ 最新”是個(gè)用不得的詞。
我就說這么多了,拋磚引玉而已,蓉兒等人看你們的了!
噢對(duì)了,問個(gè)事兒:大家有沒有覺得我每次寫的文章都太長(zhǎng)了?
從ftp定時(shí)下載按日期生成的文件
1、下載腳本get.bat如下
f:
cd f:/beifen (腳本所在目錄)
set cicdate=%date:~0,4%%date:~5,2%%date:~8,2%
(echo open ftp地址
echo 用戶名
echo 密碼
echo prompt
echo get %cicdate%.txt
echo bye) > ftp_beifen.src
ftp -s:ftp_beifen.src
echo %date%導(dǎo)出數(shù)據(jù)庫(kù)備份結(jié)束,時(shí)間:%time% >> getftp_beifen.log
2、在xp上定時(shí)自動(dòng)運(yùn)行批處理文件
AT命令是Windows XP中內(nèi)置的命令,它也可以媲美Windows中的“計(jì)劃任務(wù)”,而且在計(jì)劃的安排、任務(wù)的管理、工作事務(wù)的處理方面,
AT命令具有更強(qiáng)大更神通的功能。AT命令可在指定時(shí)間和日期、在指定計(jì)算機(jī)上運(yùn)行命令和程序。
查看所有安排的計(jì)劃 at
取消已經(jīng)安排的計(jì)劃 at 5 /Delete
在dos下運(yùn)行一下命令,系統(tǒng)就會(huì)在每天的16:46分自動(dòng)運(yùn)行批處理文件get.bat
net stop schedule
net start schedule
at 16:46 /every:Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday F:\beifen\get.bat
轉(zhuǎn)自:http://blog.csdn.net/tianlesoftware/archive/2009/12/01/4915223.aspx
一、什么是Oracle字符集
Oracle字符集是一個(gè)字節(jié)數(shù)據(jù)的解釋的符號(hào)集合,有大小之分,有相互的包容關(guān)系。ORACLE 支持國(guó)家語言的體系結(jié)構(gòu)允許你使用本地化語言來存儲(chǔ),處理,檢索數(shù)據(jù)。它使數(shù)據(jù)庫(kù)工具,錯(cuò)誤消息,排序次序,日期,時(shí)間,貨幣,數(shù)字,和日歷自動(dòng)適應(yīng)本地化語言和平臺(tái)。
影響Oracle數(shù)據(jù)庫(kù)字符集最重要的參數(shù)是NLS_LANG參數(shù)。
它的格式如下: NLS_LANG = language_territory.charset
它有三個(gè)組成部分(語言、地域和字符集),每個(gè)成分控制了NLS子集的特性。
其中:
Language: 指定服務(wù)器消息的語言, 影響提示信息是中文還是英文
Territory: 指定服務(wù)器的日期和數(shù)字格式,
Charset: 指定字符集。
如:AMERICAN _ AMERICA. ZHS16GBK
從NLS_LANG的組成我們可以看出,真正影響數(shù)據(jù)庫(kù)字符集的其實(shí)是第三部分。
所以兩個(gè)數(shù)據(jù)庫(kù)之間的字符集只要第三部分一樣就可以相互導(dǎo)入導(dǎo)出數(shù)據(jù),前面影響的只是提示信息是中文還是英文。
二.字符集的相關(guān)知識(shí):
2.1 字符集
實(shí)質(zhì)就是按照一定的字符編碼方案,對(duì)一組特定的符號(hào),分別賦予不同數(shù)值編碼的集合。Oracle數(shù)據(jù)庫(kù)最早支持的編碼方案是US7ASCII。
Oracle的字符集命名遵循以下命名規(guī)則:
<Language><bit size><encoding>
即: <語言><比特位數(shù)><編碼>
比如: ZHS16GBK表示采用GBK編碼格式、16位(兩個(gè)字節(jié))簡(jiǎn)體中文字符集
2.2 字符編碼方案
2.2.1 單字節(jié)編碼
(1)單字節(jié)7位字符集,可以定義128個(gè)字符,最常用的字符集為US7ASCII
(2)單字節(jié)8位字符集,可以定義256個(gè)字符,適合于歐洲大部分國(guó)家
例如:WE8ISO8859P1(西歐、8位、ISO標(biāo)準(zhǔn)8859P1編碼)
2.2.2 多字節(jié)編碼
(1)變長(zhǎng)多字節(jié)編碼
某些字符用一個(gè)字節(jié)表示,其它字符用兩個(gè)或多個(gè)字符表示,變長(zhǎng)多字節(jié)編碼常用于對(duì)亞洲語言的支持, 例如日語、漢語、印地語等
例如:AL32UTF8(其中AL代表ALL,指適用于所有語言)、zhs16cgb231280
(2)定長(zhǎng)多字節(jié)編碼
每一個(gè)字符都使用固定長(zhǎng)度字節(jié)的編碼方案,目前oracle唯一支持的定長(zhǎng)多字節(jié)編碼是AF16UTF16,也是僅用于國(guó)家字符集
2.2.3 unicode編碼
Unicode是一個(gè)涵蓋了目前全世界使用的所有已知字符的單一編碼方案,也就是說Unicode為每一個(gè)字符提供唯一的編碼。UTF-16是unicode的16位編碼方式,是一種定長(zhǎng)多字節(jié)編碼,用2個(gè)字節(jié)表示一個(gè)unicode字符,AF16UTF16是UTF-16編碼字符集。
UTF-8是unicode的8位編碼方式,是一種變長(zhǎng)多字節(jié)編碼,這種編碼可以用1、2、3個(gè)字節(jié)表示一個(gè)unicode字符,AL32UTF8,UTF8、UTFE是UTF-8編碼字符集
2.3 字符集超級(jí)
當(dāng)一種字符集(字符集A)的編碼數(shù)值包含所有另一種字符集(字符集B)的編碼數(shù)值,并且兩種字符集相同編碼數(shù)值代表相同的字符時(shí),則字符集A是字符集B的超級(jí),或稱字符集B是字符集A的子集。
Oracle8i和oracle9i官方文檔資料中備有子集-超級(jí)對(duì)照表(subset-superset pairs),例如:WE8ISO8859P1是WE8MSWIN1252的子集。由于US7ASCII是最早的Oracle數(shù)據(jù)庫(kù)編碼格式,因此有許多字符集是US7ASCII的超集,例如WE8ISO8859P1、ZHS16CGB231280、ZHS16GBK都是US7ASCII的超集。
2.4 數(shù)據(jù)庫(kù)字符集(oracle服務(wù)器端字符集)
數(shù)據(jù)庫(kù)字符集在創(chuàng)建數(shù)據(jù)庫(kù)時(shí)指定,在創(chuàng)建后通常不能更改。在創(chuàng)建數(shù)據(jù)庫(kù)時(shí),可以指定字符集(CHARACTER SET)和國(guó)家字符集(NATIONAL CHARACTER SET)。
2.4.1字符集
(1)用來存儲(chǔ)CHAR, VARCHAR2, CLOB, LONG等類型數(shù)據(jù)
(2)用來標(biāo)示諸如表名、列名以及PL/SQL變量等
(3)用來存儲(chǔ)SQL和PL/SQL程序單元等
2.4.2國(guó)家字符集:
(1)用以存儲(chǔ)NCHAR, NVARCHAR2, NCLOB等類型數(shù)據(jù)
(2)國(guó)家字符集實(shí)質(zhì)上是為oracle選擇的附加字符集,主要作用是為了增強(qiáng)oracle的字符處理能力,因?yàn)镹CHAR數(shù)據(jù)類型可以提供對(duì)亞洲使用定長(zhǎng)多字節(jié)編碼的支持,而數(shù)據(jù)庫(kù)字符集則不能。國(guó)家字符集在oracle9i中進(jìn)行了重新定義,只能在unicode編碼中的AF16UTF16和UTF8中選擇,默認(rèn)值是AF16UTF16
2.4.3查詢字符集參數(shù)
可以查詢以下數(shù)據(jù)字典或視圖查看字符集設(shè)置情況
nls_database_parameters、props$、v$nls_parameters
查詢結(jié)果中NLS_CHARACTERSET表示字符集,NLS_NCHAR_CHARACTERSET表示國(guó)家字符集
2.4.4修改數(shù)據(jù)庫(kù)字符集
按照上文所說,數(shù)據(jù)庫(kù)字符集在創(chuàng)建后原則上不能更改。不過有2種方法可行。
1. 如果需要修改字符集,通常需要導(dǎo)出數(shù)據(jù)庫(kù)數(shù)據(jù),重建數(shù)據(jù)庫(kù),再導(dǎo)入數(shù)據(jù)庫(kù)數(shù)據(jù)的方式來轉(zhuǎn)換。
2. 通過ALTER DATABASE CHARACTER SET語句修改字符集,但創(chuàng)建數(shù)據(jù)庫(kù)后修改字符集是有限制的,只有新的字符集是當(dāng)前字符集的超集時(shí)才能修改數(shù)據(jù)庫(kù)字符集,例如UTF8是US7ASCII的超集,修改數(shù)據(jù)庫(kù)字符集可使用ALTER DATABASE CHARACTER SET UTF8。
2.5 客戶端字符集(NLS_LANG參數(shù))
2.5.1客戶端字符集含義
客戶端字符集定義了客戶端字符數(shù)據(jù)的編碼方式,任何發(fā)自或發(fā)往客戶端的字符數(shù)據(jù)均使用客戶端定義的字符集編碼,客戶端可以看作是能與數(shù)據(jù)庫(kù)直接連接的各種應(yīng)用,例如sqlplus,exp/imp等。客戶端字符集是通過設(shè)置NLS_LANG參數(shù)來設(shè)定的。
2.5.2 NLS_LANG參數(shù)格式
NLS_LANG=<language>_<territory>.<client character set>
Language: 顯示oracle消息,校驗(yàn),日期命名
Territory:指定默認(rèn)日期、數(shù)字、貨幣等格式
Client character set:指定客戶端將使用的字符集
例如:NLS_LANG=AMERICAN_AMERICA.US7ASCII
AMERICAN是語言,AMERICA是地區(qū),US7ASCII是客戶端字符集
2.5.3客戶端字符集設(shè)置方法
1)UNIX環(huán)境
$NLS_LANG=“simplified chinese”_china.zhs16gbk
$export NLS_LANG
編輯oracle用戶的profile文件
2)Windows環(huán)境
編輯注冊(cè)表
Regedit.exe ---》 HKEY_LOCAL_MACHINE ---》SOFTWARE ---》 ORACLE-HOME
2.5.4 NLS參數(shù)查詢
Oracle提供若干NLS參數(shù)定制數(shù)據(jù)庫(kù)和用戶機(jī)以適應(yīng)本地格式,例如有NLS_LANGUAGE,NLS_DATE_FORMAT,NLS_CALENDER等,可以通過查詢以下數(shù)據(jù)字典或v$視圖查看。
NLS_DATABASE_PARAMETERS:顯示數(shù)據(jù)庫(kù)當(dāng)前NLS參數(shù)取值,包括數(shù)據(jù)庫(kù)字符集取值
NLS_SESSION_PARAMETERS: 顯示由NLS_LANG 設(shè)置的參數(shù),或經(jīng)過alter session 改變后的參數(shù)值(不包括由NLS_LANG 設(shè)置的客戶端字符集)
NLS_INSTANCE_PARAMETE: 顯示由參數(shù)文件init<SID>.ora 定義的參數(shù)
V$NLS_PARAMETERS:顯示數(shù)據(jù)庫(kù)當(dāng)前NLS參數(shù)取值
2.5.5修改NLS參數(shù)
使用下列方法可以修改NLS參數(shù)
(1)修改實(shí)例啟動(dòng)時(shí)使用的初始化參數(shù)文件
(2)修改環(huán)境變量NLS_LANG
(3)使用ALTER SESSION語句,在oracle會(huì)話中修改
(4)使用某些SQL函數(shù)
NLS作用優(yōu)先級(jí)別:Sql function > alter session > 環(huán)境變量或注冊(cè)表 > 參數(shù)文件 > 數(shù)據(jù)庫(kù)默認(rèn)參數(shù)
三.EXP/IMP 與 字符集
3.1 EXP/IMP
Export 和 Import 是一對(duì)讀寫Oracle數(shù)據(jù)的工具。Export 將 Oracle 數(shù)據(jù)庫(kù)中的數(shù)據(jù)輸出到操作系統(tǒng)文件中, Import 把這些文件中的數(shù)據(jù)讀到Oracle 數(shù)據(jù)庫(kù)中,由于使用exp/imp進(jìn)行數(shù)據(jù)遷移時(shí),數(shù)據(jù)從源數(shù)據(jù)庫(kù)到目標(biāo)數(shù)據(jù)庫(kù)的過程中有四個(gè)環(huán)節(jié)涉及到字符集,如果這四個(gè)環(huán)節(jié)的字符集不一致,將會(huì)發(fā)生字符集轉(zhuǎn)換。
EXP
____________ _________________ _____________
|imp導(dǎo)入文件|<-|環(huán)境變量NLS_LANG|<-|數(shù)據(jù)庫(kù)字符集|
------------ ----------------- -------------
IMP
____________ _________________ _____________
|imp導(dǎo)入文件|->|環(huán)境變量NLS_LANG|->|數(shù)據(jù)庫(kù)字符集|
------------ ----------------- -------------
四個(gè)字符集是
(1)源數(shù)據(jù)庫(kù)字符集
(2)Export過程中用戶會(huì)話字符集(通過NLS_LANG設(shè)定)
(3)Import過程中用戶會(huì)話字符集(通過NLS_LANG設(shè)定)
(4)目標(biāo)數(shù)據(jù)庫(kù)字符集
3.2導(dǎo)出的轉(zhuǎn)換過程
在Export過程中,如果源數(shù)據(jù)庫(kù)字符集與Export用戶會(huì)話字符集不一致,會(huì)發(fā)生字符集轉(zhuǎn)換,并在導(dǎo)出文件的頭部幾個(gè)字節(jié)中存儲(chǔ)Export用戶會(huì)話字符集的ID號(hào)。在這個(gè)轉(zhuǎn)換過程中可能發(fā)生數(shù)據(jù)的丟失。
例:如果源數(shù)據(jù)庫(kù)使用ZHS16GBK,而Export用戶會(huì)話字符集使用US7ASCII,由于ZHS16GBK是16位字符集,而US7ASCII是7位字符集,這個(gè)轉(zhuǎn)換過程中,中文字符在US7ASCII中不能夠找到對(duì)等的字符,所以所有中文字符都會(huì)丟失而變成“?? ”形式,這樣轉(zhuǎn)換后生成的Dmp文件已經(jīng)發(fā)生了數(shù)據(jù)丟失。
因此如果想正確導(dǎo)出源數(shù)據(jù)庫(kù)數(shù)據(jù),則Export過程中用戶會(huì)話字符集應(yīng)等于源數(shù)據(jù)庫(kù)字符集或是源數(shù)據(jù)庫(kù)字符集的超集
3.3導(dǎo)入的轉(zhuǎn)換過程
(1)確定導(dǎo)出數(shù)據(jù)庫(kù)字符集環(huán)境
通過讀取導(dǎo)出文件頭,可以獲得導(dǎo)出文件的字符集設(shè)置
(2)確定導(dǎo)入session的字符集,即導(dǎo)入Session使用的NLS_LANG環(huán)境變量
(3)IMP讀取導(dǎo)出文件
讀取導(dǎo)出文件字符集ID,和導(dǎo)入進(jìn)程的NLS_LANG進(jìn)行比較
(4)如果導(dǎo)出文件字符集和導(dǎo)入Session字符集相同,那么在這一步驟內(nèi)就不需要轉(zhuǎn)換, 如果不同,就需要把數(shù)據(jù)轉(zhuǎn)換為導(dǎo)入Session使用的字符集。可以看出,導(dǎo)入數(shù)據(jù)到數(shù)據(jù)庫(kù)過程中發(fā)生兩次字符集轉(zhuǎn)換
第一次:導(dǎo)入文件字符集與導(dǎo)入Session使用的字符集之間的轉(zhuǎn)換,如果這個(gè)轉(zhuǎn)換過程不能正確完成,Import向目標(biāo)數(shù)據(jù)庫(kù)的導(dǎo)入過程也就不能完成。
第二次:導(dǎo)入Session字符集與數(shù)據(jù)庫(kù)字符集之間的轉(zhuǎn)換。
四. 查看數(shù)據(jù)庫(kù)字符集
涉及三方面的字符集,
1. oracel server端的字符集;
2. oracle client端的字符集;
3. dmp文件的字符集。
在做數(shù)據(jù)導(dǎo)入的時(shí)候,需要這三個(gè)字符集都一致才能正確導(dǎo)入。
4.1 查詢oracle server端的字符集
有很多種方法可以查出oracle server端的字符集,比較直觀的查詢方法是以下這種:
SQL> select userenv('language') from dual;
USERENV('LANGUAGE')
----------------------------------------------------
SIMPLIFIED CHINESE_CHINA.ZHS16GBK
SQL>select userenv(‘language’) from dual;
AMERICAN _ AMERICA. ZHS16GBK
4.2 如何查詢dmp文件的字符集
用oracle的exp工具導(dǎo)出的dmp文件也包含了字符集信息,dmp文件的第2和第3個(gè)字節(jié)記錄了dmp文件的字符集。如果dmp文件不大,比如只有幾M或幾十M,可以用UltraEdit打開(16進(jìn)制方式),看第2第3個(gè)字節(jié)的內(nèi)容,如0354,然后用以下SQL查出它對(duì)應(yīng)的字符集:
SQL> select nls_charset_name(to_number('0354','xxxx')) from dual;
ZHS16GBK
如果dmp文件很大,比如有2G以上(這也是最常見的情況),用文本編輯器打開很慢或者完全打不開,可以用以下命令(在unix主機(jī)上):
cat exp.dmp |od -x|head -1|awk '{print $2 $3}'|cut -c 3-6
然后用上述SQL也可以得到它對(duì)應(yīng)的字符集。
4.3 查詢oracle client端的字符集
在windows平臺(tái)下,就是注冊(cè)表里面相應(yīng)OracleHome的NLS_LANG。還可以在dos窗口里面自己設(shè)置,
比如: set nls_lang=AMERICAN_AMERICA.ZHS16GBK
這樣就只影響這個(gè)窗口里面的環(huán)境變量。
在unix平臺(tái)下,就是環(huán)境變量NLS_LANG。
$echo $NLS_LANG
AMERICAN_AMERICA.ZHS16GBK
如果檢查的結(jié)果發(fā)現(xiàn)server端與client端字符集不一致,請(qǐng)統(tǒng)一修改為同server端相同的字符集。
補(bǔ)充:
(1).數(shù)據(jù)庫(kù)服務(wù)器字符集
select * from nls_database_parameters
來源于props$,是表示數(shù)據(jù)庫(kù)的字符集。
(2).客戶端字符集環(huán)境
select * from nls_instance_parameters
其來源于v$parameter,表示客戶端的字符集的設(shè)置,可能是參數(shù)文件,環(huán)境變量或者是注冊(cè)表
(3).會(huì)話字符集環(huán)境
select * from nls_session_parameters
來源于v$nls_parameters,表示會(huì)話自己的設(shè)置,可能是會(huì)話的環(huán)境變量或者是alter session完成,如果會(huì)話沒有特殊的設(shè)置,將與nls_instance_parameters一致。
(4).客戶端的字符集要求與服務(wù)器一致,才能正確顯示數(shù)據(jù)庫(kù)的非Ascii字符。
如果多個(gè)設(shè)置存在的時(shí)候,NLS作用優(yōu)先級(jí)別:Sql function > alter session > 環(huán)境變量或注冊(cè)表 > 參數(shù)文件 > 數(shù)據(jù)庫(kù)默認(rèn)參數(shù)
字符集要求一致,但是語言設(shè)置卻可以不同,語言設(shè)置建議用英文。如字符集是zhs16gbk,則nls_lang可以是American_America.zhs16gbk。
五. 修改oracle的字符集
按照上文所說,數(shù)據(jù)庫(kù)字符集在創(chuàng)建后原則上不能更改。因此,在設(shè)計(jì)和安裝之初考慮使用哪一種字符集十分重要。對(duì)數(shù)據(jù)庫(kù)server而言,錯(cuò)誤的修改字符集將會(huì)導(dǎo)致很多不可測(cè)的后果,可能會(huì)嚴(yán)重影響數(shù)據(jù)庫(kù)的正常運(yùn)行,所以在修改之前一定要確認(rèn)兩種字符集是否存在子集和超集的關(guān)系。一般來說,除非萬不得已,我們不建議修改oracle數(shù)據(jù)庫(kù)server端的字符集。特別說明,我們最常用的兩種字符集ZHS16GBK和ZHS16CGB231280之間不存在子集和超集關(guān)系,因此理論上講這兩種字符集之間的相互轉(zhuǎn)換不受支持。
不過修改字符集有2種方法可行。
1. 通常需要導(dǎo)出數(shù)據(jù)庫(kù)數(shù)據(jù),重建數(shù)據(jù)庫(kù),再導(dǎo)入數(shù)據(jù)庫(kù)數(shù)據(jù)的方式來轉(zhuǎn)換。
2. 通過ALTER DATABASE CHARACTER SET語句修改字符集,但創(chuàng)建數(shù)據(jù)庫(kù)后修改字符集是有限制的,只有新的字符集是當(dāng)前字符集的超集時(shí)才能修改數(shù)據(jù)庫(kù)字符集,例如UTF8是US7ASCII的超集,修改數(shù)據(jù)庫(kù)字符集可使用ALTER DATABASE CHARACTER SET UTF8。
5.1 修改server端字符集(不建議使用)
1. 關(guān)閉數(shù)據(jù)庫(kù)
SQL>SHUTDOWN IMMEDIATE
2. 啟動(dòng)到Mount
SQL>STARTUP MOUNT;
SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
SQL>ALTER DATABASE OPEN;
SQL>ALTER DATABASE CHARACTER SET ZHS16GBK;
SQL>ALTER DATABASE national CHARACTER SET ZHS16GBK;
SQL>SHUTDOWN IMMEDIATE;
SQL>STARTUP
注意:如果沒有大對(duì)象,在使用過程中進(jìn)行語言轉(zhuǎn)換沒有什么影響,(切記設(shè)定的字符集必須是ORACLE支持,不然不能start) 按上面的做法就可以。
若出現(xiàn)‘ORA-12717: Cannot ALTER DATABASE NATIONAL CHARACTER SET when NCLOB data exists’ 這樣的提示信息,
要解決這個(gè)問題有兩種方法
1. 利用INTERNAL_USE 關(guān)鍵字修改區(qū)域設(shè)置,
2. 利用re-create,但是re-create有點(diǎn)復(fù)雜,所以請(qǐng)用internal_use
SQL>SHUTDOWN IMMEDIATE;
SQL>STARTUP MOUNT EXCLUSIVE;
SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
SQL>ALTER DATABASE OPEN;
SQL>ALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE UTF8;
SQL>SHUTDOWN immediate;
SQL>startup;
如果按上面的做法做,National charset的區(qū)域設(shè)置就沒有問題
5.2 修改dmp文件字符集
上文說過,dmp文件的第2第3字節(jié)記錄了字符集信息,因此直接修改dmp文件的第2第3字節(jié)的內(nèi)容就可以‘騙’過oracle的檢查。這樣做理論上也僅是從子集到超集可以修改,但很多情況下在沒有子集和超集關(guān)系的情況下也可以修改,我們常用的一些字符集,如US7ASCII,WE8ISO8859P1,ZHS16CGB231280,ZHS16GBK基本都可以改。因?yàn)楦牡闹皇莇mp文件,所以影響不大。
具體的修改方法比較多,最簡(jiǎn)單的就是直接用UltraEdit修改dmp文件的第2和第3個(gè)字節(jié)。
比如想將dmp文件的字符集改為ZHS16GBK,可以用以下SQL查出該種字符集對(duì)應(yīng)的16進(jìn)制代碼: SQL> select to_char(nls_charset_id('ZHS16GBK'), 'xxxx') from dual;
0354
然后將dmp文件的2、3字節(jié)修改為0354即可。
如果dmp文件很大,用ue無法打開,就需要用程序的方法了。
5.3客戶端字符集設(shè)置方法
1)UNIX環(huán)境
$NLS_LANG=“simplified chinese”_china.zhs16gbk
$export NLS_LANG
編輯oracle用戶的profile文件
2)Windows環(huán)境
編輯注冊(cè)表
Regedit.exe ---》 HKEY_LOCAL_MACHINE ---》SOFTWARE ---》 ORACLE-HOME
或者在窗口設(shè)置:
set nls_lang=AMERICAN_AMERICA.ZHS16GBK
本文來自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/tianlesoftware/archive/2009/12/01/4915223.aspx
轉(zhuǎn)自:http://blog.csdn.net/tianlesoftware/archive/2009/11/04/4764254.aspx
從10g開始,oracle開始提供Shrink的命令,假如我們的表空間中支持自動(dòng)段空間管理 (ASSM),就可以使用這個(gè)特性縮小段,即降低HWM。這里需要強(qiáng)調(diào)一點(diǎn),10g的這個(gè)新特性,僅對(duì)ASSM表空間有效,否則會(huì)報(bào) ORA-10635: Invalid segment or tablespace type。
有關(guān)ASSM的詳細(xì)信息,請(qǐng)參考我的Blog:Oracle 自動(dòng)段空間管理
http://blog.csdn.net/tianlesoftware/archive/2009/12/07/4958989.aspx
如果經(jīng)常在表上執(zhí)行DML操作,會(huì)造成數(shù)據(jù)庫(kù)塊中數(shù)據(jù)分布稀疏,浪費(fèi)大量空間。同時(shí)也會(huì)影響全表掃描的性能,因?yàn)槿頀呙栊枰L問更多的數(shù)據(jù)塊。從oracle10g開始,表可以通過shrink來重組數(shù)據(jù)使數(shù)據(jù)分布更緊密,同時(shí)降低HWM釋放空閑數(shù)據(jù)塊。
segment shrink分為兩個(gè)階段:
1、數(shù)據(jù)重組(compact):通過一系列insert、delete操作,將數(shù)據(jù)盡量排列在段的前面。在這個(gè)過程中需要在表上加RX鎖,即只在需要移動(dòng)的行上加鎖。由于涉及到rowid的改變,需要enable row movement.同時(shí)要disable基于rowid的trigger.這一過程對(duì)業(yè)務(wù)影響比較小。
2、HWM調(diào)整:第二階段是調(diào)整HWM位置,釋放空閑數(shù)據(jù)塊。此過程需要在表上加X鎖,會(huì)造成表上的所有DML語句阻塞。在業(yè)務(wù)特別繁忙的系統(tǒng)上可能造成比較大的影響。
shrink space語句兩個(gè)階段都執(zhí)行。
shrink space compact只執(zhí)行第一個(gè)階段。
如果系統(tǒng)業(yè)務(wù)比較繁忙,可以先執(zhí)行shrink space compact重組數(shù)據(jù),然后在業(yè)務(wù)不忙的時(shí)候再執(zhí)行shrink space降低HWM釋放空閑數(shù)據(jù)塊。
shrink必須開啟行遷移功能。
alter table table_name enable row movement ;
注意:alter table XXX enable row movement語句會(huì)造成引用表XXX的對(duì)象(如存儲(chǔ)過程、包、視圖等)變?yōu)闊o效。執(zhí)行完成后,最好執(zhí)行一下utlrp.sql來編譯無效的對(duì)象。
語法:
alter table <table_name> shrink space [ <null> | compact | cascade ];
alter table <table_name> shrink space compcat;
收縮表,相當(dāng)于把塊中數(shù)據(jù)打結(jié)實(shí)了,但會(huì)保持 high water mark;
alter table <tablespace_name> shrink space;
收縮表,降低 high water mark;
alter table <tablespace_name> shrink space cascade;
收縮表,降低 high water mark,并且相關(guān)索引也要收縮一下下。
alter index idxname shrink space;
回縮索引
1:普通表
Sql腳本,改腳本會(huì)生成相應(yīng)的語句
select'alter table '||table_name||' enable row movement;'||chr(10)||'alter table '||table_name||' shrink space;'||chr(10)from user_tables;
select'alter index '||index_name||' shrink space;'||chr(10)from user_indexes;
2:分區(qū)表的處理
進(jìn)行shrink space時(shí) 發(fā)生ORA-10631錯(cuò)誤.shrink space有一些限制.
在表上建有函數(shù)索引(包括全文索引)會(huì)失敗。
Sql腳本,改腳本會(huì)生成相應(yīng)的語句
select 'alter table '||table_name||' enable row movement;'||chr(10)||'alter table '||table_name||' shrink space;'||chr(10) from user_tables where ;
select 'alter index '||index_name||' shrink space;'||chr(10) from user_indexes where uniqueness='NONUNIQUE' ;
select 'alter table '||segment_name||' modify subpartition '||partition_name||' shrink space;'||chr(10) from user_segments where segment_type='TABLE SUBPARTITION' ';
詳細(xì)測(cè)試:
我們用系統(tǒng)視圖all_objects來在上個(gè)測(cè)試的tablespace ASSM上創(chuàng)建測(cè)試表my_objects
/* Formatted on 2009-12-7 20:42:45 (QP5 v5.115.810.9015) */
CREATE TABLESPACE ASSM DATAFILE 'd:\ASSM01.dbf' SIZE 100M EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO;
/* Formatted on 2009-12-7 20:39:26 (QP5 v5.115.810.9015) */
SELECT TABLESPACE_NAME,
BLOCK_SIZE,
EXTENT_MANAGEMENT,
ALLOCATION_TYPE,
SEGMENT_SPACE_MANAGEMENT
FROM dba_tablespaces
WHERE TABLESPACE_NAME = 'ASSM';
TABLESPACE_NAME BLOCK_SIZE EXTENT_MAN ALLOCATIO SEGMEN
--------------------- ---------- ---------- --------- ------
ASSM 8192 LOCAL SYSTEM AUTO
1 row selected.
/* Formatted on 2009-12-7 20:44:15 (QP5 v5.115.810.9015) */
CREATE TABLE my_objects
TABLESPACE assm
AS
SELECT * FROM all_objects;
然后我們隨機(jī)地從table MY_OBJECTS中刪除一部分?jǐn)?shù)據(jù):
SQL> SELECT COUNT ( * ) FROM my_objects;
COUNT(*)
----------
49477
SQL> delete from my_objects where object_name like '%C%';
SQL> delete from my_objects where object_name like '%U%';
SQL> delete from my_objects where object_name like '%A%';
現(xiàn)在我們使用show_space()來看看my_objects的數(shù)據(jù)存儲(chǔ)狀況:
注: show_space() 存儲(chǔ)過程代碼參看一下連接的附件
http://blog.csdn.net/tianlesoftware/archive/2009/12/07/4958989.aspx
SQL>exec show_space('my_objects','auto','T','Y');
Total Blocks............................768
Total Bytes.............................6291456
Unused Blocks...........................68
Unused Bytes............................557056
Last Used Ext FileId....................8
Last Used Ext BlockId...................649
Last Used Block.........................60
*************************************************
The segment is analyzed
0% -- 25% free space blocks.............41
0% -- 25% free space bytes..............335872
25% -- 50% free space blocks............209
25% -- 50% free space bytes.............1712128
50% -- 75% free space blocks............190
50% -- 75% free space bytes.............1556480
75% -- 100% free space blocks...........229
75% -- 100% free space bytes............1875968
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................11
Total bytes.............................90112
PL/SQL 過程已成功完成。
這里,table my_objects的HWM下有767個(gè)block,其中,free space為25-50%的block有209個(gè),free space為50-75%的block有190個(gè),free space為75-100%的block有229個(gè). Total blocks 11個(gè)。
這種情況下,我們需要對(duì)這個(gè)table的現(xiàn)有數(shù)據(jù)行進(jìn)行重組。
要使用assm上的shink,首先我們需要使該表支持行移動(dòng),可以用這樣的命令來完成:
alter table my_objects enable row movement;
現(xiàn)在,就可以來降低my_objects的HWM,回收空間了,使用命令:
alter table bookings shrink space;
我們具體的看一下實(shí)驗(yàn)的結(jié)果:
SQL> alter table my_objects enable row movement;
表已更改。
SQL> alter table my_objects shrink space;
表已更改。
SQL>exec show_space('my_objects','auto','T','Y');
Total Blocks............................272
Total Bytes.............................2228224
Unused Blocks...........................0
Unused Bytes............................0
Last Used Ext FileId....................8
Last Used Ext BlockId...................265
Last Used Block.........................16
*************************************************
The segment is analyzed
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............0
25% -- 50% free space bytes.............0
50% -- 75% free space blocks............1
50% -- 75% free space bytes.............8192
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................257
Total bytes.............................2105344
在執(zhí)行玩shrink命令后,我們可以看到,table my_objects的HWM現(xiàn)在降到了271的位置,而且HWM下的block的空間使用狀況,Total blocks 的block有257個(gè),free space 為25-50% Block只有0個(gè)。
Shrink 的實(shí)現(xiàn)機(jī)制:
我們接下來討論一下shrink的實(shí)現(xiàn)機(jī)制,我們同樣使用討論move機(jī)制的那個(gè)實(shí)驗(yàn)來觀察。
/* Formatted on 2009-12-7 20:58:40 (QP5 v5.115.810.9015) */
CREATE TABLE TEST_HWM (id INT, name CHAR (2000))
TABLESPACE ASSM;
INSERT INTO TEST_HWM VALUES (1, 'aa');
INSERT INTO TEST_HWM VALUES (2, 'bb');
INSERT INTO TEST_HWM VALUES (2, 'cc');
INSERT INTO TEST_HWM VALUES (3, 'dd');
INSERT INTO TEST_HWM VALUES (4, 'ds');
INSERT INTO TEST_HWM VALUES (5, 'dss');
INSERT INTO TEST_HWM VALUES (6, 'dss');
INSERT INTO TEST_HWM VALUES (7, 'ess');
INSERT INTO TEST_HWM VALUES (8, 'es');
INSERT INTO TEST_HWM VALUES (9, 'es');
INSERT INTO TEST_HWM VALUES (10, 'es');
我們來看看這個(gè)table的rowid和block的ID和信息:
/* Formatted on 2009-12-7 21:00:02 (QP5 v5.115.810.9015) */
SQL>SELECT ROWID, id, name FROM TEST_HWM;ROWID ID NAME
ROWID ID NAME
------------------------------------- ---------- --------
AAANMEAAIAAAAEcAAA 3 dd
AAANMEAAIAAAAEcAAB 4 ds
AAANMEAAIAAAAEcAAC 5 dss
AAANMEAAIAAAAEdAAA 6 dss
AAANMEAAIAAAAEdAAB 7 ess
AAANMEAAIAAAAEdAAC 8 es
AAANMEAAIAAAAEeAAA 9 es
AAANMEAAIAAAAEeAAB 10 es
AAANMEAAIAAAAEgAAA 1 aa
AAANMEAAIAAAAEgAAB 2 bb
AAANMEAAIAAAAEgAAC 2 cc
/* Formatted on 2009-12-7 21:00:49 (QP5 v5.115.810.9015) */
SQL>SELECT EXTENT_ID,
FILE_ID,
RELATIVE_FNO,
BLOCK_ID,
BLOCKS
FROM dba_extents
WHERE segment_name = 'TEST_HWM';
EXTENT_ID FILE_ID RELATIVE_FNO BLOCK_ID BLOCKS
---------- ---------- ------------ ---------- ----------
0 8 8 281 8
1 row selected.
然后從table test_hwm中刪除一些數(shù)據(jù):
delete from TEST_HWM where id = 2;
delete from TEST_HWM where id = 4;
delete from TEST_HWM where id = 3;
delete from TEST_HWM where id = 7;
delete from TEST_HWM where id = 8;
觀察table test_hwm的rowid和blockid的信息:
SQL> select rowid , id,name from TEST_HWM;
ROWID ID NAME
------------------------------------------ ---------- ---------
AAANMEAAIAAAAEcAAC 5 dss
AAANMEAAIAAAAEdAAA 6 dss
AAANMEAAIAAAAEeAAA 9 es
AAANMEAAIAAAAEeAAB 10 es
AAANMEAAIAAAAEgAAA 1 aa
/* Formatted on 2009-12-7 21:00:49 (QP5 v5.115.810.9015) */
SQL>SELECT EXTENT_ID,
FILE_ID,
RELATIVE_FNO,
BLOCK_ID,
BLOCKS
FROM dba_extents
WHERE segment_name = 'TEST_HWM';
EXTENT_ID FILE_ID RELATIVE_FNO BLOCK_ID BLOCKS
---------- ---------- ------------ ---------- ----------
0 8 8 281 8
1 row selected.
從以上的信息,我們可以看到,在table test_hwm中,剩下的數(shù)據(jù)是分布在AAAAEc,AAAAEd,AAAAEf,AAAAEg這樣四個(gè)連續(xù)的block中。
SQL> exec show_space('TEST_HWM','auto','T','Y');
Total Blocks............................8
Total Bytes.............................65536
Unused Blocks...........................0
Unused Bytes............................0
Last Used Ext FileId....................8
Last Used Ext BlockId...................281
Last Used Block.........................8
*************************************************
The segment is analyzed
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............1
25% -- 50% free space bytes.............8192
50% -- 75% free space blocks............3
50% -- 75% free space bytes.............24576
75% -- 100% free space blocks...........1
75% -- 100% free space bytes............8192
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................0
Total bytes.............................0
我們可以看到目前這四個(gè)block的空間使用狀況,AAAAEc,AAAAEd,AAAAEf,AAAAEg上各有一行數(shù)據(jù),我們猜測(cè)free space為50-75%的3個(gè)block是這三個(gè)block,那么free space為25-50%的1個(gè)block就是AAAAEg了,剩下free space為 75-100% 的3個(gè)block,是HWM下已格式化的尚未使用的block。(在extent不大于于16個(gè)block時(shí),是以一個(gè)extent為單位來移動(dòng)的)
然后,我們對(duì)table my_objects執(zhí)行shtink的操作:
SQL> alter table test_hwm enable row movement;
Table altered
SQL> alter table test_hwm shrink space;
Table altered
SQL> select rowid ,id,name from TEST_HWM;
ROWID ID NAME
------------------ ---------- ------------
AAANMEAAIAAAAEcAAA 10 es
AAANMEAAIAAAAEcAAC 5 dss
AAANMEAAIAAAAEcAAD 1 aa
AAANMEAAIAAAAEcAAE 9 es
AAANMEAAIAAAAEdAAA 6 dss
/* Formatted on 2009-12-7 21:00:49 (QP5 v5.115.810.9015) */
SQL>SELECT EXTENT_ID,
FILE_ID,
RELATIVE_FNO,
BLOCK_ID,
BLOCKS
FROM dba_extents
WHERE segment_name = 'TEST_HWM';
EXTENT_ID FILE_ID RELATIVE_FNO BLOCK_ID BLOCKS
---------- ---------- ------------ ---------- ----------
0 8 8 281 8
1 row selected.
當(dāng)執(zhí)行了shrink操作后,有意思的現(xiàn)象出現(xiàn)了。我們來看看oracle是如何移動(dòng)行數(shù)據(jù)的,這里的情況和move已經(jīng)不太一樣了。我們知道,在move操作的時(shí)候,所有行的rowid都發(fā)生了變化,table所位于的block的區(qū)域也發(fā)生了變化,但是所有行物理存儲(chǔ)的順序都沒有發(fā)生變化,所以我們得到的結(jié)論是,oracle以block為單位,進(jìn)行了block間的數(shù)據(jù)copy。那么shrink后,我們發(fā)現(xiàn),部分行數(shù)據(jù)的rowid發(fā)生了變化,同時(shí),部分行數(shù)據(jù)的物理存儲(chǔ)的順序也發(fā)生了變化,而table所位于的block的區(qū)域卻沒有變化,這就說明,shrink只移動(dòng)了table其中一部分的行數(shù)據(jù),來完成釋放空間,而且,這個(gè)過程是在table當(dāng)前所使用的block中完成的。
那么Oracle具體移動(dòng)行數(shù)據(jù)的過程是怎樣的呢?我們根據(jù)這樣的實(shí)驗(yàn)結(jié)果,可以來猜測(cè)一下:
Oracle是以行為單位來移動(dòng)數(shù)據(jù)的。Oracle從當(dāng)前table存儲(chǔ)的最后一行數(shù)據(jù)開始移動(dòng),從當(dāng)前table最先使用的block開始搜索空間,所以,shrink之前,rownum=10的那行數(shù)據(jù)(10,es),被移動(dòng)到block AAAAEc上,寫到(1,aa)這行數(shù)據(jù)的后面,所以(10,es)的rownum和rowid同時(shí)發(fā)生改變。然后是(9,es)這行數(shù)據(jù),重復(fù)上述過程。這是oracle從后向前移動(dòng)行數(shù)據(jù)的大致遵循的規(guī)則,那么具體移動(dòng)行數(shù)據(jù)的的算法是比較復(fù)雜的,包括向ASSM的table中insert數(shù)據(jù)使用block的順序的算法也是比較復(fù)雜的,大家有興趣的可以自己來研究,在這里我們不多做討論。
在shrink table的同時(shí)shrink這個(gè)table上的index:
alter table my_objects shrink space cascade;
同樣地,這個(gè)操作只有當(dāng)table上的index也是ASSM時(shí),才能使用。
Move 和 Shrink 產(chǎn)生日志的對(duì)比
我們對(duì)比了同樣數(shù)據(jù)量和分布狀況的兩張table,在move和shrink下生成的redo size(table上沒有index的情況下):
/* Formatted on 2009-12-7 21:20:43 (QP5 v5.115.810.9015) */
SQL>SELECT tablespace_name, SEGMENT_SPACE_MANAGEMENT
FROM dba_tablespaces
WHERE tablespace_name IN ('ASSM', 'HWM');
TABLESPACE_NAME SEGMENT_SPACE_MANAGEMENT
------------------------------ ------------------------
ASSM AUTO
HWM MANUAL
SQL> create table my_objects tablespace ASSM as select * from all_objects where rownum<20000;
Table created
SQL> create table my_objects1 tablespace HWM as select * from all_objects where rownum<20000;
Table created
SQL> select bytes/1024/1024 from user_segments where segment_name = 'MY_OBJECTS';
BYTES/1024/1024
---------------
2.1875
SQL> delete from my_objects where object_name like '%C%';
7278 rows deleted
SQL> delete from my_objects1 where object_name like '%C%';
7278 rows deleted
SQL> delete from my_objects where object_name like '%U%';
2732 rows deleted
SQL> delete from my_objects1 where object_name like '%U%';
2732 rows deleted
SQL> commit;
Commit complete
SQL> alter table my_objects enable row movement;
Table altered
/* Formatted on 2009-12-7 21:21:48 (QP5 v5.115.810.9015) */
SQL>SELECT VALUE
FROM v$mystat, v$statname
WHERE v$mystat.statistic# = v$statname.statistic#
AND v$statname.name = 'redo size';
VALUE
----------
27808792
SQL> alter table my_objects shrink space;
Table altered
SQL>SELECT VALUE
FROM v$mystat, v$statname
WHERE v$mystat.statistic# = v$statname.statistic#
AND v$statname.name = 'redo size';
VALUE
----------
32579712
SQL> alter table my_objects1 move;
Table altered
SQL>SELECT VALUE
FROM v$mystat, v$statname
WHERE v$mystat.statistic# = v$statname.statistic#
AND v$statname.name = 'redo size';
VALUE
----------
32676784
對(duì)于table my_objects,進(jìn)行shrink,產(chǎn)生了32579712 – 27808792=4770920,約4.5M的redo ;對(duì)table my_objects1進(jìn)行move,產(chǎn)生了32676784-32579712= 97072,約95K的redo size。
結(jié)論:與move比較起來,shrink的日志寫要大得多。
Shrink的幾點(diǎn)問題:
1. shrink后index是否需要rebuild:
因?yàn)閟hrink的操作也會(huì)改變行數(shù)據(jù)的rowid,那么,如果table上有index時(shí),shrink table后index會(huì)不會(huì)變?yōu)閁NUSABLE呢?
我們來看這樣的實(shí)驗(yàn),同樣構(gòu)建my_objects的測(cè)試表:
create table my_objects tablespace ASSM as select * from all_objects where rownum<20000;
create index i_my_objects on my_objects (object_id);
delete from my_objects where object_name like '%C%';
delete from my_objects where object_name like '%U%';
現(xiàn)在我們來shrink table my_objects:
SQL> alter table my_objects enable row movement;
Table altered
SQL> alter table my_objects shrink space;
Table altered
SQL> select index_name,status from user_indexes where index_name='I_MY_OBJECTS';
INDEX_NAME STATUS
------------------------------ --------
I_MY_OBJECTS VALID
我們發(fā)現(xiàn),table my_objects上的index的狀態(tài)為VALID,估計(jì)shrink在移動(dòng)行數(shù)據(jù)時(shí),也一起維護(hù)了index上相應(yīng)行的數(shù)據(jù)rowid的信息。我們認(rèn)為,這是對(duì)于move操作后需要rebuild index的改進(jìn)。但是如果一個(gè)table上的index數(shù)量較多,我們知道,維護(hù)index的成本是比較高的,shrink過程中用來維護(hù)index的成本也會(huì)比較高。
2. shrink時(shí)對(duì)table的lock
在對(duì)table進(jìn)行shrink時(shí),會(huì)對(duì)table進(jìn)行怎樣的鎖定呢?當(dāng)我們對(duì)table MY_OBJECTS進(jìn)行shrink操作時(shí),查詢v$locked_objects視圖可以發(fā)現(xiàn),table MY_OBJECTS上加了row-X (SX) 的lock:
SQL>select OBJECT_ID, SESSION_ID,ORACLE_USERNAME,LOCKED_MODE from v$locked_objects;
OBJECT_ID SESSION_ID ORACLE_USERNAME LOCKED_MODE
---------- ---------- ------------------ -----------
55422 153 DLINGER 3
SQL> select object_id from user_objects where object_name = 'MY_OBJECTS';
OBJECT_ID
----------
55422
那么,當(dāng)table在進(jìn)行shrink時(shí),我們對(duì)table是可以進(jìn)行DML操作的。
3. shrink對(duì)空間的要求
我們?cè)谇懊嬗懻摿藄hrink的數(shù)據(jù)的移動(dòng)機(jī)制,既然oracle是從后向前移動(dòng)行數(shù)據(jù),那么,shrink的操作就不會(huì)像move一樣,shrink不需要使用額外的空閑空間。
本文來自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/tianlesoftware/archive/2009/11/04/4764254.aspx
轉(zhuǎn)自:http://blog.csdn.net/rein07/archive/2010/11/25/6033937.aspx
1.SQL>shutdown abort 如果數(shù)據(jù)庫(kù)是打開狀態(tài),強(qiáng)行關(guān)閉
2.SQL>sqlplus / as sysdba
3.SQL>startup
ORACLE 例程已經(jīng)啟動(dòng)。
Total System Global Area 293601280 bytes
Fixed Size 1248624 bytes
Variable Size 121635472 bytes
Database Buffers 167772160 bytes
Redo Buffers 2945024 bytes
數(shù)據(jù)庫(kù)裝載完畢。
ORA-01122: 數(shù)據(jù)庫(kù)文件 1 驗(yàn)證失敗
ORA-01110: 數(shù)據(jù)文件 1:
'F:\ORACLE\PRODUCT\10.2.0\DB_1\ORADATA\ORCLDW\SYSTEM01.DBF'
ORA-01207: 文件比控制文件更新 - 舊的控制文件
4.SQL>alter database backup controlfile to trace as 'f:\aa';
數(shù)據(jù)庫(kù)已更改。
5.SQL>shutdown immediate 如果數(shù)據(jù)庫(kù)是打開狀態(tài),則關(guān)閉
ORA-01109: 數(shù)據(jù)庫(kù)未打開
已經(jīng)卸載數(shù)據(jù)庫(kù)
6.SQL>startup nomount;
ORACLE 例程已經(jīng)啟動(dòng)。
Total System Global Area 105979576 bytes
Fixed Size 454328 bytes
Variable Size 79691776 bytes
Database Buffers 25165824 bytes
Redo Buffers 667648 bytes
7.Editplus之類的編輯器打開在第四步生成的f:\aa文件;
其實(shí)在這個(gè)文件中的已經(jīng)告訴你咋樣恢復(fù)你的數(shù)據(jù)庫(kù)了,找到STARTUP NOMOUNT字樣,然后下面可以看到類似語句,這個(gè)文件有好幾個(gè)類似的生成控制文件語句,主要針對(duì)不懂的環(huán)境執(zhí)行不同的語句,象我的數(shù)據(jù)庫(kù)沒有做任何備份,也不是在歸檔模式,就執(zhí)行這句
CREATE CONTROLFILE REUSE DATABASE "ORCLDW" NORESETLOGS NOARCHIVELOG
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 100
MAXINSTANCES 8
MAXLOGHISTORY 292
LOGFILE
GROUP 1 'F:\ORACLE\PRODUCT\10.2.0\DB_1\ORADATA\ORCLDW\REDO01.LOG' SIZE 50M,
GROUP 2 'F:\ORACLE\PRODUCT\10.2.0\DB_1\ORADATA\ORCLDW\REDO02.LOG' SIZE 50M,
GROUP 3 'F:\ORACLE\PRODUCT\10.2.0\DB_1\ORADATA\ORCLDW\REDO03.LOG' SIZE 50M
DATAFILE
'F:\ORACLE\PRODUCT\10.2.0\DB_1\ORADATA\ORCLDW\SYSTEM01.DBF',
'F:\ORACLE\PRODUCT\10.2.0\DB_1\ORADATA\ORCLDW\UNDOTBS01.DBF',
'F:\ORACLE\PRODUCT\10.2.0\DB_1\ORADATA\ORCLDW\SYSAUX01.DBF',
'F:\ORACLE\PRODUCT\10.2.0\DB_1\ORADATA\ORCLDW\USERS01.DBF',
'F:\ORACLE\PRODUCT\10.2.0\DB_1\ORADATA\ORCLDW\EXAMPLE01.DBF'
CHARACTER SET ZHS16GBK
;
執(zhí)行上面這段語句,這個(gè)語句重建控制文件,然后你可以看著f:\aa文件完成下面的恢復(fù)工作了,
8.SQL>RECOVER DATABASE (恢復(fù)指定表空間、數(shù)據(jù)文件或整個(gè)數(shù)據(jù)庫(kù))
9.SQL>ALTER DATABASE OPEN 打開數(shù)據(jù)庫(kù)
本文來自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/rein07/archive/2010/11/25/6033937.aspx
引用
trailblizer 的 Oracle:Rank,Dense_Rank,Row_Number比較
Oracle:Rank,Dense_Rank,Row_Number比較
一個(gè)員工信息表
Create Table EmployeeInfo (CODE Number(3) Not Null,EmployeeName varchar2(15),DepartmentID Number(3),Salary NUMBER(7,2),
Constraint PK_EmployeeInfo Primary Key (CODE));
Select * From EMPLOYEEINFO

現(xiàn)執(zhí)行SQL語句:
Select EMPLOYEENAME,SALARY,
RANK() OVER (Order By SALARY Desc) "RANK",
DENSE_RANK() OVER (Order By SALARY Desc ) "DENSE_RANK",
ROW_NUMBER() OVER(Order By SALARY Desc) "ROW_NUMBER"
From EMPLOYEEINFO
結(jié)果如下:

Rank,Dense_rank,Row_number函數(shù)為每條記錄產(chǎn)生一個(gè)從1開始至N的自然數(shù),N的值可能小于等于記錄的總數(shù)。這3個(gè)函數(shù)的唯一區(qū)別在于當(dāng)碰到相同數(shù)據(jù)時(shí)的排名策略。
①ROW_NUMBER:
Row_number函數(shù)返回一個(gè)唯一的值,當(dāng)碰到相同數(shù)據(jù)時(shí),排名按照記錄集中記錄的順序依次遞增。
②DENSE_RANK:
Dense_rank函數(shù)返回一個(gè)唯一的值,除非當(dāng)碰到相同數(shù)據(jù)時(shí),此時(shí)所有相同數(shù)據(jù)的排名都是一樣的。
③RANK:
Rank函數(shù)返回一個(gè)唯一的值,除非遇到相同的數(shù)據(jù)時(shí),此時(shí)所有相同數(shù)據(jù)的排名是一樣的,同時(shí)會(huì)在最后一條相同記錄和下一條不同記錄的排名之間空出排名。
同時(shí)也可以分組排序,也就是在Over從句內(nèi)加入Partition by groupField:
Select DEPARTMENTID,EMPLOYEENAME,SALARY,
RANK() OVER ( Partition By DEPARTMENTID Order By SALARY Desc) "RANK",
DENSE_RANK() OVER ( Partition By DEPARTMENTID Order By SALARY Desc ) "DENSE_RANK",
ROW_NUMBER() OVER( Partition By DEPARTMENTID Order By SALARY Desc) "ROW_NUMBER"
From EMPLOYEEINFO
結(jié)果如下:

現(xiàn)在如果插入一條工資為空的記錄,那么執(zhí)行上述語句,結(jié)果如下:

會(huì)發(fā)現(xiàn)空值的竟然排在了第一位,這顯然不是想要的結(jié)果。解決的辦法是在Over從句Order By后加上 NULLS Last即:
Select EMPLOYEENAME,SALARY,
RANK() OVER (Order By SALARY Desc Nulls Last) "RANK",
DENSE_RANK() OVER (Order By SALARY Desc Nulls Last) "DENSE_RANK",
ROW_NUMBER() OVER(Order By SALARY Desc Nulls Last ) "ROW_NUMBER"
From EMPLOYEEINFO
結(jié)果如下:

Oracle Sql Loader中文字符導(dǎo)入亂碼的解決方案
服務(wù)器端字符集NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
控制文件ctl:
LOAD DATA
CHARACTERSET ZHS16GBK
INFILE 'c:\testfile.txt'
id name desc
FIELDS TERMINATED BY ","
(id,name ,desc )
導(dǎo)入成功
其中c:\testfile.txt文件中有中文,在將此文件導(dǎo)入到oracle數(shù)據(jù)庫(kù)中時(shí),需要設(shè)置字符集CHARACTERSET ZHS16GBK
(1)查看服務(wù)器端字符集
通過客戶端或服務(wù)器端的sql*plus登錄ORACLE的一個(gè)合法用戶,執(zhí)行下列SQL語句:
SQL > select * from V$NLS_PARAMETERS
------------------------
(2)控制文件ctl:
LOAD DATA
CHARACTERSET ZHS16GBK
INFILE '/inffile/vac/subs-vac.csv'
TRUNCATE
INTO TABLE INF_VAC_SUBS_PRODUCT
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
TRAILING NULLCOLS
(
USER_NUMBER,
PRODUCT_ID,
EFFECTIVE_DATE DATE "YYYY/MM/DD HH24:MI:SS",
EXPIRATION_DATE DATE "YYYY/MM/DD HH24:MI:SS"
)
文章分類:數(shù)據(jù)庫(kù)
要測(cè)試sql loader 以及快速產(chǎn)生大量測(cè)試數(shù)據(jù)
生成大量測(cè)試數(shù)據(jù)思路。
一,用plsql developer 生成csv 文件
二,用>>輸出重定向,追加到一個(gè)cvs 文件里。
三,再用sql loader 快速載入。
在plsql developer 執(zhí)行
- SELECT object_id,object_name FROM dba_objects;
SELECT object_id,object_name FROM dba_objects;
右鍵plsql developer 導(dǎo)出csv 格式 1.csv。在linux 上執(zhí)行下面的腳本
- #!/bin/bash
-
- for((i=1;i<200;i=i+1))
- do
- cat 1.csv >> 2.csv;
- echo $i;
- done
#!/bin/bash
for((i=1;i<200;i=i+1))
do
cat 1.csv >> 2.csv;
echo $i;
done
這樣 50000 * 200 差不到就有一千萬的數(shù)據(jù)了。我測(cè)試的 11047500 392M
可以用:
wc -l 2.csv
查看csv 里有多少條數(shù)據(jù)。現(xiàn)在測(cè)試數(shù)據(jù)有了。我們來試一下sql loader 的載入效果吧。
創(chuàng)建sqlloader 控制文件如下,保存為1.ctl
- load data
- infile '2.csv'
- into table my_objects
- fields terminated by ','optionally enclosed by '"'
- (object_id,
- object_name
- );
load data
infile '2.csv'
into table my_objects
fields terminated by ','optionally enclosed by '"'
(object_id,
object_name
);
控制文件簡(jiǎn)要說明:
-- INFILE 'n.csv' 導(dǎo)入多個(gè)文件
-- INFILE * 要導(dǎo)入的內(nèi)容就在control文件里 下面的BEGINDATA后面就是導(dǎo)入的內(nèi)容
--BADFILE '1.bad' 指定壞文件地址
--apend into table my_objects 追加
-- INSERT 裝載空表 如果原先的表有數(shù)據(jù) sqlloader會(huì)停止 默認(rèn)值
-- REPLACE 原先的表有數(shù)據(jù) 原先的數(shù)據(jù)會(huì)全部刪除
-- TRUNCATE 指定的內(nèi)容和replace的相同 會(huì)用truncate語句刪除現(xiàn)存數(shù)據(jù)
--可以指定位置加載
--(object_id position(1:3) char,object_name position(5:7) char)
--分別指定分隔符
--(object_id char terminated by ",", object_name char terminated by ",")
--執(zhí)行sqlldr userid=scott/a123 control=1.ctl log=1.out direct=true
--30秒可以載入200萬的測(cè)試數(shù)據(jù) 79MB
--sqlldr userid=/ control=result1.ctl direct=true parallel=true
--sqlldr userid=/ control=result2.ctl direct=true parallel=true
--sqlldr userid=/ control=result2.ctl direct=true parallel=true
--當(dāng)加載大量數(shù)據(jù)時(shí)(大約超過10GB),最好抑制日志的產(chǎn)生:
--SQLALTER TABLE RESULTXT nologging;
--這樣不產(chǎn)生REDO LOG,可以提高效率。然后在CONTROL文件中l(wèi)oad data上面加一行:unrecoverable
--此選項(xiàng)必須要與DIRECT共同應(yīng)用。
--在并發(fā)操作時(shí),ORACLE聲稱可以達(dá)到每小時(shí)處理100GB數(shù)據(jù)的能力!其實(shí),估計(jì)能到1-10G就算不錯(cuò)了,開始可用結(jié)構(gòu)
--相同的文件,但只有少量數(shù)據(jù),成功后開始加載大量數(shù)據(jù),這樣可以避免時(shí)間的浪費(fèi)
下面就是執(zhí)行了
- sqlldr userid=scott/a123 control=1.ctl log=1.out direct=true
sqlldr userid=scott/a123 control=1.ctl log=1.out direct=true
結(jié)果:30秒可以載入200萬的測(cè)試數(shù)據(jù) 79MB
226秒載入1100萬的測(cè)試數(shù)據(jù) 392Mb
我的環(huán)境是在虛擬機(jī),測(cè)得的結(jié)果
MemTotal: 949948 kB
model name : Intel(R) Pentium(R) D CPU 2.80GHz
stepping : 8
cpu MHz : 2799.560
cache size : 1024 KB
還是挺快的:)