Apache配置虚拟主机
本文转自 http://www.ideagrace.com/html/doc/2005/10/27/00686.html
| |||||
©2005 Idea Grace |
本文转自 http://www.ideagrace.com/html/doc/2005/10/27/00686.html
| |||||
©2005 Idea Grace |
Posted by
马面祭司
at
11:59 PM
0
comments
其实Delphi为了速度的原因,对于接口是采用直接解析接口在实例中的偏移来得到的.这个可以从下面的代码中看到:
var
mInt: ITestInterface;
mInt2: ITestInterface2;
begin
mInt := TTestInterface2.Create;
mInt2 := TTestInterface2.Create;
end;
其中 mInt := TTestInterface2.Create 代码为:
mov dl, $01
mov eax, [$00452e4]
call TObject.Create
mov edx, eax
jz +$03
sub edx, -$0C
lea eax, [ebp-$04]
call @IntfCopy
而 mInt2 := TTestInterface2.Create 代码为:
mov dl, $01
mov eax, [$00452e4]
call TObject.Create
mov edx, eax
jz +$03
sub edx, -$0C
lea eax, [ebp-$08]
call @IntfCopy
但对于接口之间的转化时, CSDN的halfdream(哈欠) 兄说的很对, Delphi在call @IntfCast里调用了@QueryInterface, 而这里面的代码, 其实是在System的TObject对象的GetInterface这个方法中, 但这个方法有个问题, 它需要GUID, 但我们实际可以在Delphi中使用无GUID的接口, 那么就会发现, 根本无法进行转化
比如:
INoGUIDInterface = interface
procedure NoGUID;
end;
INoGUIDInterface2 = interface
procedure NoGUID2;
end;
var
mInt: INoGUIDInterface;
mInt2: INoGUIDInterface2;
begin
mInt := TTestNoGUIDInterface2.Create;
mInt.NoGUID;
mInt2 := mInt as INoGUIDInterface2;
mInt2.NoGUID2;
end;
编译就会出错了, Operator not applicable to this operand type 根本就不支持. 所以表明接口时还是随手加上GUID的比较好
Posted by
马面祭司
at
2:37 AM
0
comments
今天在发现delphi里的接口是不能强制转化的, 比如如下代码:
ITestInterface = interface(IUnknown)
['{DE8E7E63-BD1B-4BD8-B59A-43F4B2B3A3DC}']
procedure Chk;
end;
ITestInterface2 = interface(IUnknown)
['{3B47B113-4664-4CCC-9A69-E378F2D2363E}']
procedure Chk2;
end;
var
mInt: ITestInterface;
mInt2: ITestInterface2;
begin
mInt := TTestInterface2.Create;
mInt.Chk;
ITestInterface2(mInt).Chk2;
mInt2 := mInt as ITestInterface2;
mInt2.Chk2;
end;
从运行情况可以看出,在第一种情况 ITestInterface2(mInt).Chk2; 下,实际运行的还是ITestInterface下的procedure Chk;而第二种情况 mInt2 := mInt as ITestInterface2; 就能正确的运行ITestInterface2下的procedure Chk2;了.这是为什么呢?
原来这都出自Delphi的编译之手,在进行强制转化 ITestInterface2(mInt).Chk2; 时, 代码是:
mov eax, [ebp-$04]
mov edx, [eax]
call dword ptr [edx+$0c]
而进行 mInt.Chk; 调用时的代码也是这个,这说明强制转化时,编译器根本就没有把ITestInterface转化为ITestInterface2,而是理解为直接的对象强制转化,然后希望能在方法表里找到对应的方法,而且在对接口进行方法的解析时,也只是以方法的声明顺序,而不是实际的方法名来进行解析.所以在Chk为ITestInterface的第一个方法,而Chk2也为ITestInterface2的第一个方法时,就会直接的调用了ITestInterface的Chk,而不是ITestInterface2的Chk2.这个结论也可能通过下面这个实验来表明.
ITestInterface = interface(IUnknown)
['{DE8E7E63-BD1B-4BD8-B59A-43F4B2B3A3DC}']
procedure Chk;
end;
ITestInterface2 = interface(IUnknown)
['{3B47B113-4664-4CCC-9A69-E378F2D2363E}']
procedure Chk2;
procedure Chk22;
end;
var
mInt: ITestInterface;
mInt2: ITestInterface2;
begin
mInt := TTestInterface2.Create;
mInt.Chk;
ITestInterface2(mInt).Chk22;
mInt2 := mInt as ITestInterface2;
mInt2.Chk2;
end;
在这种情况下,就会报地址出错,那是因为ITestInterface根本就没有第二个方法.当然下面的代码也能说明问题
ITestInterface = interface(IUnknown)
['{DE8E7E63-BD1B-4BD8-B59A-43F4B2B3A3DC}']
procedure Chk;
procedure Chk1;
end;
ITestInterface2 = interface(IUnknown)
['{3B47B113-4664-4CCC-9A69-E378F2D2363E}']
procedure Chk2;
procedure Chk22;
end;
var
mInt: ITestInterface;
mInt2: ITestInterface2;
begin
mInt := TTestInterface2.Create;
mInt.Chk;
ITestInterface2(mInt).Chk22;
mInt2 := mInt as ITestInterface2;
mInt2.Chk2;
end;
在这种情况下,程序会调用ITestInterface的Chk1方法.
好上面说了强制转化时发生的情况,下面说用as来转化时发生的情况.
当用as来转化时,代码就变为:
lea eax, [ebp-$08]
mov edx, [ebp-$04]
mov ecx, $00452bc4
call @IntfCast
mov eax, [ebp-$08]
mov edx, [eax]
call dword prt [edx+$0c]
发现,在用as标志转化后,就会使编译器知道要在类实例中查找实际的接口ITestInterface2而不是用mInt所声明的ITestInteface.
以上说明Delphi7的编译器对接口的支持还是不够好,造成在强制转化时,不能正确的识别出要求的接口类型来.
Posted by
马面祭司
at
2:00 AM
0
comments
在这本书中, Part1的Enhancing the code的Code Retention一节中指出如果把
.class public explicit CharArray8 extends [mscorlib]System.ValueType { .size 8 }
这句放在
.field public static valuetype CharArray8 Format at FormatData
之前, 但在Even类之后的话,编译会出错, 但经过实际编译发现,这样子也是没有问题的, 看来要不是书上写错了,要不就是微软改进了它的编译器.
Posted by
马面祭司
at
8:19 AM
0
comments
Emacs for Windows: http://learn.tsinghua.edu.cn:8080/2002315162/index.html
这个网站上有emacs的windows版本, 直接就是可执行文件,而不用自己再去编译了.
Emacs 中文化指南: http://man.chinaunix.net/newsoft/Emac/book.html
这个网站实在是好,站长同学把他使用emacs的经验都写在上面了.很多东东都是可以直接复制来用.
emacs在windows上使用时,它没有建立一个缺省的.emacs配置文件,可以直接在emacs上使用~/.emacs来建立配置文件.
下面这个代码可以最大化emacs
(w32-send-sys-command 61488)
Posted by
马面祭司
at
10:23 PM
0
comments
所有的程序都有标准输入,标准输出,标准错误这三个管道存在, 所以我们想得到控制台程序的输出,可以通过重定向这些管道来实现.
首先, 我们要建立一个管道作为控制台程序的标准输出管道, 因为这个管道要转给控制台程序使用, 所以它应该是可以被控制台程序继承的句柄.
ZeroMemory(@mSa, SizeOf(mSa));
mSa.nLength := SizeOf(mSa);
mSa.bInheritHandle := True; //设定为可以为子进程继承的句柄
mSa.lpSecurityDescriptor := nil;
if not CreatePipe(mOutRd, mOutWr, @mSa, 0) then raise Exception.Create('建立管道出错');
第二步, 复制读管道的句柄, 因为读管道的句柄在建立时是一个可继承句柄, 它可能会被子进程使用, 那样会造成信息的丢失与父进程的堵塞, 所以我们要复制成一个不可以继承句柄, 并且它实际上在子进程中是没有用的, 所以我们在复制成功后要关闭它.
if not DuplicateHandle(GetCurrentProcess, mOutRd, GetCurrentProcess,
@mOutRdDup, 0, False, DUPLICATE_SAME_ACCESS) then
raise Exception.Create('复制读句柄出错');
CloseHandle(mOutRd);
第三步, 我们要建立控制台子进程了
ZeroMemory(@mStartupInfo, SizeOf(mStartupInfo));
mStartupInfo.cb := SizeOf(mStartupInfo);
mStartupInfo.dwFlags := mStartupInfo.dwFlags or STARTF_USESTDHANDLES; //将标准输出重定向
mStartupInfo.hStdOutput := mOutWr;
mStartupInfo.hStdError := mOutWr;
ZeroMemory(@mProcess, SizeOf(mProcess));
if not CreateProcess(nil, cmdLine,nil, nil, True, 0, nil, WorkDir, mStartupInfo,mProcess) then
raise Exception.Create('启动程序出错');
CloseHandle(mProcess.hProcess);
CloseHandle(mProcess.hThread);
第四步, 关闭写句柄, 要不然当子进程关闭了自己后, 会因为写句柄还被父进程所打开, 而使下面的ReadFile无法得知管道已结束, 从而堵塞.
if not CloseHandle(mOutWr) then
raise Exception.Create('标准输出句柄关闭出错');
while ReadFile(mOutRdDup, mBuff, 256, mRealRead, nil) do begin
if mRealRead = 0 then Break;
//作点自己爱作的事情吧
end;
完整的代码如下:
var
mRealRead: DWORD;
mOutRd, mOutWr, mOutRdDup: THandle;
mSa: TSecurityAttributes;
mProcess: TProcessInformation;
mStartupInfo: TStartupInfo;
mBuff: array[0..255] of Char;
begin
ZeroMemory(@mSa, SizeOf(mSa));
mSa.nLength := SizeOf(mSa);
mSa.bInheritHandle := True;
mSa.lpSecurityDescriptor := nil;
if not CreatePipe(mOutRd, mOutWr, @mSa, 0) then raise Exception.Create('建立管道出错');
if not DuplicateHandle(GetCurrentProcess, mOutRd, GetCurrentProcess,
@mOutRdDup, 0, False, DUPLICATE_SAME_ACCESS) then
raise Exception.Create('复制读句柄出错');
CloseHandle(mOutRd);
ZeroMemory(@mStartupInfo, SizeOf(mStartupInfo));
mStartupInfo.cb := SizeOf(mStartupInfo);
mStartupInfo.dwFlags := mStartupInfo.dwFlags or STARTF_USESTDHANDLES;
mStartupInfo.hStdOutput := mOutWr;
mStartupInfo.hStdError := mOutWr;
mStartupInfo.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
ZeroMemory(@mProcess, SizeOf(mProcess));
if not CreateProcess(nil, cmdLine,nil, nil, True, 0, nil, WorkDir, mStartupInfo,mProcess) then raise Exception.Create('启动程序出错');
CloseHandle(mProcess.hProcess);
CloseHandle(mProcess.hThread);
if not CloseHandle(mOutWr) then
raise Exception.Create('标准输出句柄关闭出错');
while ReadFile(mOutRdDup, mBuff, 256, mRealRead, nil) do begin
if mRealRead = 0 then Break;
mmo1.Lines.Add(mBuff);
Application.ProcessMessages;
end;
Posted by
马面祭司
at
8:09 PM
0
comments
修改文件版本号, 其实就是修改文件的资源. MSDN上没有明说如何修改文件的版本号的方法, 因为MS认为版本号应该是属于文件创建者的, 而不是如我们这样的文件所有者应该去修改的. 但资源总是资源, MS提供了如何修改资源的函数, 当然这些函数也可以修改版本号.
首先, 我们要找到文件的版本信息资源:
mSize := GetFileVersionInfoSize('FileName.exe');
SetLength(mVersion, mSize);
GetFileVersionInfo('FileName.exe', mRes, mSize, mVersion);
这个代码能让我们得到文件的版本信息资源, 得到的结果就放在mVersion中, 其实这个就是一串的二进制形的资源内存块.
第二步, 我们要找到文件的版本信息:
VerQueryValue(mVersion, '\', mFixV, mLen);
mFixVersion1 := PVSFixedFileInfo(mFixV);
这一步能让我们得到mFixVersionInfo, 它是mVersion这个资源内存块中指向文件的版本信息的那一部分的指针.
第三步, 修改文件的版本信息:
mFixVersion^.dwFileVersionMS := $10001; //高位低位都为1
mFixVersion^.dwFileVersionLS := 26 shl 16 + 26; //高位低位都为26
这两步演示了如何修改文件的版本号, dwFileVersionMS的高位是Major Version, 低位是Minor Version, dwFileVersionLS的高位是Release Version, 低位是Build Version.
第四步, 保存修改的内容, 下面就可以参考MSDN上的UpdateResource部分的例子了, 因为都是资源嘛:
mHExe := BeginUpdateResource('FileName.Exe', False);
if VerQueryValue(mVersion, '\VarFileInfo\Translation', mTranslate, mLen) then begin
//这步是因为基本都是单区域资源的, 如果是多区域的, 可以参考MSDN中的作法,
//将mTranslate/sizeof(LANGANDCODEPAGE)来得到第一个
mLang := PLANGANDCODEPAGE(mTranslate);
if UpdateResource(mHExe, RT_VERSION, MakeIntResource(1), mLang^.wLanguage, mVersion, mSize) then
EndUpdateResource(mHExe, False);
FreeLibrary(mHExe);
这样, 我们就修改了文件的版本号了, 可以类推出如何修改版本资源中的其它资源.
完整的代码如下
type
PLANGANDCODEPAGE = ^LANGANDCODEPAGE;
LANGANDCODEPAGE = record
wLanguage: Word;
wCodePage: Word;
end;
var
mSize: Integer;
mLen, mLen1: UINT;
mTranslate, mFixV: Pointer;
mHExe, mRes: THandle;
mVersion: array of Byte;
mFixVersion: VS_FIXEDFILEINFO;
mFixVersion1: PVSFixedFileInfo;
mLang: PLANGANDCODEPAGE;
begin
mSize := GetFileVersionInfoSize('FileName.exe', mRes);
SetLength(mVersion, mSize);
GetFileVersionInfo('FileName.exe', mRes, mSize, mVersion);
VerQueryValue(mVersion, '\', mFixV, mLen);
mFixVersion1 := PVSFixedFileInfo(mFixV);
mFixVersion1^.dwFileVersionMS := $10001;
mFixVersion1^.dwFileVersionLS := 26 shl 16 + 26;
mHExe := BeginUpdateResource('FileName.exe', False);
if VerQueryValue(mVersion, '\VarFileInfo\Translation', mTranslate, mLen) then begin
mLang := PLANGANDCODEPAGE(mTranslate);
if UpdateResource(mHExe, RT_VERSION, MakeIntResource(1), mLang^.wLanguage, mVersion, mSize) then
EndUpdateResource(mHExe, False);
end
FreeLibrary(mHExe);
Posted by
马面祭司
at
11:27 PM
0
comments
关于pl/sql中的instr函数, 当要查找的字符串或被查找的字符串为NULL时, 返回的值也是NULL.
Posted by
马面祭司
at
1:35 AM
0
comments
以下是自定义聚集函数的代码例子, 抄自http://yangtingkun.itpub.net/post/468/3380
SQL> CREATE OR REPLACE TYPE T_LINK AS OBJECT (
2 STR VARCHAR2(30000),
3 STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT T_LINK) RETURN NUMBER,
4 MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT T_LINK, VALUE IN VARCHAR2) RETURN NUMBER,
5 MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN T_LINK, RETURNVALUE OUT VARCHAR2, FLAGS IN NUMBE
R) RETURN NUMBER,
6 MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT T_LINK, CTX2 IN T_LINK) RETURN NUMBER
7 )
8 /
SQL> CREATE OR REPLACE TYPE BODY T_LINK IS
2 STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT T_LINK) RETURN NUMBER IS
3 BEGIN
4 SCTX := T_LINK(NULL);
5 RETURN ODCICONST.SUCCESS;
6 END;
7
8 MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT T_LINK, VALUE IN VARCHAR2) RETURN NUMBER IS
9 BEGIN
10 SELF.STR := SELF.STR || VALUE;
11 RETURN ODCICONST.SUCCESS;
12 END;
13
14 MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN T_LINK, RETURNVALUE OUT VARCHAR2, FLAGS IN NUMBE
R) RETURN NUMBER IS
15 BEGIN
16 RETURNVALUE := SELF.STR;
17 RETURN ODCICONST.SUCCESS;
18 END;
19
20 MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT T_LINK, CTX2 IN T_LINK) RETURN NUMBER IS
21 BEGIN
22 NULL;
23 RETURN ODCICONST.SUCCESS;
24 END;
25 END;
26 /
SQL> CREATE OR REPLACE FUNCTION F_LINK(P_STR VARCHAR2) RETURN VARCHAR2
2 AGGREGATE USING T_LINK;
3 /
Posted by
马面祭司
at
1:21 AM
0
comments
| Oracle8 SQL Reference Release 8.0 A58225-01 |
This appendix lists Oracle reserved words and keywords.
lists Oracle reserved words. Words followed by an asterisk (*) are also ANSI reserved words.
lists Oracle keywords. Keywords marked with asterisks (*) are also ANSI reserved words. For maximum portability to other implementations of SQL, do not use these words as schema object names.
| Copyright © 1997 Oracle Corporation. All Rights Reserved. |
Posted by
马面祭司
at
10:48 PM
0
comments
/*+ FULL(tablename) */: 明确的指定进行全表扫描
/*+ ROWID(tablename) */: 明确的选择根据rowid进行表扫描
/*+ CLUSTER(tablename) */: 明确的指定对指定表进行群集扫描, 只能应用于tablename的条件中有群集对象时
/*+ HASH(tablename) */: 明确的选择对指定表进行hash扫描, 只能应用于tablename的条件中有群集对象时
/*+ HASH_AJ */: 转化一个not in子查询为一个anti-join的hash扫描
/*+ HASH_SJ */: 转化一个EXISTS子查询为一个semi-join的hash扫描
/*+ INDEX(TABLENAME INDEXNAME) */: 明确的指定使用某个表的某个索引, 指定了这个优化参数, 优化器对这个表将不考虑进行全表扫描或用这个表的其它索引. 如果对表指定了多个索引, 那么优化器将会考查每一个索引的成本, 选择成本最小, 或者选择多个索引联合使用, 然后将结果再组合起来, 当这都建立在, 优化器认为这样作是成本最低的情况下. 如果没有指定索引, 优化器会考查表上每一个可以使用的索引.
/*+ INDEX_ASC(tablename indexname) */: 这个优化参数在缺省时与 INDEX 优化参数是一样的, 除非你的数据库中的索引扫描的缺省行为被改变了. 缺省行为是对索引进行正序扫描
/*+ INDEX_COMBINE(tablename indexname) */ : 如果不指定索引, 那么优化器将使用bitmap索引进行布尔组合, 而不管是不是成本最低的. 如果没有bitmap索引的话, 也会强制的转化一个索引为bitmap索引来进行布尔组合. 如果指定了索引,那也与上叙一样, 但会使用指定的索引.
/*+ INDEX_DESC(tablename indexname) */: 与 INDEX 优化参数一样, 不过将会以逆序进行索引扫描.
/*+ INDEX_FFS(tablename indexname) */: 会用索引快速扫描代替全表扫描.
/*+ MERGE_AJ */: 转化一个not in子查询为一个 merge anti-join 查询
/*+ MERGE_SJ */: 转化一个exists子查询为一个merge semi-join 查询
/*+ AND_EQUAL(tablename indexname indexname.....) */: 明确指定建立一种执行计划, 这个计划会把根据指定索引得到列进行组合. 这个优化参数必须指定至少二个索引, 但不能多于五个
/*+ USE_CONCAT */: 将where语句中的or运行转化为union all形的操作, 如果这个操作的成本比没有这个操作的成本低的话
/*+ ORDERED */: 指定oracle根据from后面表的顺序进行join操作
/*+ STAR */: 指定实行star plan, star plan将最大的表放在join操作的最后, 并进行nested loops join. 这个优化参数所用的语句,必须至少有三个表
/*+ USE_NL(TABLENAME) */: 在很多情况下 nested loops join比sort-merge join要快的返回第一行记录, 造成更快的反应速度,这个参数就是指定表要进行 nested loops join, 而不是sort-merge join
/*+ USE_MERGE(TABLENAME) */: 指定表要进行sort-merge join
/*+ USE_HASH(TABLENAME) */: 指定表进行hash join
/*+ DRIVING_SITE(TABLENAME) */: 指定表是在其它服务器上的
Posted by
马面祭司
at
12:58 AM
0
comments
有时候执行计划一直不是你想要的, 但oracle又一直用这样的执行计划, 那么可能是因为oracle中对表的成本统计数据太旧了. 这时, 可以运行 analyze table 表名 compute statistics 来对表的成本统计数据进行刷新.
Posted by
马面祭司
at
11:43 PM
0
comments
Performs a memory sort on a row source
This operation was introduced in Oracle 9.0.1 though it may have been used in limited circumstances in some earlier versions
This operation is implemented in the following versions
|
This example was developed using Oracle 9.2.0.1 on Windows 2000
This example requires the following table and index definitions
CREATE TABLE t1 (c1 NUMBER);
CREATE INDEX T1_C1 ON T1(C1);
At least one of the tables must be analysed
ANALYZE TABLE t1 COMPUTE STATISTICS;
The statement
SELECT t1.c01, t2.c01
FROM t1;
generates the following execution plan
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 MERGE JOIN (CARTESIAN)
2 1 TABLE ACCESS (FULL) OF 'T1'
3 1 BUFFER (SORT)
4 3 TABLE ACCESS (FULL) OF 'T2'
This example was developed using Oracle 9.2.0.1 on Windows 2000
This example requires the following table and index definitions
CREATE TABLE t1 (c1 NUMBER,c2 NUMBER);
In Oracle 9.0.1 and above the statement
SELECT c1,c2 FROM t1
CONNECT BY c1 = PRIOR c2
START WITH c1 = 0;
generates the following execution plan
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 CONNECT BY (WITH FILTERING)
2 1 NESTED LOOPS
3 2 TABLE ACCESS (FULL) OF 'T1'
4 2 TABLE ACCESS (BY USER ROWID) OF 'T1'
5 1 NESTED LOOPS
6 5 BUFFER (SORT)
7 6 CONNECT BY PUMP
8 5 TABLE ACCESS (FULL) OF 'T1'
Posted by
马面祭司
at
10:46 PM
0
comments
当对视图进行update时, 会出现ora-01779错误, 这个错误是因为要修改的字段在视图中不能保证物理上唯一,多出现在与多表关联时, 一个表因与另一个表的关联, 原表中的字段产生了多条记录的原故. 具体可以见 http://forums.oracle.com/forums/message.jspa?messageID=1266445
下面是其中一个回帖:
For a table to be key preserved in a view, the primary key of that table, if it were present in the view, ciould serve as a primary key of the view.
In your case, m.id cannot be a PK of the view because there could be more than one row in c pointing to the same row in m. Table c is key preserved (thus updateable) in the inner join version because each row of c can only appear once in the view.
Posted by
马面祭司
at
12:37 AM
0
comments
前些天, 在工作中遇到要从管道的名称中的解析出管道所在的路进行统计的问题. 系统中, 管道的名称基本都以"XX路-XX路"输入, "XX路"就是管道所在的道路名. 麻烦的是根据管道的结点, 名称里还加入了"XX路1-XX路1"或"XX路001#-XX路001#"之类的无关符号. 如果都要一个个进行解析, 那只能疯掉, 还好Oracle提供了一个批量的函数TRANSLATE. 这个函数就是把一个字符串中某些指定的字符用另一些字符来代替, 于是, 只要写成 TRANSLATE(管道名称, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ#_''"+-', ' ') 就能把名称中基本含有的无关的字符全变成了空格了, 而且如果字符是连续的, 那也会合成为一个空格, 真是美妙啊. 下面是TRANSLATE函数的英文原帮助:
TRANSLATE
Syntax
TRANSLATE(char, from, to)
Purpose
Returns char with all occurrences of each character in from replaced by its corresponding character in to. Characters in char that are not in from are not replaced. The argument from can contain more characters than to. In this case, the extra characters at the end of from have no corresponding characters in to. If these extra characters appear in char, they are removed from the return value. You cannot use an empty string for to to remove all characters in from from the return value. Oracle interprets the empty string as null, and if this function has a null argument, it returns null.
Example 1
The following statement translates a license number. All letters 'ABC...Z' are translated to 'X' and all digits '012 . . . 9' are translated to '9':
SELECT TRANSLATE('2KRW229',
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'9999999999XXXXXXXXXXXXXXXXXXXXXXXXXX') "License"
FROM DUAL;
License
--------
9XXX999
Example 2
The following statement returns a license number with the characters removed and the digits remaining:
SELECT TRANSLATE('2KRW229',
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'0123456789')
"Translate example"
FROM DUAL;
Translate example
-----------------
2229
Posted by
马面祭司
at
11:38 PM
0
comments