星期日, 九月 10, 2006

oracle 942错误

Imp正常,但Exp却无法完成
==============================
前日晚上准备对刚刚启用的Unix环境Oracle数据库做一次Exp逻辑备份,报如下错误:
EXP-00056: ORACLE error 942 encountered
ORA-00942: table or view does not exist
EXP-00000: Export terminated unsuccessfully
感觉很奇怪,因为数据库中的数据就是通过Imp转移来的,怎么这里的Exp不能用了呢?上网搜了一下,发现这个问题还并不鲜见,找到一篇文章解 释为Oracle本身的一个bug,发生在从920升级到9206以后,因此建议在升级后用Exp命令来检验升级是否真正成功,但事已至此,我又检查了测 试环境和开发环境,发现都有这样的我问题,于是根据作者提供的方法,执行了/rdbms/admin/catpatch.sql脚本,然后手动编译了 sys schema下的所有package,再使用Exp命令导出数据就可以了,具体命令如下:
SQL>shutdown immediate;
SQL>startup migrate;
SQL>@?/rdbms/admin/catpatch.sql
SQL>shutdown immediate;
SQL>startup;

========================

XP-00056: 遇到 ORACLE 错误 942

ORA-00942: 表或视图不存在

EXP-00000: 导出终止失败

解决办法:报此错误并不是因为你的权限不够,也不是因为你的命令有误,而是ORACLE本身的问题,是由于你的客户端版本低于服务器端的版本造成的。最好的办法就是装一个与服务器端版本相同客户端。要不就到服务器端去导吧。


星期五, 九月 08, 2006

在Oracle中存取BLOB对象实现文件的上传和下载

最近做一个J2EE项目,需要在JSP页面实现对文件的上传和下载。很早以前就知道JDBC支持大对象(LOB)的存取,以为很容易,做起来才发现问题多多,读了一大堆文章,反而没有什么头绪了。正如一位网友文章所讲:“…网络上的教程99%都是行不通的,连SUN自己的文档都一直错误……”,实际情况大致如此了。

存取BLOB出现这么多问题,我认为大半是由数据库开发商、应用服务器商在JDBC驱动上的不兼容性带来的。而实际应用中,每个人的开发运行环境不同,使得某个网友的solution没有办法在别人的应用中重现,以至于骂声一片。至于为什么会不兼容、有哪些问题,我没有时间去弄清,这里只说说我们怎样解决了问题的。

基于上述原因,先列出我们的开发环境,免得有人配不出来,招人唾骂。

数据库 Oracle 9i

应用服务器 BEA Weblogic 8.11

开发工具 JBuilder X

在JSP实现文件Upload/Download可以分成这样几块 :文件提交到形成InputSteam;InputSteam以BLOB格式入库;数据从库中读出为InputSteam;InputStream输出到页面形成下载文件。先说BLOB吧。

1. BLOB入库

(1) 直接获得数据库连接的情况

这是Oracle提供的标准方式,先插入一个空BLOB对象,然后Update这个空对象。代码如下:

//得到数据库连接(驱动包是weblogic的,没有下载任何新版本)

Class.forName("oracle.jdbc.driver.OracleDriver");

Connection con = DriverManager.getConnection(

"jdbc:oracle:thin:@localhost:1521:testdb", "test", "test");

//处理事务

con.setAutoCommit(false);

Statement st = con.createStatement();

//插入一个空对象

st.executeUpdate("insert into BLOBIMG values(103,empty_blob())");

//用for update方式锁定数据行

ResultSet rs = st.executeQuery(

"select contents from BLOBIMG where id=103 for update");

if (rs.next()) {

//得到java.sql.Blob对象,然后Cast为oracle.sql.BLOB

oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob(1).;

//到数据库的输出流

OutputStream outStream = blob.getBinaryOutputStream();

//这里用一个文件模拟输入流

File file = new File("d:\\proxy.txt");

InputStream fin = new FileInputStream(file);

//将输入流写到输出流

byte[] b = new byte[blob.getBufferSize()];

int len = 0;

while ( (len = fin.read(b)) != -1) {

outStream.write(b, 0, len);

//blob.putBytes(1,b);

}







//依次关闭(注意顺序)

fin.close();

outStream.flush();

outStream.close();

con.commit();

con.close();

(2) 通过JNDI获得数据库连接

在Weblogic中配置到Oracle的JDBC Connection Pool和DataSource,绑定到Context中,假定绑定名为”orads”。

为了得到数据库连接,做一个连接工厂,主要代码如下:

Context context = new InitialContext();

ds = (DataSource) context.lookup("orads");

return ds.getConnection();

以下是BLOB写入数据库的代码:



Connection con = ConnectionFactory.getConnection();

con.setAutoCommit(false);

Statement st = con.createStatement();

st.executeUpdate("insert into BLOBIMG values(103,empty_blob())");

ResultSet rs = st.executeQuery(

"select contents from BLOBIMG where id=103 for update");

if (rs.next()) {

//上面代码不变

//这里不能用oracle.sql.BLOB,会报ClassCast 异常

weblogic.jdbc.vendor.oracle.OracleThinBlobblob = (weblogic.jdbc.vendor.oracle.OracleThinBlob) rs.getBlob(1);

//以后代码也不变

OutputStream outStream = blob.getBinaryOutputStream();

File file = new File("d:\\proxy.txt");

InputStream fin = new FileInputStream(file);

byte[] b = new byte[blob.getBufferSize()];

int len = 0;

while ( (len = fin.read(b)) != -1) {

outStream.write(b, 0, len);

}

fin.close();

outStream.flush();

outStream.close();

con.commit();

con.close();



2. BLOB出库

从数据库中读出BLOB数据没有上述由于连接池的不同带来的差异,只需要J2SE的标准类java.sql.Blob就可以取得输出流(注意区别java.sql.Blob和oracle.sql.BLOB)。代码如下:

Connection con = ConnectionFactory.getConnection();

con.setAutoCommit(false);

Statement st = con.createStatement();

//这里的SQL语句不再需要”for update”

ResultSet rs = st.executeQuery(

"select contents from BLOBIMG where id=103 ");

if (rs.next()) {

java.sql.Blob blob = rs.getBlob(1);



InputStream ins = blob.getBinaryStream();



//用文件模拟输出流

File file = new File("d:\\output.txt");

OutputStream fout = new FileOutputStream(file);

//下面将BLOB数据写入文件

byte[] b = new byte[1024];

int len = 0;

while ( (len = ins.read(b)) != -1) {

fout.write(b, 0, len);

}

//依次关闭

fout.close();

ins.close();

con.commit();

con.close();



3. 从JSP页面提交文件到数据库

(1) 提交页面的代码如下:

<form action="handle.jsp" enctype="multipart/form-data" method="post" >

<input type="hidden" name="id" value="103"/>

<input type="file" name="fileToUpload">

<input type="submit" value="Upload">

</form>



(2) 由于JSP没有提供文件上传的处理能力,只有使用第三方的开发包。网络上开源的包有很多,我们这里选择Apache Jakarta的FileUpload,在http://jakarta.apache.org/commons/fileupload/index.html 可以得到下载包和完整的API文档。法奥为adajspException

处理页面(handle.jsp)的代码如下

<%

boolean isMultipart = FileUpload.isMultipartContent(request);

if (isMultipart) {

// 建立一个新的Upload对象

DiskFileUpload upload = new DiskFileUpload();

// 设置上载文件的参数

//upload.setSizeThreshold(yourMaxMemorySize);

//upload.setSizeMax(yourMaxRequestSize);

String rootPath = getServletConfig().getServletContext().getRealPath("/") ;

upload.setRepositoryPath(rootPath+\\uploads);



// 分析request中的传来的文件流,返回Item的集合,

// 轮询Items,如果不是表单域,就是一个文件对象。

List items = upload.parseRequest(request);

Iterator iter = items.iterator();

while (iter.hasNext()) {

FileItem item = (FileItem) iter.next();

//如果是文件对象

if (!item.isFormField()) {







//如果是文本文件,可以直接显示

//out.println(item.getString());







//将上载的文件写到服务器的\WEB-INF\webstart\下,文件名为test.txt

//File uploadedFile = new File(rootPath+"\\uploads\\test.txt");

//item.write(uploadedFile);







//下面的代码是将文件入库(略):

//注意输入流的获取



InputStream uploadedStream = item.getInputStream();



}

//否则是普通表单

else{

out.println("FieldName: " + item.getFieldName()+"<br>");

out.println("Value: "+item.getString()+"<br>"); }

}

}

%>







4. 从数据库读取BLOB然后保存到客户端磁盘上

这段代码有点诡异,执行后将会弹出文件保存对话窗口,将BLOB数据读出保存到本地文件。全文列出如下:

<%@ page contentType="text/html; charset=GBK" import="java.io.*" import="java.sql.*" import="test.global.ConnectionFactory"%><%

Connection con = ConnectionFactory.getConnection();

con.setAutoCommit(false);

Statement st = con.createStatement();

ResultSet rs = st.executeQuery(

"select contents from BLOBIMG where id=103 ");

if (rs.next()) {

Blob blob = rs.getBlob(1);

InputStream ins = blob.getBinaryStream();

response.setContentType("application/unknown");

response.addHeader("Content-Disposition", "attachment; filename="+"output.txt");

OutputStream outStream = response.getOutputStream();

byte[] bytes = new byte[1024];

int len = 0;

while ((len=ins.read(bytes))!=-1) {

outStream.write(bytes,0,len);

}

ins.close();

outStream.close();

outStream = null;

con.commit();

con.close();

}

%>

注意,在<% … … %>之外,绝对不能有任何字符,空格或回车都不行,不然会导致outputStream出错,对非ASCII输出文件来说就是格式错误不可读。

在Oracle中存取BLOB对象实现文件的上传和下载_站长技术站 -

最近做一个J2EE项目,需要在JSP页面实现对文件的上传和下载。很早以前就知道JDBC支持大对象(LOB)的存取,以为很容易,做起来才发现问题多多,读了一大堆文章,反而没有什么头绪了。正如一位网友文章所讲:“…网络上的教程99%都是行不通的,连SUN自己的文档都一直错误……”,实际情况大致如此了。

存取BLOB出现这么多问题,我认为大半是由数据库开发商、应用服务器商在JDBC驱动上的不兼容性带来的。而实际应用中,每个人的开发运行环境不同,使得某个网友的solution没有办法在别人的应用中重现,以至于骂声一片。至于为什么会不兼容、有哪些问题,我没有时间去弄清,这里只说说我们怎样解决了问题的。

基于上述原因,先列出我们的开发环境,免得有人配不出来,招人唾骂。

数据库 Oracle 9i

应用服务器 BEA Weblogic 8.11

开发工具 JBuilder X

JSP实现文件Upload/Download可以分成这样几块 :文件提交到形成InputSteamInputSteamBLOB格式入库;数据从库中读出为InputSteamInputStream输出到页面形成下载文件。先说BLOB吧。

1. BLOB入库

(1) 直接获得数据库连接的情况

这是Oracle提供的标准方式,先插入一个空BLOB对象,然后Update这个空对象。代码如下:

//得到数据库连接(驱动包是weblogic的,没有下载任何新版本)

Class.forName("oracle.jdbc.driver.OracleDriver");

Connection con = DriverManager.getConnection(

"jdbc:oracle:thin:@localhost:1521:testdb", "test", "test");

//处理事务

con.setAutoCommit(false);

Statement st = con.createStatement();

//插入一个空对象

st.executeUpdate("insert into BLOBIMG values(103,empty_blob())");

//for update方式锁定数据行

ResultSet rs = st.executeQuery(

"select contents from BLOBIMG where id=103 for update");

if (rs.next()) {

//得到java.sql.Blob对象,然后Castoracle.sql.BLOB

oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob(1).;

//到数据库的输出流

OutputStream outStream = blob.getBinaryOutputStream();

//这里用一个文件模拟输入流

File file = new File("d:\\proxy.txt");

InputStream fin = new FileInputStream(file);

//将输入流写到输出流

byte[] b = new byte[blob.getBufferSize()];

int len = 0;

while ( (len = fin.read(b)) != -1) {

outStream.write(b, 0, len);

//blob.putBytes(1,b);

}

//依次关闭(注意顺序)

fin.close();

outStream.flush();

outStream.close();

con.commit();

con.close();

(2) 通过JNDI获得数据库连接

Weblogic中配置到OracleJDBC Connection PoolDataSource,绑定到Context中,假定绑定名为”orads”

为了得到数据库连接,做一个连接工厂,主要代码如下:

Context context = new InitialContext();

ds = (DataSource) context.lookup("orads");

return ds.getConnection();

以下是BLOB写入数据库的代码:

Connection con = ConnectionFactory.getConnection();

con.setAutoCommit(false);

Statement st = con.createStatement();

st.executeUpdate("insert into BLOBIMG values(103,empty_blob())");

ResultSet rs = st.executeQuery(

"select contents from BLOBIMG where id=103 for update");

if (rs.next()) {

//上面代码不变

//这里不能用oracle.sql.BLOB,会报ClassCast 异常

weblogic.jdbc.vendor.oracle.OracleThinBlobblob = (weblogic.jdbc.vendor.oracle.OracleThinBlob) rs.getBlob(1);

//以后代码也不变

OutputStream outStream = blob.getBinaryOutputStream();

File file = new File("d:\\proxy.txt");

InputStream fin = new FileInputStream(file);

byte[] b = new byte[blob.getBufferSize()];

int len = 0;

while ( (len = fin.read(b)) != -1) {

outStream.write(b, 0, len);

}

fin.close();

outStream.flush();

outStream.close();

con.commit();

con.close();

2. BLOB出库

从数据库中读出BLOB数据没有上述由于连接池的不同带来的差异,只需要J2SE的标准类java.sql.Blob就可以取得输出流(注意区别java.sql.Bloboracle.sql.BLOB)。代码如下:

Connection con = ConnectionFactory.getConnection();

con.setAutoCommit(false);

Statement st = con.createStatement();

//这里的SQL语句不再需要”for update”

ResultSet rs = st.executeQuery(

"select contents from BLOBIMG where id=103 ");

if (rs.next()) {

java.sql.Blob blob = rs.getBlob(1);

InputStream ins = blob.getBinaryStream();

//用文件模拟输出流

File file = new File("d:\\output.txt");

OutputStream fout = new FileOutputStream(file);

//下面将BLOB数据写入文件

byte[] b = new byte[1024];

int len = 0;

while ( (len = ins.read(b)) != -1) {

fout.write(b, 0, len);

}

//依次关闭

fout.close();

ins.close();

con.commit();

con.close();

3. JSP页面提交文件到数据库

(1) 提交页面的代码如下:

name="fileToUpload">

value="Upload">

(2) 由于JSP没有提供文件上传的处理能力,只有使用第三方的开发包。网络上开源的包有很多,我们这里选择Apache JakartaFileUpload,在http://jakarta.apache.org/commons/fileupload/index.html 可以得到下载包和完整的API文档。法奥为adajspException

处理页面(handle.jsp)的代码如下

<%

boolean isMultipart = FileUpload.isMultipartContent(request);

if (isMultipart) {

// 建立一个新的Upload对象

DiskFileUpload upload = new DiskFileUpload();

// 设置上载文件的参数

//upload.setSizeThreshold(yourMaxMemorySize);

//upload.setSizeMax(yourMaxRequestSize);

String rootPath = getServletConfig().getServletContext().getRealPath("/") ;

upload.setRepositoryPath(rootPath+\\uploads);

// 分析request中的传来的文件流,返回Item的集合,

// 轮询Items,如果不是表单域,就是一个文件对象。

List items = upload.parseRequest(request);

Iterator iter = items.iterator();

while (iter.hasNext()) {

FileItem item = (FileItem) iter.next();

//如果是文件对象

if (!item.isFormField()) {

//如果是文本文件,可以直接显示

//out.println(item.getString());

//将上载的文件写到服务器的\WEB-INF\webstart\下,文件名为test.txt

//File uploadedFile = new File(rootPath+"\\uploads\\test.txt");

//item.write(uploadedFile);

//下面的代码是将文件入库(略):

//注意输入流的获取

InputStream uploadedStream = item.getInputStream();

}

//否则是普通表单

else{

out.println("FieldName: " + item.getFieldName()+"
");

out.println("Value: "+item.getString()+"
");
}

}

}

%>

4. 从数据库读取BLOB然后保存到客户端磁盘上

这段代码有点诡异,执行后将会弹出文件保存对话窗口,将BLOB数据读出保存到本地文件。全文列出如下:

<%@ page contentType="text/html; charset=GBK" import="java.io.*" import="java.sql.*" import="test.global.ConnectionFactory"%><%

Connection con = ConnectionFactory.getConnection();

con.setAutoCommit(false);

Statement st = con.createStatement();

ResultSet rs = st.executeQuery(

"select contents from BLOBIMG where id=103 ");

if (rs.next()) {

Blob blob = rs.getBlob(1);

InputStream ins = blob.getBinaryStream();

response.setContentType("application/unknown");

response.addHeader("Content-Disposition", "attachment; filename="+"output.txt");

OutputStream outStream = response.getOutputStream();

byte[] bytes = new byte[1024];

int len = 0;

while ((len=ins.read(bytes))!=-1) {

outStream.write(bytes,0,len);

}

ins.close();

outStream.close();

outStream = null;

con.commit();

con.close();

}

%>

注意,在<% … … %>之外,绝对不能有任何字符,空格或回车都不行,不然会导致outputStream出错,对非ASCII输出文件来说就是格式错误不可读。



">
<$BlogItemTitle$>

动态SQL和PL/SQL的EXECUTE IMMEDIATE选项--ORACLE

EXECUTE IMMEDIATE代替了以前Oracle8i中DBMS_SQL package包.它解析并马上执行动态的SQL语句或非运行时创建的PL/SQL块.动态创建和执行SQL语句性能超前,EXECUTE IMMEDIATE的目标在于减小企业费用并获得较高的性能,较之以前它相当容易编码.尽管DBMS_SQL仍然可用,但是推荐使用EXECUTE IMMEDIATE,因为它获的收益在包之上。
  
  使用技巧
  
  1. EXECUTE IMMEDIATE将不会提交一个DML事务执行,应该显式提交
  如果通过EXECUTE IMMEDIATE处理DML命令,那么在完成以前需要显式提交或者作为EXECUTE IMMEDIATE自己的一部分. 如果通过EXECUTE IMMEDIATE处理DDL命令,它提交所有以前改变的数据
  
  2. 不支持返回多行的查询,这种交互将用临时表来存储记录(参照例子如下)或者用REF cursors.
  
  3. 当执行SQL语句时,不要用分号,当执行PL/SQL块时,在其尾部用分号.
  
  4. 在Oracle手册中,未详细覆盖这些功能。下面的例子展示了所有用到Execute immediate的可能方面.希望能给你带来方便.
  
  5. 对于Forms开发者,当在PL/SQL 8.0.6.3.版本中,Forms 6i不能使用此功能.
  
  EXECUTE IMMEDIATE用法例子
  
  1. 在PL/SQL运行DDL语句
  
   begin
   execute immediate 'set role all';
   end;
  
  2. 给动态语句传值(USING 子句)
  
   declare
   l_depnam varchar2(20) := 'testing';
   l_loc  varchar2(10) := 'Dubai';
   begin
   execute immediate 'insert into dept values (:1, :2, :3)'
    using 50, l_depnam, l_loc;
   commit;
   end;
  
  3. 从动态语句检索值(INTO子句)
  
   declare
   l_cnt  varchar2(20);
   begin
   execute immediate 'select count(1) from emp'
    into l_cnt;
   dbms_output.put_line(l_cnt);
   end;
  
  4. 动态调用例程.例程中用到的绑定变量参数必须指定参数类型.黓认为IN类型,其它类型必须显式指定
  
   declare
   l_routin  varchar2(100) := 'gen2161.get_rowcnt';
   l_tblnam  varchar2(20) := 'emp';
   l_cnt   number;
   l_status  varchar2(200);
   begin
   execute immediate 'begin ' || l_routin || '(:2, :3, :4); end;'
    using in l_tblnam, out l_cnt, in out l_status;
  
   if l_status != 'OK' then
     dbms_output.put_line('error');
   end if;
   end;
  
  5. 将返回值传递到PL/SQL记录类型;同样也可用%rowtype变量
  
   declare
   type empdtlrec is record (empno number(4),
                ename varchar2(20),
                deptno number(2));
   empdtl empdtlrec;
   begin
   execute immediate 'select empno, ename, deptno ' ||
            'from emp where empno = 7934'
    into empdtl;
   end;
  
  6. 传递并检索值.INTO子句用在USING子句前
  
   declare
   l_dept  pls_integer := 20;
   l_nam   varchar2(20);
   l_loc   varchar2(20);
   begin
   execute immediate 'select dname, loc from dept where deptno = :1'
    into l_nam, l_loc
    using l_dept ;
   end;
  
  7. 多行查询选项.对此选项用insert语句填充临时表,用临时表进行进一步的处理,也可以用REF cursors纠正此缺憾.
  
   declare
   l_sal  pls_integer := 2000;
   begin
   execute immediate 'insert into temp(empno, ename) ' ||
            '     select empno, ename from emp ' ||
            '     where sal > :1'
    using l_sal;
   commit;
   end;
  
  对于处理动态语句,EXECUTE IMMEDIATE比以前可能用到的更容易并且更高效.当意图执行动态语句时,适当地处理异常更加重要.应该关注于捕获所有可能的异常.

">
<$BlogItemTitle$>

Oracle自定义函数——f_henry_GetStringLength_

Oracle下的Length()函数不能区分中英文,只能得到字符数而不能得到字节数,很多时候插入string到字段中时总要先进行一次检查,防止 string长度超过了字段定义的长度,一般大家都是把这个检测放到应用程序中执行,用我写的这个小函数就可以实现在数据库服务器端对要插入的字段进行检 测。

create or replace function f_henry_GetStringLength(pv_String in varchar2) return integer is
Result integer;
i number;
begin
Result:=0;
if length(pv_String)=0 then
return(Result);
end if;
for i in 1 .. length(pv_String) loop
if ascii(substr(pv_String,i,1))<256 then
Result:=Result+1;
else
Result:=Result+2;
end if;
end loop;
return(Result);
end f_henry_GetStringLength;

/*************************以下是测试***************************/

SQL> select length('啊$@oii发大幅') from dual;

LENGTH('啊$@OII发大幅')
-----------------------
9

SQL> select f_henry_GetStringLength('啊$@oii发大幅') from dual;

F_HENRY_GETSTRINGLENGTH('啊$@O
------------------------------
13



">
<$BlogItemTitle$>

求在9i的存储过程中二维数组的完整例子及说明table ,varrry ,recor都行.

---------------------- 单维数组 ------------------------

DECLARE
TYPE emp_ssn_array IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;

best_employees emp_ssn_array;
worst_employees emp_ssn_array;

BEGIN
best_employees(1) := '123456';
best_employees(2) := '888888';

worst_employees(1) := '222222';
worst_employees(2) := '666666';

FOR i IN 1..best_employees.count LOOP
DBMS_OUTPUT.PUT_LINE('i=' ¦ ¦ i ¦ ¦ ', best_employees= ' ¦ ¦best_employees(i)
¦ ¦ ', worst_employees= ' ¦ ¦worst_employees(i));
END LOOP;

END;

---------------------- 多维数组 ------------------------
DECLARE

TYPE emp_type IS RECORD
( emp_id number,
emp_name string(80),
emp_gender string(80));

TYPE emp_type_array IS TABLE OF
emp_type INDEX BY BINARY_INTEGER;

emp_rec_array emp_type_array;
emp_rec emp_type;

BEGIN
emp_rec.emp_id := 300000000;
emp_rec.emp_name := 'Barbara';
emp_rec.emp_gender := 'Female';

emp_rec_array(1) := emp_rec;

emp_rec.emp_id := 300000008;
emp_rec.emp_name := 'Rick';
emp_rec.emp_gender := 'Male';

emp_rec_array(2) := emp_rec;

FOR i IN 1..emp_rec_array.count LOOP
DBMS_OUTPUT.PUT_LINE('i=' ¦ ¦i
¦ ¦', emp_id =' ¦ ¦emp_rec_array(i).emp_id
¦ ¦', emp_name =' ¦ ¦emp_rec_array(i).emp_name
¦ ¦', emp_gender = ' ¦ ¦emp_rec_array(i).emp_gender);
END LOOP;

END;
-------------- Result --------------
i=1, emp_id =300000000, emp_name =Barbara, emp_gender = Female
i=2, emp_id =300000008, emp_name =Rick, emp_gender = Male

">
<$BlogItemTitle$>

oracle错误信息大全

ORACLE的这类错误在ORALCE的文档中有详细说明,但原因及措施说明不详细,本文当着重说明如何解决这类错误。

  1、ORA-12571、ORA-03113、ORA-03114、ORA-01041

  特征:客户端(代理或应用服务器)有时报这类断连错误

  原因:如果偶尔出现一次,则可能为网络原因或用户异常中止,如果经常出现则为客户端与服务端的字符集不一致。

  措施:如果偶尔出现,可在服务端的协议配置文件PROTOCOL.ORA中增加一行

  TCP.NODELAY=YES;

  如果经常出现,则为客户端与服务端字符集不一致或网络原因。

  客户端的字符集在注册表里定义:    HKEY__LOCAL__MACHINE/SOFTWARE/ORACLE/NLS__LANG

  在客户端注册表中的TCP参数项中设置   TCPMAXDATARETRANSMITIONS=20。

  2、ORA-01000

  特征:达到会话允许的最大游标

  原因:达到会话允许的最大游标数

  措施:有两种解决方法:

  (1)在初始化文件INIT.ORA文件中增加OPEN_CURSORS的数量,一般要求大于200。

  (2)在应用级,与开发工具有关,例如设置MAXOPEN_CURSORS等。

  3、ORA-01545

  特征:某个回滚段不可用

  原因:(1)当使回滚段ONLINE时,但回滚段不可用,例如回滚段所在表空间OFFLINE;

  (2) 当使回滚段ONLINE时,但回滚段已ONLINE,例如回滚段被使用两次,典型的案例如OPS方式时,回滚段不能公有;

  (3)删除回滚段时,回滚段中有活动的事务;

  措施:(1)确保回滚段可

  (2)从初始化文件INIT.ORA的参数ROLLBACK)SEGMENTS中删除指定的回滚段。

  (3)可以将回滚段所在表空间删除,取消UNDO事务

  4、ORA-0165x

  特征:表空间没有足够的空间供分配

  原因:表空间已满;存储参数不合理,NEXT太小;没有连续的区间

  措施:如果表空间已满,则需为表空间增加文件;如果存储参数不合理,则需增加INITIAL和NEXT;如果没有连续的区间,需要合并空闲的表空间。

  查看空间碎片用DBA_FREE_SPACE

  5、ORA-01555

  特征:当前会话无法读到以前版本的数据

  原因:原因很多,主要原因有下列:回滚段太小、太少;回滚段冲突;交叉提交(FETCH_ACROSS)

  措施:增加回滚段数量;

  6、ORA-04031

  特征:共享池内存区内存不够,或产生内存碎片

  原因:当试图装载一个大包时或执行一个较大的存储过程时,而共享池没有连续的内存空间。

  措施:如果是内存不够,则增加SHARE)POOL_SIZE;

  如果是内存碎片,执行alter system flush share_pool

  7、ORA-04091

  特征:触发器工作不正常

  原因:一个行触发读取或修改变化的表(正在修改、插入)时,产生这种错误。

  措施:检查触发器脚本,保证引用完整性

  8、ORA-01242、ORA-01113

  特征:介质故障导致数据库宕机

  原因:介质故障。

  措施:检查硬件故障;修改dbshut脚本,将其中的STARTUP命令修改为:

  Startup open recover

  Alter database open



">
<$BlogItemTitle$>

ORACLE函数大全

SQL中的单记录函数
1.ASCII
返回与指定的字符对应的十进制数;
SQL> select ascii('A') A,ascii('a') a,ascii('0') zero,ascii(' ') space from dual;

A A ZERO SPACE
--------- --------- --------- ---------
65 97 48 32


2.CHR
给出整数,返回对应的字符;
SQL> select chr(54740) zhao,chr(65) chr65 from dual;

ZH C
-- -
赵 A

3.CONCAT
连接两个字符串;
SQL> select concat('010-','88888888')||'转23' 高乾竞电话 from dual;

高乾竞电话
----------------
010-88888888转23

4.INITCAP
返回字符串并将字符串的第一个字母变为大写;
SQL> select initcap('smith') upp from dual;

UPP
-----
Smith


5.INSTR(C1,C2,I,J)
在一个字符串中搜索指定的字符,返回发现指定的字符的位置;
C1 被搜索的字符串
C2 希望搜索的字符串
I 搜索的开始位置,默认为1
J 出现的位置,默认为1
SQL> select instr('oracle traning','ra',1,2) instring from dual;

INSTRING
---------
9


6.LENGTH
返回字符串的长度;
SQL> select name,length(name),addr,length(addr),sal,length(to_char(sal)) from gao.nchar_tst;

NAME LENGTH(NAME) ADDR LENGTH(ADDR) SAL LENGTH(TO_CHAR(SAL))
------ ------------ ---------------- ------------ --------- --------------------
高乾竞 3 北京市海锭区 6 9999.99 7



7.LOWER
返回字符串,并将所有的字符小写
SQL> select lower('AaBbCcDd')AaBbCcDd from dual;

AABBCCDD
--------
aabbccdd


8.UPPER
返回字符串,并将所有的字符大写
SQL> select upper('AaBbCcDd') upper from dual;

UPPER
--------
AABBCCDD



9.RPAD和LPAD(粘贴字符)
RPAD 在列的右边粘贴字符
LPAD 在列的左边粘贴字符
SQL> select lpad(rpad('gao',10,'*'),17,'*')from dual;

LPAD(RPAD('GAO',1
-----------------
*******gao*******
不够字符则用*来填满


10.LTRIM和RTRIM
LTRIM 删除左边出现的字符串
RTRIM 删除右边出现的字符串
SQL> select ltrim(rtrim(' gao qian jing ',' '),' ') from dual;

LTRIM(RTRIM('
-------------
gao qian jing


11.SUBSTR(string,start,count)
取子字符串,从start开始,取count个
SQL> select substr('13088888888',3,8) from dual;

SUBSTR('
--------
08888888


12.REPLACE('string','s1','s2')
string 希望被替换的字符或变��
s1 被替换的字符串
s2 要替换的字符串
SQL> select replace('he love you','he','i') from dual;

REPLACE('H
----------
i love you


13.SOUNDEX
返回一个与给定的字符串读音相同的字符串
SQL> create table table1(xm varchar(8));
SQL> insert into table1 values('weather');
SQL> insert into table1 values('wether');
SQL> insert into table1 values('gao');

SQL> select xm from table1 where soundex(xm)=soundex('weather');

XM
--------
weather
wether


14.TRIM('s' from 'string')
LEADING 剪掉前面的字符
TRAILING 剪掉后面的字符
如果不指定,默认为空格符

15.ABS
返回指定值的绝对值
SQL> select abs(100),abs(-100) from dual;

ABS(100) ABS(-100)
--------- ---------
100 100


16.ACOS
给出反余弦的值
SQL> select acos(-1) from dual;

ACOS(-1)
---------
3.1415927


17.ASIN
给出反正弦的值
SQL> select asin(0.5) from dual;

ASIN(0.5)
---------
.52359878


18.ATAN
返回一个数字的反正切值
SQL> select atan(1) from dual;

ATAN(1)
---------
.78539816


19.CEIL
返回大于或等于给出数字的最小整数
SQL> select ceil(3.1415927) from dual;

CEIL(3.1415927)
---------------
4


20.COS
返回一个给定数字的余弦
SQL> select cos(-3.1415927) from dual;

COS(-3.1415927)
---------------
-1


21.COSH
返回一个数字反余弦值
SQL> select cosh(20) from dual;

COSH(20)
---------
242582598


22.EXP
返回一个数字e的n次方根
SQL> select exp(2),exp(1) from dual;

EXP(2) EXP(1)
--------- ---------
7.3890561 2.7182818


23.FLOOR
对给定的数字取整数
SQL> select floor(2345.67) from dual;

FLOOR(2345.67)
--------------
2345


24.LN
返回一个数字的对数值
SQL> select ln(1),ln(2),ln(2.7182818) from dual;

LN(1) LN(2) LN(2.7182818)
--------- --------- -------------
0 .69314718 .99999999


25.LOG(n1,n2)
返回一个以n1为底n2的对数
SQL> select log(2,1),log(2,4) from dual;

LOG(2,1) LOG(2,4)
--------- ---------
0 2


26.MOD(n1,n2)
返回一个n1除以n2的余数
SQL> select mod(10,3),mod(3,3),mod(2,3) from dual;

MOD(10,3) MOD(3,3) MOD(2,3)
--------- --------- ---------
1 0 2


27.POWER
返回n1的n2次方根
SQL> select power(2,10),power(3,3) from dual;

POWER(2,10) POWER(3,3)
----------- ----------
1024 27


28.ROUND和TRUNC
按照指定的精度进行舍入
SQL> select round(55.5),round(-55.4),trunc(55.5),trunc(-55.5) from dual;

ROUND(55.5) ROUND(-55.4) TRUNC(55.5) TRUNC(-55.5)
----------- ------------ ----------- ------------
56 -55 55 -55


29.SIGN
取数字n的符号,大于0返回1,小于0返回-1,等于0返回0
SQL> select sign(123),sign(-100),sign(0) from dual;

SIGN(123) SIGN(-100) SIGN(0)
--------- ---------- ---------
1 -1 0


30.SIN
返回一个数字的正弦值
SQL> select sin(1.57079) from dual;

SIN(1.57079)
------------
1


31.SIGH
返回双曲正弦的值
SQL> select sin(20),sinh(20) from dual;

SIN(20) SINH(20)
--------- ---------
.91294525 242582598


32.SQRT
返回数字n的根
SQL> select sqrt(64),sqrt(10) from dual;

SQRT(64) SQRT(10)
--------- ---------
8 3.1622777


33.TAN
返回数字的正���值
SQL> select tan(20),tan(10) from dual;

TAN(20) TAN(10)
--------- ---------
2.2371609 .64836083


34.TANH
返回数字n的双曲正切值
SQL> select tanh(20),tan(20) from dual;

TANH(20) TAN(20)
--------- ---------
1 2.2371609



35.TRUNC
按照指定的精度截取一个数
SQL> select trunc(124.1666,-2) trunc1,trunc(124.16666,2) from dual;

TRUNC1 TRUNC(124.16666,2)
--------- ------------------
100 124.16



36.ADD_MONTHS
增加或减去月份
SQL> select to_char(add_months(to_date('199912','yyyymm'),2),'yyyymm') from dual;

TO_CHA
------
200002
SQL> select to_char(add_months(to_date('199912','yyyymm'),-2),'yyyymm') from dual;

TO_CHA
------
199910


37.LAST_DAY
返回日期的最后一天
SQL> select to_char(sysdate,'yyyy.mm.dd'),to_char((sysdate)+1,'yyyy.mm.dd') from dual;

TO_CHAR(SY TO_CHAR((S
---------- ----------
2004.05.09 2004.05.10
SQL> select last_day(sysdate) from dual;

LAST_DAY(S
----------
31-5月 -04


38.MONTHS_BETWEEN(date2,date1)
给出date2-date1的月份
SQL> select months_between('19-12月-1999','19-3月-1999') mon_between from dual;

MON_BETWEEN
-----------
9
SQL>selectmonths_between(to_date('2000.05.20','yyyy.mm.dd'),to_date('2005.05.20','yyyy.mm.dd')) mon_betw from dual;

MON_BETW
---------
-60


39.NEW_TIME(date,'this','that')
给出在this时区=other时区的日期和时间
SQL> select to_char(sysdate,'yyyy.mm.dd hh24:mi:ss') bj_time,to_char(new_time
2 (sysdate,'PDT','GMT'),'yyyy.mm.dd hh24:mi:ss') los_angles from dual;

BJ_TIME LOS_ANGLES
------------------- -------------------
2004.05.09 11:05:32 2004.05.09 18:05:32


40.NEXT_DAY(date,'day')
给出日期date和星期x之后计算下一个星期的日期
SQL> select next_day('18-5月-2001','星期五') next_day from dual;

NEXT_DAY
----------
25-5月 -01



41.SYSDATE
用来得到系统的当前日期
SQL> select to_char(sysdate,'dd-mm-yyyy day') from dual;

TO_CHAR(SYSDATE,'
-----------------
09-05-2004 星期日
trunc(date,fmt)按照给出的要求将日期截断,如果fmt='mi'表示保留分,截断秒
SQL> select to_char(trunc(sysdate,'hh'),'yyyy.mm.dd hh24:mi:ss') hh,
2 to_char(trunc(sysdate,'mi'),'yyyy.mm.dd hh24:mi:ss') hhmm from dual;

HH HHMM
------------------- -------------------
2004.05.09 11:00:00 2004.05.09 11:17:00



42.CHARTOROWID
将字符数据类型转换为ROWID类型
SQL> select rowid,rowidtochar(rowid),ename from scott.emp;

ROWID ROWIDTOCHAR(ROWID) ENAME
------------------ ------------------ ----------
AAAAfKAACAAAAEqAAA AAAAfKAACAAAAEqAAA SMITH
AAAAfKAACAAAAEqAAB AAAAfKAACAAAAEqAAB ALLEN
AAAAfKAACAAAAEqAAC AAAAfKAACAAAAEqAAC WARD
AAAAfKAACAAAAEqAAD AAAAfKAACAAAAEqAAD JONES


43.CONVERT(c,dset,sset)
将源字符串 sset从一个语言字符集转换到另一个目的dset字符集
SQL> select convert('strutz','we8hp','f7dec') "conversion" from dual;

conver
------
strutz


44.HEXTORAW
将一个十六进制构成的字符串转换为二进制


45.RAWTOHEXT
将一个二进制构成的字符串转换为十六进制



46.ROWIDTOCHAR
将ROWID数据类型转换为字符类型



47.TO_CHAR(date,'format')
SQL> select to_char(sysdate,'yyyy/mm/dd hh24:mi:ss') from dual;

TO_CHAR(SYSDATE,'YY
-------------------
2004/05/09 21:14:41



48.TO_DATE(string,'format')
将字符串转化为ORACLE中的一个日期


49.TO_MULTI_BYTE
将字符串中的单字节字符转化为多字节字符
SQL> select to_multi_byte('高') from dual;

TO
--



50.TO_NUMBER
将给出的字符转换为数字
SQL> select to_number('1999') year from dual;

YEAR
---------
1999


51.BFILENAME(dir,file)
指定一个外部二进制文件
SQL>insert into file_tb1 values(bfilename('lob_dir1','image1.gif'));


52.CONVERT('x','desc','source')
将x字段或变量的源source转换为desc
SQL> select sid,serial#,username,decode(command,
2 0,'none',
3 2,'insert',
4 3,
5 'select',
6 6,'update',
7 7,'delete',
8 8,'drop',
9 'other') cmd from v$session where type!='background';

SID SERIAL# USERNAME CMD
--------- --------- ------------------------------ ------
1 1 none
2 1 none
3 1 none
4 1 none
5 1 none
6 1 none
7 1275 none
8 1275 none
9 20 GAO select
10 40 GAO none


53.DUMP(s,fmt,start,length)
DUMP函数以fmt指定的内部数字格式返回一个VARCHAR2类型的值
SQL> col global_name for a30
SQL> col dump_string for a50
SQL> set lin 200
SQL> select global_name,dump(global_name,1017,8,5) dump_string from global_name;

GLOBAL_NAME DUMP_STRING
------------------------------ --------------------------------------------------
ORACLE.WORLD Typ=1 Len=12 CharacterSet=ZHS16GBK: W,O,R,L,D


54.EMPTY_BLOB()和EMPTY_CLOB()
这两个函数都是用来对大数据类型字段进行初始化操作的函数


55.GREATEST
返回一组表达式中的最大值,即比较字符的编码大小.
SQL> select greatest('AA','AB','AC') from dual;

GR
--
AC
SQL> select greatest('啊','安','天') from dual;

GR
--



56.LEAST
返回一组表达式中的最小��
SQL> select least('啊','安','天') from dual;

LE
--



57.UID
返回标识当前用户的唯一整数
SQL> show user
USER 为"GAO"
SQL> select username,user_id from dba_users where user_id=uid;

USERNAME USER_ID
------------------------------ ---------
GAO 25



58.USER
返回当前用户的名字
SQL> select user from dual;

USER
------------------------------
GAO


59.USEREVN
返回当前用户环境的信息,opt可以是:
ENTRYID,SESSIONID,TERMINAL,ISDBA,LABLE,LANGUAGE,CLIENT_INFO,LANG,VSIZE
ISDBA 查看当前用户是否是DBA如果是则返回true
SQL> select userenv('isdba') from dual;

USEREN
------
FALSE
SQL> select userenv('isdba') from dual;

USEREN
------
TRUE
SESSION
返回会话标志
SQL> select userenv('sessionid') from dual;

USERENV('SESSIONID')
--------------------
152
ENTRYID
返回会话人口标志
SQL> select userenv('entryid') from dual;

USERENV('ENTRYID')
------------------
0
INSTANCE
返回当前INSTANCE的标志
SQL> select userenv('instance') from dual;

USERENV('INSTANCE')
-------------------
1
LANGUAGE
返回当前环境变量
SQL> select userenv('language') from dual;

USERENV('LANGUAGE')
----------------------------------------------------
SIMPLIFIED CHINESE_CHINA.ZHS16GBK
LANG
返回当前环境的语言的缩写
SQL> select userenv('lang') from dual;

USERENV('LANG')
----------------------------------------------------
ZHS
TERMINAL
返回用户的终端或机器的标志
SQL> select userenv('terminal') from dual;

USERENV('TERMINA
----------------
GAO
VSIZE(X)
返回X的大小(字节)数
SQL> select vsize(user),user from dual;

VSIZE(USER) USER
----------- ------------------------------
6 SYSTEM



60.AVG(DISTINCT|ALL)
all表示对所有的值求平均值,distinct只对不同的值求平均值
SQLWKS> create table table3(xm varchar(8),sal number(7,2));
语句已处理。
SQLWKS> insert into table3 values('gao',1111.11);
SQLWKS> insert into table3 values('gao',1111.11);
SQLWKS> insert into table3 values('zhu',5555.55);
SQLWKS> commit;

SQL> select avg(distinct sal) from gao.table3;

AVG(DISTINCTSAL)
----------------
3333.33

SQL> select avg(all sal) from gao.table3;

AVG(ALLSAL)
-----------
2592.59


61.MAX(DISTINCT|ALL)
求最大值,ALL表示对所有的值求最大值,DISTINCT表示对不同的值求最大值,相同的只取一次
SQL> select max(distinct sal) from scott.emp;

MAX(DISTINCTSAL)
----------------
5000


62.MIN(DISTINCT|ALL)
求最小值,ALL表示对所有的值求最小值,DISTINCT表示对不同的值求最小值,相同的只取一次
SQL> select min(all sal) from gao.table3;

MIN(ALLSAL)
-----------
1111.11


63.STDDEV(distinct|all)
求标准差,ALL表示对所有的值求标准差,DISTINCT表示只对不同的值求标准差
SQL> select stddev(sal) from scott.emp;

STDDEV(SAL)
-----------
1182.5032

SQL> select stddev(distinct sal) from scott.emp;

STDDEV(DISTINCTSAL)
-------------------
1229.951



64.VARIANCE(DISTINCT|ALL)
求协方差

SQL> select variance(sal) from scott.emp;

VARIANCE(SAL)
-------------
1398313.9


65.GROUP BY
主要用来对一组数进行统计
SQL> select deptno,count(*),sum(sal) from scott.emp group by deptno;

DEPTNO COUNT(*) SUM(SAL)
--------- --------- ---------
10 3 8750
20 5 10875
30 6 9400



66.HAVING
对分组统计再加限制条件
SQL> select deptno,count(*),sum(sal) from scott.emp group by deptno having count(*)>=5;

DEPTNO COUNT(*) SUM(SAL)
--------- --------- ---------
20 5 10875
30 6 9400
SQL> select deptno,count(*),sum(sal) from scott.emp having count(*)>=5 group by deptno ;

DEPTNO COUNT(*) SUM(SAL)
--------- --------- ---------
20 5 10875
30 6 9400


67.ORDER BY
用于对查询到的结果进行排序输出
SQL> select deptno,ename,sal from scott.emp order by deptno,sal desc;

DEPTNO ENAME SAL
--------- ---------- ---------
10 KING 5000
10 CLARK 2450
10 MILLER 1300
20 SCOTT 3000
20 FORD 3000
20 JONES 2975
20 ADAMS 1100
20 SMITH 800
30 BLAKE 2850
30 ALLEN 1600
30 TURNER 1500
30 WARD 1250
30 MARTIN 1250
30 JAMES 950

">
<$BlogItemTitle$>

星期四, 九月 07, 2006

关于firefox对style.display属性的解释问题

最近在制作网站的过程中出现了一个问题,就是firefox下对遇style.display执行结果和ie不一样,真实郁闷,多方查找资料,终于发现了问题,代码如下:


<html>
<head>
<title>display</title>
<script type="text/javascript">
<!--
function show(){
var msg=document.getElementById("showmsg");
if(msg.style.display=="none"){
msg.style.display="block";
}
else
msg.style.display="none";
}
//-->
</script>
</head>
<body>
<table width="100%" >
<tr width="100%">
<td width="100%">
<font style="cursor:hand;" onclick="show()">
ddddddddddddddddd
</font>
</td>
</tr>
<tr id="showmsg" style="display:none;">
<td>dsffdafa</td>
</tr>
<tr><td>电风扇扩大发洒家艰苦</td></tr>
</table>
</body>
<html>



上面的HTML页面在IE和Firefox中的执行结果不同:
1)"display:none;"后面的内容站用原来块的内容空间//但Firefox好象把这个和"visibility:hidden;"一样处理的
2)"display:block;"将隐藏的内容显示出来//Firefox好象是为其重新开辟内容显示空间

最后正确有效的处理结果
发现个问题:
当将javascript脚本改下就可以了:
<script type="text/javascript">
<!--
function show(){
var msg=document.getElementById("showmsg");
if(msg.style.display=="none")
{ msg.style.display="";//即将此句有原来的msg.style.display="block";改为:msg.style.display=""; }
else
msg.style.display="none"; } //-->
</script>
呵呵~,搞定!

">
<$BlogItemTitle$>

Windows2000下整合Mysql4.0.13与Tomcat4.1.24搭建Jsp环境

原 由:在资料浩瀚的互联网中,却找不到一份最新的Mysql4.0.13与Tomcat4.1.24的整合配置文档。在自己工作之余,总结了自己搭建JSP 环境的实际经验并参照以前版本Mysql、Tomcat相关配置文章,写了这篇配置文档。希望能给和我一样喜欢JAVA的广大初学者以作参考,以期少走些 弯路;水平有限加之时间仓促,欢迎斧正!

目录:

一、软件准备

二、软件安装

三、首次配置及测试

四、整合配置

五、全线测试

六、补充说明

七、感谢

八、说明


具体实现步骤:


一、软件准备:

假设你有一台能正常运行win2000 的硬软软件环境。

1.J2sdk1.4.1 : 到http://java.sun.com/j2se/1.4.1/download.html下载;

2.Mysql4.0.13: 到http://www.mysql.com 下载;

3.Tomcat4.1.24:到 http://jakarta.apache.org/ 下载;

4.mm.mysql-2.0.4-bin.jar: 到 http://mysql.ihostunit.com/Downloads/Contrib/mm.mysql-2.0.4-bin.jar 下载;


二、软件安装:

1.安装J2sdk:

按照安装向导进行安装(一般安装到C:\j2sdk1.4.1下,方便操作);

2.安装Mysql:

按照安装向导进行安装(选择安装目录为C:\,方便操作;安装成功后其路径为:C:\mysql);

3.安装Tomcat:

按照安装向导进行安装(更改安装目录为C:\Tomcat4。1,其间会要你输入Admin(系统管理员)的口令);

4.放置Mysql的Jdbc驱动:

将mm.mysql-2.0.4-bin.jar文件放到C:\j2sdk1.4.0-rc\lib下(其实放到哪都应该无所谓,主要是在系统变量里指一下就可以了,但有不少人说放到这里好,所以我就放这里了);


三、首次配置及测试:

对以上安装的软件环境进行首次配置,并测试其环境:

(1)配置--环境变量:

1.新建系统变量JAVA_HOME,其值为:C:\j2sdk1.4.1 (若你没按以上路径安装请更改为您的安装路径);

2.新建系统变量TOMCAT_HOME,其值为:C:\Tomcat4 (若你没按以上路径安装请更改为您的安装路径);

3.系统变量CLASSPATH,添加,其值为:C:\Tomcat 4.1\common\classes;C:\Tomcat 4.1\common\lib

4.系统变量CLASSPATH,添加,其值为:C:\j2sdk1.4.0-rc\lib\mm.mysql-2.0.4-bin;


(2)测试默认服务:

1.请先启动Tomcat4.1(在开始-程序中找到Apache Tomcat4.1运行Start Tomcat)服务:

打开浏览器,在地址栏中输入: http://localhost:8080 检验:此时能在浏览器中看到Tomcat的欢迎界面.说明Tomcat工作正常(注意,Tomcat默认端口为8080,若有其它程序占用,请更改);

2.启动Mysql服务(Mysql服务默认随操作系统启动,并有winmysqladmin.exe最小化在系统托盘上):

进入CMD,到C:\mysql\bin目录下,执行mysql,回车,正常的话输出一些欢迎信息,说明Mysql工作正常;


四、整合配置:

对Mysql4与Tomcat4做相应的配置,让其共同为你工作:

1.将mm.mysql-2.0.4-bin.jar拷贝到Tomcat的common/lib目录下;

2.测试是否连接正常;将如下代码保存成test.jsp至C:\Tomcat 4.1\webapps\ROOT目录下:

;%@ page contentType="text/html;charset=gb2312" %;
;%
java.sql.Connection conn;
java.lang.String strConn;
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
conn= java.sql.DriverManager.getConnection("jdbc:mysql://localhost/test","root","");
%;
;%--这里连接的是Mysql4默认自带的test库,用户与密码用的是默认的root与空--%;

3、在浏览器的地址中输入http://localhost:8080/test.jsp如果运行以后,出现空白页面,即表示Mysql4与Tomcat4整合成功;


五、全线测试:

1.启动Tomcat4.1;

2.建立数据库及表;

首先在mysql里面建立一个表,并且插如几条数据。sql代码如下:
create database test;--运行
use test;--运行
create talbe admin (id int(4) auto_increment primary key,name varchar(20));--运行
INSERT INTO user(name) VALUES('test');--运行
ok,你已经建立了数据库test,建立了表user,并且插入了一条记录。

3、显示数据库中的记录;

将如下代码保存成test2.jsp至C:\Tomcat 4.1\webapps\ROOT目录下:
;%@ page contentType="text/html;charset=GBK" %;
;%@ page language="java" import=" java.sql.*"%;
;%
Connection conn = null;
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
conn = java.sql.DriverManager.getConnection("jdbc:mysql://localhost/test","root","");
if(conn==null){
System.out.println("get Conn Error");
}
Statement stmt=conn.createStatement();
ResultSet RS_result=null;
%;
;html;
;head;
;title;测试;/title;;/head;
;body;
;%
RS_result= stmt.executeQuery("select * from user");
String Name;
while(RS_result.next())
{
Name=RS_result.getString("name");
%;
;%=Name%;
;%
}
RS_result.close();
stmt.close();
conn.close ();
%;
;/body;
;/html;

4.打开你的浏览器,在地址栏中输入http://localhost:8080/test.jsp如果运行以后,页面上显示test,即表示读取数据库成功;


六、补充说明:

1.假设已有一项目在E:\test\oa目录下(包含index.jsp及其它jsp文件和bean,如WEB-INF\classes\下的servlet、javabean);
设置Tomcat以支持你的项目,打开C:\Tomcat4.1\conf\server.xml文件,在";/Host;"之前,";/Context;"之后添加
;Context path="/oa" debug="0" docBase="E:\test\oa" reloadable="true"/;并保存。
说明:Context (表示一个web应用程序): docBase定义应用程序的路径;path 表示此web应用程序的url的前缀,这样请求的url
http://localhost:8080/oa;reloadable 这个属性非常重要,如果为true,则tomcat会自动检测应用程序的/WEB-INF/lib
和/WEB-INF/classes目录的变化,自动装载修改或新的bean及servlet,我们可以在不重起tomcat的情况下看到bean带给jsp的变化;

2.启动Tomcat4.1,在浏览器的地址中输入http://localhost:8080/oa,如jsp及bean等没有错误,一般会将你的index.jsp/index.html
文件的内容给执行并显示。


七、感谢:

1.感谢Apache、Mysql组织,为大家提供了如此之好的免费的应用服务器与数据库;

2.感谢以前写过Tomcat3.x/Tomcat4.*配置文档的朋友们,为我今天写这篇文档作了参考;


八、说明:

1.若您觉得满意,想转载或收藏这篇文章,我非常感谢,但请您注明作者hoxisoft(hoxisoft@263.net

星期三, 九月 06, 2006

使用Java编写oracle存储过程

bromon原创 请尊重版权

     通常我们都使用ps/sql为oracle编写存储过程,从oracle 8开始我们可以有另一种选择: Java。8.0开始,oracle自带一个jvm,内置对java的支持,任何java能做的事情你都可以放到oracle里面来做,你甚至可以在里面 操作db2。这让oracle具备了极其巨大的扩展能力,只要你愿意,完全可以开发一个trigger,让它在适当的时候给管理员的msn发送一条即时消 息。

    好消息说完了,现在是坏消息:由于ps/sql是过程化的语言,它基本上不具备多 态的概念,供oracle使用的java方法必须申明为static,所以在oracle中你无法使用java的动态特性,比如接口、反射等。不过这并不 妨碍你用java做爱做的事。

    我们以一个简单的hello world为例,我想任何一个有经验的java程序员都能够通过这个例子,派生出其他希奇古怪的应用,有好的创意记得要与我共享,我的msn是bromon@gmail.com

    首先是创建一个java类,你可以用jbuilder/eclipse来编写,也可以直接在oracle的控制台里面创建。前者不多说,看看后一种方式。

    启动sql plus,执行如下命令:


  1. create or replace and compile java source named "hello_sp"  as
  2. /**
  3.  *创建oracle存储过程的java类
  4.  *@author bromon
  5. **/
  6. package  org.bromon.oracle;
  7. public   class  Hello
  8. {
  9.    public   static   String  say( String  name)
  10.   {
  11.      return  "你好," +name;
  12.   }
  13. }

Java以创建。

然后在oracle中把这个类导入成为一个函数,执行命令:

  1. create or replace function hello_sp(name varchar2)  return  varchar2
  2. as language java name 
  3. 'org.bromon.oracle.Hello.say(java.lang. String return  java.lang. String ';


函数已创建

现在可以调用该函数,执行:
  1. select hello('bromon') from dual;


返回结果:你好,bromon

有一个需要注意的问题是,假如我们的java方法是没有参数的,比如:

  1. public   static   String  say()
  2.   {
  3.      return  "你好";
  4.   }

那么在创建函数的时候,函数名不应该有扩号:hello_sp
否则会报告函数有编译错误。

如果你的java类是在IDE里面编写的,那么只需要在oracle中加载编译过的class文件即可,方法是:

启 动enterprise manage console,在"方案"下找到"源类型 ",右击"java类",选择"加载java",选择对应的class文件即可。

Oracle的换行符

  • 在SQL中,表示字符串得引号强烈建议使用单引号(')。虽然MySQL也可以使用双引号("),但是为了和SQL Server和Oracle统一,建议都使用单引号。如果在字符串中也有单引号出现的话,在SQL中需要将其替换为两个单引号(''),DBMS会将其解 释为一个单引号的。
  • 关于SQL的换行符和字符串连接符,在MySQL、SQL Server和Oracle中均有不同,下面以列表显示。
      MySQL SQL Server Oracle
    换行符 \n或\r\n或CHAR(10) CHAR(13) CHR(10)
    字符串连接符 CONCAT() + ||或CONCAT()
  • 游标使用大全

    游标使用大全
    查询

    SELECT语句用于从数据库中查询数据,当在PL/SQL中使用SELECT语句时,要与INTO子句一起使用,查询的返回值被赋予INTO子句中的变量,变量的声明是在DELCARE中。SELECT INTO语法如下:

    SELECT [DISTICT|ALL]{*|column[,column,...]}

    INTO (variable[,variable,...] |record)

    FROM {table|(sub-query)}[alias]

    WHERE............

    PL/SQL中SELECT语句只返回一行数据。如果超过一行数据,那么就要使用显式游标(对游标的讨论我们将在后面进行),INTO子句中要有与SELECT子句中相同列数量的变量。INTO子句中也可以是记录变量。



    %TYPE属性

    在PL/SQL中可以将变量和常量声明为内建或用户定义的数据类型,以引用一个列名,同时继承他的数据类型和大小。这种动态赋值方法是非常有用的,比如变量引用的列的数据类型和大小改变了,如果使用了%TYPE,那么用户就不必修改代码,否则就必须修改代码。



    例:

    v_empno SCOTT.EMP.EMPNO%TYPE;

    v_salary EMP.SALARY%TYPE;

     不但列名可以使用%TYPE,而且变量、游标、记录,或声明的常量都可以使用%TYPE。这对于定义相同数据类型的变量非常有用。

    DELCARE

    V_A NUMBER(5):=10;

    V_B V_A%TYPE:=15;

    V_C V_A%TYPE;

    BEGIN

    DBMS_OUTPUT.PUT_LINE

    ('V_A='||V_A||'V_B='||V_B||'V_C='||V_C);

    END



    SQL>/

    V_A=10 V_B=15 V_C=

    PL/SQL procedure successfully completed.

    SQL>



    其他DML语句

    其它操作数据的DML语句是:INSERT、UPDATE、DELETE和LOCK TABLE,这些语句在PL/SQL中的语法与在SQL中的语法相同。我们在前面已经讨论过DML语句的使用这里就不再重复了。在DML语句中可以使用任何在DECLARE部分声明的变量,如果是嵌套块,那么要注意变量的作用范围。



    例:

    CREATE OR REPLACE PROCEDURE FIRE_EMPLOYEE (pempno in number)

     AS

    v_ename EMP.ENAME%TYPE;

    BEGIN

     SELECT ename INTO v_ename

    FROM emp

    WHERE empno=p_empno;

    INSERT INTO FORMER_EMP(EMPNO,ENAME)

    VALUES (p_empno,v_ename);

    DELETE FROM emp

    WHERE empno=p_empno;

    UPDATE former_emp

    SET date_deleted=SYSDATE

    WHERE empno=p_empno;



    EXCEPTION

    WHEN NO_DATA_FOUND THEN

    DBMS_OUTPUT.PUT_LINE('Employee Number Not Found!');

    END



    DML语句的结果

    当执行一条DML语句后,DML语句的结果保存在四个游标属性中,这些属性用于控制程序流程或者了解程序的状态。当运行DML语句时,PL/SQL打开一个内建游标并处理结果,游标是维护查询结果的内存中的一个区域,游标在运行DML语句时打开,完成后关闭。隐式游标只使用SQL%FOUND,SQL% NOTFOUND,SQL%ROWCOUNT三个属性.SQL%FOUND,SQL%NOTFOUND是布尔值,SQL%ROWCOUNT是整数值。



    SQL%FOUND和SQL%NOTFOUND

    在执行任何DML语句前SQL%FOUND和SQL%NOTFOUND的值都是NULL,在执行DML语句后,SQL%FOUND的属性值将是:



    . TRUE :INSERT

    . TRUE :DELETE和UPDATE,至少有一行被DELETE或UPDATE.

    . TRUE :SELECT INTO至少返回一行

    当SQL%FOUND为TRUE时,SQL%NOTFOUND为FALSE。



    SQL%ROWCOUNT

    在执行任何DML语句之前,SQL%ROWCOUNT的值都是NULL,对于SELECT INTO语句,如果执行成功,SQL%ROWCOUNT的值为1,如果没有成功,SQL%ROWCOUNT的值为0,同时产生一个异常 NO_DATA_FOUND.



    SQL%ISOPEN

    SQL%ISOPEN是一个布尔值,如果游标打开,则为TRUE, 如果游标关闭,则为FALSE.对于隐式游标而言SQL%ISOPEN总是FALSE,这是因为隐式游标在DML语句执行时打开,结束时就立即关闭。



    事务控制语句

    事务是一个工作的逻辑单元可以包括一个或多个DML语句,事物控制帮助用户保证数据的一致性。如果事务控制逻辑单元中的任何一个DML语句失败,那么整个事务都将回滚,在PL/SQL中用户可以明确地使用COMMIT、ROLLBACK、SAVEPOINT以及SET TRANSACTION语句。

    COMMIT语句终止事务,永久保存数据库的变化,同时释放所有LOCK,ROLLBACK终止现行事务释放所有LOCK,但不保存数据库的任何变化, SAVEPOINT用于设置中间点,当事务调用过多的数据库操作时,中间点是非常有用的,SET TRANSACTION用于设置事务属性,比如read-write和隔离级等。



    显式游标

    当查询返回结果超过一行时,就需要一个显式游标,此时用户不能使用select into语句。PL/SQL管理隐式游标,当查询开始时隐式游标打开,查询结束时隐式游标自动关闭。显式游标在PL/SQL块的声明部分声明,在执行部分或异常处理部分打开,取数据,关闭。



    使用游标

    这里要做一个声明,我们所说的游标通常是指显式游标,因此从现在起没有特别指明的情况,我们所说的游标都是指显式游标。要在程序中使用游标,必须首先声明游标。



    声明游标

    语法:

    CURSOR cursor_name IS select_statement;



    在PL/SQL中游标名是一个未声明变量,不能给游标名赋值或用于表达式中。



    例:

    DELCARE

    CURSOR C_EMP IS SELECT empno,ename,salary

    FROM emp

    WHERE salary>2000

    ORDER BY ename;

    ........

    BEGIN

    在游标定义中SELECT语句中不一定非要表可以是视图,也可以从多个表或视图中选择的列,甚至可以使用*来选择所有的列 。



    打开游标

    使用游标中的值之前应该首先打开游标,打开游标初始化查询处理。打开游标的语法是:

    OPEN cursor_name

    cursor_name是在声明部分定义的游标名。



    例:

    OPEN C_EMP;



    关闭游标

    语法:

    CLOSE cursor_name



    例:

    CLOSE C_EMP;



    从游标提取数据

    从游标得到一行数据使用FETCH命令。每一次提取数据后,游标都指向结果集的下一行。语法如下:

    FETCH cursor_name INTO variable[,variable,...]

    对于SELECT定义的游标的每一列,FETCH变量列表都应该有一个变量与之相对应,变量的类型也要相同。



    例:

    SET SERVERIUTPUT ON

    DECLARE

    v_ename EMP.ENAME%TYPE;

    v_salary EMP.SALARY%TYPE;

    CURSOR c_emp IS SELECT ename,salary FROM emp;

    BEGIN

    OPEN c_emp;

    FETCH c_emp INTO v_ename,v_salary;

    DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);

    FETCH c_emp INTO v_ename,v_salary;

    DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);

    FETCH c_emp INTO v_ename,v_salary;

    DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);

    CLOSE c_emp;

    END



    这段代码无疑是非常麻烦的,如果有多行返回结果,可以使用循环并用游标属性为结束循环的条件,以这种方式提取数据,程序的可读性和简洁性都大为提高,下面我们使用循环重新写上面的程序:

    SET SERVERIUTPUT ON

    DECLARE

    v_ename EMP.ENAME%TYPE;

    v_salary EMP.SALARY%TYPE;

    CURSOR c_emp IS SELECT ename,salary FROM emp;

    BEGIN

    OPEN c_emp;

    LOOP

    FETCH c_emp INTO v_ename,v_salary;

    EXIT WHEN c_emp%NOTFOUND;

    DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);

    END



    记录变量

    定义一个记录变量使用TYPE命令和%ROWTYPE,关于%ROWsTYPE的更多信息请参阅相关资料。

    记录变量用于从游标中提取数据行,当游标选择很多列的时候,那么使用记录比为每列声明一个变量要方便得多。

    当在表上使用%ROWTYPE并将从游标中取出的值放入记录中时,如果要选择表中所有列,那么在SELECT子句中使用*比将所有列名列出来要安全得多。



    例:

    SET SERVERIUTPUT ON

    DECLARE

    R_emp EMP%ROWTYPE;

    CURSOR c_emp IS SELECT * FROM emp;

    BEGIN

    OPEN c_emp;

    LOOP

    FETCH c_emp INTO r_emp;

    EXIT WHEN c_emp%NOTFOUND;

    DBMS_OUT.PUT.PUT_LINE('Salary of Employee'||r_emp.ename||'is'|| r_emp.salary);

    END LOOP;

    CLOSE c_emp;

    END;



    %ROWTYPE也可以用游标名来定义,这样的话就必须要首先声明游标:



    SET SERVERIUTPUT ON

    DECLARE

    CURSOR c_emp IS SELECT ename,salary FROM emp;

    R_emp c_emp%ROWTYPE;

    BEGIN

    OPEN c_emp;

    LOOP

    FETCH c_emp INTO r_emp;

    EXIT WHEN c_emp%NOTFOUND;

    DBMS_OUT.PUT.PUT_LINE('Salary of Employee'||r_emp.ename||'is'|| r_emp.salary);

    END LOOP;

    CLOSE c_emp;

    END;



    带参数的游标

    与存储过程和函数相似,可以将参数传递给游标并在查询中使用。这对于处理在某种条件下打开游标的情况非常有用。它的语法如下:



    CURSOR cursor_name[(parameter[,parameter],...)] IS select_statement;



    定义参数的语法如下:

    Parameter_name [IN] data_type[{:=|DEFAULT} value]



      与存储过程不同的是,游标只能接受传递的值,而不能返回值。参数只定义数据类型,没有大小。

    另外可以给参数设定一个缺省值,当没有参数值传递给游标时,就使用缺省值。游标中定义的参数只是一个占位符,在别处引用该参数不一定可靠。



    在打开游标时给参数赋值,语法如下:



    OPEN cursor_name[value[,value]....];

    参数值可以是文字或变量。



    例:

    DECALRE

    CURSOR c_dept IS SELECT * FROM dept ORDER BY deptno;

    CURSOR c_emp (p_dept VARACHAR2) IS

    SELECT ename,salary

    FROM emp

    WHERE deptno=p_dept

    ORDER BY ename

    r_dept DEPT%ROWTYPE;

    v_ename EMP.ENAME%TYPE;

    v_salary EMP.SALARY%TYPE;

    v_tot_salary EMP.SALARY%TYPE;

    BEGIN

    OPEN c_dept;

    LOOP

    FETCH c_dept INTO r_dept;

    EXIT WHEN c_dept%NOTFOUND;

    DBMS_OUTPUT.PUT_LINE('Department:'|| r_dept.deptno||'-'||r_dept.dname);

    v_tot_salary:=0;

    OPEN c_emp(r_dept.deptno);

    LOOP

    FETCH c_emp INTO v_ename,v_salary;

    EXIT WHEN c_emp%NOTFOUND;

    DBMS_OUTPUT.PUT_LINE('Name:'|| v_ename||' salary:'||v_salary);

    v_tot_salary:=v_tot_salary+v_salary;

    END LOOP;

    CLOSE c_emp;

    DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:'|| v_tot_salary);

    END LOOP;

    CLOSE c_dept;

    END;



    游标FOR循环

    在大多数时候我们在设计程序的时候都遵循下面的步骤:

    1、打开游标

    2、开始循环

    3、从游标中取值

    4、检查那一行被返回

    5、处理

    6、关闭循环

    7、关闭游标

    可以简单的把这一类代码称为游标用于循环。但还有一种循环与这种类型不相同,这就是FOR循环,用于FOR循环的游标按照正常的声明方式声明,它的优点在于不需要显式的打开、关闭、取数据,测试数据的存在、定义存放数据的变量等等。游标FOR循环的语法如下:



    FOR record_name IN

    (corsor_name[(parameter[,parameter]...)]

    | (query_difinition)

    LOOP

    statements

    END LOOP;



    下面我们用for循环重写上面的例子:

    DECALRE

    CURSOR c_dept IS SELECT deptno,dname FROM dept ORDER BY deptno;

    CURSOR c_emp (p_dept VARACHAR2) IS

    SELECT ename,salary

    FROM emp

    WHERE deptno=p_dept

    ORDER BY ename

    v_tot_salary EMP.SALARY%TYPE;

    BEGIN

    FOR r_dept IN c_dept LOOP

    DBMS_OUTPUT.PUT_LINE('Department:'|| r_dept.deptno||'-'||r_dept.dname);

    v_tot_salary:=0;

    FOR r_emp IN c_emp(r_dept.deptno) LOOP

    DBMS_OUTPUT.PUT_LINE('Name:' || v_ename || 'salary:' || v_salary);

    v_tot_salary:=v_tot_salary+v_salary;

    END LOOP;

    DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:'|| v_tot_salary);

    END LOOP;

    END;



    在游标FOR循环中使用查询

    在游标FOR循环中可以定义查询,由于没有显式声明所以游标没有名字,记录名通过游标查询来定义。

    DECALRE

    v_tot_salary EMP.SALARY%TYPE;

    BEGIN

    FOR r_dept IN (SELECT deptno,dname FROM dept ORDER BY deptno) LOOP

    DBMS_OUTPUT.PUT_LINE('Department:'|| r_dept.deptno||'-'||r_dept.dname);

    v_tot_salary:=0;

    FOR r_emp IN (SELECT ename,salary

       FROM emp

       WHERE deptno=p_dept

       ORDER BY ename) LOOP

    DBMS_OUTPUT.PUT_LINE('Name:'|| v_ename||' salary:'||v_salary);

    v_tot_salary:=v_tot_salary+v_salary;

    END LOOP;

    DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:'|| v_tot_salary);

    END LOOP;

    END;



    游标中的子查询

    语法如下:



    CURSOR C1 IS SELECT * FROM emp

    WHERE deptno NOT IN (SELECT deptno

    FROM dept

    WHERE dname!='ACCOUNTING');

    可以看出与SQL中的子查询没有什么区别。



    游标中的更新和删除

    在PL/SQL中依然可以使用UPDATE和DELETE语句更新或删除数据行。显式游标只有在需要获得多行数据的情况下使用。PL/SQL提供了仅仅使用游标就可以执行删除或更新记录的方法。

    UPDATE 或DELETE语句中的WHERE CURRENT OF子串专门处理要执行UPDATE或DELETE操作的表中取出的最近的数据。要使用这个方法,在声明游标时必须使用FOR UPDATE子串,当对话使用FOR UPDATE子串打开一个游标时,所有返回集中的数据行都将处于行级(ROW-LEVEL)独占式锁定,其他对象只能查询这些数据行,不能进行 UPDATE、DELETE或SELECT...FOR UPDATE操作。



    语法:

    FOR UPDATE [OF [schema.]table.column[,[schema.]table.column]..

    [nowait]



    在多表查询中,使用OF子句来锁定特定的表,如果忽略了OF子句,那么所有表中选择的数据行都将被锁定。如果这些数据行已经被其他会话锁定,那么正常情况下Oracle将等待,直到数据行解锁。



    在UPDATE和DELETE中使用WHERE CURRENT OF子串的语法如下:



    WHERE{CURRENT OF cursor_name|search_condition}



    例:

    DELCARE

    CURSOR c1 IS SELECT empno,salary

    FROM emp

    WHERE comm IS NULL

    FOR UPDATE OF comm;

    v_comm NUMBER(10,2);

    BEGIN

    FOR r1 IN c1 LOOP

    IF r1.salary<500 THEN

    v_comm:=r1.salary*0.25;

    ELSEIF r1.salary<1000 THEN

    v_comm:=r1.salary*0.20;

    ELSEIF r1.salary<3000 THEN

    v_comm:=r1.salary*0.15;

    ELSE

    v_comm:=r1.salary*0.12;

    END IF;

    UPDATE emp;

    SET comm=v_comm

    WHERE CURRENT OF c1l;

    END LOOP;

    END
    Last edited Aug 17, 2006 - Note created Aug 16, 2006


    EditDelete
    ORACLE 的这类错误在ORALCE的文档中有详细说明,但原因及措施说明不详细,本文当着重说明如何解决这类错误。 1、ORA-12571、ORA-03113、ORA-03114、ORA-01041 特征:客户端(代理或应用服务器)有时报这类断连错误原因:如果偶尔出现一次,则可能为网络原因或用户异常中止,如果经常出现则为客户端与服务端的字符集不一致。措施:如果偶尔出现,可在服务端的协议配置文件PROTOCOL.ORA中增加一行 TCP.NODELAY=YES; 如果经常出现,则为客户端与服务端字符集不一致或网络原因。 客户端的字符集在注册表里定义: HKEY__LOCAL__MACHINE/SOFTWARE/ORACLE/NLS__LANG 在客户端注册表中的TCP参数项中设置 TCPMAXDATARETRANSMITIONS=20。 2、ORA-01000 特征:达到会话允许的最大 游标 数原因:达到会话允许的最大游标数 措施:有两种解决方法: (1)在初始化文件INIT.ORA文件中增加OPEN_CURSORS的数量,一般要求大于200。 (2)在应用级,与开发工具有关,例如设置MAXOPEN_CURSORS等。 3、ORA-01545 特征:某个 回滚段 不可用原因:(1)当使回滚段ONLINE时,但回滚段不可用,例如回滚段所在表空间OFFLINE; (2) 当使回滚段ONLINE时,但回滚段已ONLINE,例如回滚段被使用两次,典型的案例如OPS方式时,回滚段不能公有; (3)删除回滚段时,回滚段中有活动的事务; 措施:(1)确保回滚段可 (2)从初始化文件INIT.ORA的参数ROLLBACK)SEGMENTS中删除指定的回滚段。 (3)可以将回滚段所在表空间删除,取消UNDO事务 4、ORA-0165x 特征:表空间没有足够的空间供分配原因:表空间已满;存储参数不合理,NEXT太小;没有连续的区间措施:如果表空间已满,则需为表空间增加文件;如果存储参数不合理,则需增加INITIAL和NEXT;如果没有连续的区间,需要合并空闲的表空间。查看空间碎片用DBA_FREE_SPACE 5、ORA-01555 特征:当前会话无法读到以前版本的数据原因:原因很多,主要原因有下列:回滚段太小、太少;回滚段冲突;交叉提交(FETCH_ACROSS) 措施:增加回滚段数量; 6、ORA-04031 特征:共享池内存区内存不够,或产生内存碎片 原因:当试图装载一个大包时或执行一个较大的 存储过程时,而共享池没有连续的内存空间。 措施:如果是内存不够,则增加SHARE)POOL_SIZE; 如果是内存碎片,执行alter system flush share_pool 7、ORA-04091 特征:触发器工作不正常原因:一个行触发读取或修改变化的表(正在修改、插入)时,产生这种错误。 措施:检查触发器脚本,保证引用完整性 8、ORA-01242、ORA-01113 特征:介质故障导致数据库宕机 原因:介质故障。措施:检查硬件故障;修改dbshut脚本,将其中的STARTUP命令修改为: Startup open recover Alter database open
    Note created Aug 16, 2006
    Oracle常见错误诊断_站长技术站 - www.souzz.net/...


    EditDelete
    摘自: 求在9i的存储过程中二维数组的完整例子及说明,在线等.table ,varrry ,recor都行. ---------------------- 单维数组 ------------------------ DECLARE TYPE emp_ssn_array IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; best_employees emp_ssn_array; worst_employees emp_ssn_array; BEGIN best_employees(1) := '123456'; best_employees(2) := '888888'; worst_employees(1) := '222222'; worst_employees(2) := '666666'; FOR i IN 1..best_employees.count LOOP DBMS_OUTPUT.PUT_LINE('i=' ¦ ¦ i ¦ ¦ ', best_employees= ' ¦ ¦best_employees(i) ¦ ¦ ', worst_employees= ' ¦ ¦worst_employees(i)); END LOOP; END; ---------------------- 多维数组 ------------------------ DECLARE TYPE emp_type IS RECORD ( emp_id number, emp_name string(80), emp_gender string(80)); TYPE emp_type_array IS TABLE OF emp_type INDEX BY BINARY_INTEGER; emp_rec_array emp_type_array; emp_rec emp_type; BEGIN emp_rec.emp_id := 300000000; emp_rec.emp_name := 'Barbara'; emp_rec.emp_gender := 'Female'; emp_rec_array(1) := emp_rec; emp_rec.emp_id := 300000008; emp_rec.emp_name := 'Rick'; emp_rec.emp_gender := 'Male'; emp_rec_array(2) := emp_rec; FOR i IN 1..emp_rec_array.count LOOP DBMS_OUTPUT.PUT_LINE('i=' ¦ ¦i ¦ ¦', emp_id =' ¦ ¦emp_rec_array(i).emp_id ¦ ¦', emp_name =' ¦ ¦emp_rec_array(i).emp_name ¦ ¦', emp_gender = ' ¦ ¦emp_rec_array(i).emp_gender); END LOOP; END; -------------- Result -------------- i=1, emp_id =300000000, emp_name =Barbara, emp_gender = Female i=2, emp_id =300000008, emp_name =Rick, emp_gender = Male
    Note created Aug 17, 2006
    求在9i的存储过程中二维数组的完整例子及说明,在线等.table ,varrry ,recor都行. - 开发 源码 常见问题 - faq.lvjiyong.com/...


    EditDelete

    Oracle 下的Length()函数不能区分中英文,只能得到字符数而不能得到字节数,很多时候插入string到字段中时总要先进行一次检查,防止string长度超过了字段定义的长度,一般大家都是把这个检测放到应用程序中执行,用我写的这个小函数就可以实现在数据库服务器端对要插入的字段进行检测。

    create or replace function f_henry_GetStringLength(pv_String in varchar2) return integer is
    Result integer;
    i number;
    begin
    Result:=0;
    if length(pv_String)=0 then
    return(Result);
    end if;
    for i in 1 .. length(pv_String) loop
    if ascii(substr(pv_String,i,1))<256 then
    Result:=Result+1;
    else
    Result:=Result+2;
    end if;
    end loop;
    return(Result);
    end f_henry_GetStringLength;

    /*************************以下是测试***************************/

    SQL> select length('啊$@oii发大幅') from dual;

    LENGTH('啊$@OII发大幅')
    -----------------------
    9

    SQL> select f_henry_GetStringLength('啊$@oii发大幅') from dual;

    F_HENRY_GETSTRINGLENGTH('啊$@O
    ------------------------------
    13

    Note created Aug 17, 2006
    Oracle自定义函数——f_henry_GetStringLength_ - www.tbnet.cn/...


    EditDelete
    访问页面的人可以在线聊天

    Note created Aug 17, 2006
    Woocall首页 - woocall.sina.com.cn/...


    EditDelete

    EXECUTE IMMEDIATE代替了以前Oracle8i中DBMS_SQL package包.它解析并马上执行动态的SQL语句或非运行时创建的PL/SQL块.动态创建和执行SQL语句性能超前,EXECUTE IMMEDIATE的目标在于减小企业费用并获得较高的性能,较之以前它相当容易编码.尽管DBMS_SQL仍然可用,但是推荐使用EXECUTE IMMEDIATE,因为它获的收益在包之上。
      
      使用技巧
      
      1. EXECUTE IMMEDIATE将不会提交一个DML事务执行,应该显式提交
      如果通过EXECUTE IMMEDIATE处理DML命令,那么在完成以前需要显式提交或者作为EXECUTE IMMEDIATE自己的一部分. 如果通过EXECUTE IMMEDIATE处理DDL命令,它提交所有以前改变的数据
      
      2. 不支持返回多行的查询,这种交互将用临时表来存储记录(参照例子如下)或者用REF cursors.
      
      3. 当执行SQL语句时,不要用分号,当执行PL/SQL块时,在其尾部用分号.
      
      4. 在Oracle手册中,未详细覆盖这些功能。下面的例子展示了所有用到Execute immediate的可能方面.希望能给你带来方便.
      
      5. 对于Forms开发者,当在PL/SQL 8.0.6.3.版本中,Forms 6i不能使用此功能.
      
      EXECUTE IMMEDIATE用法例子
      
      1. 在PL/SQL运行DDL语句
      
       begin
       execute immediate 'set role all';
       end;
      
      2. 给动态语句传值(USING 子句)
      
       declare
       l_depnam varchar2(20) := 'testing';
       l_loc  varchar2(10) := 'Dubai';
       begin
       execute immediate 'insert into dept values (:1, :2, :3)'
        using 50, l_depnam, l_loc;
       commit;
       end;
      
      3. 从动态语句检索值(INTO子句)
      
       declare
       l_cnt  varchar2(20);
       begin
       execute immediate 'select count(1) from emp'
        into l_cnt;
       dbms_output.put_line(l_cnt);
       end;
      
      4. 动态调用例程.例程中用到的绑定变量参数必须指定参数类型.黓认为IN类型,其它类型必须显式指定
      
       declare
       l_routin  varchar2(100) := 'gen2161.get_rowcnt';
       l_tblnam  varchar2(20) := 'emp';
       l_cnt   number;
       l_status  varchar2(200);
       begin
       execute immediate 'begin ' || l_routin || '(:2, :3, :4); end;'
        using in l_tblnam, out l_cnt, in out l_status;
      
       if l_status != 'OK' then
         dbms_output.put_line('error');
       end if;
       end;
      
      5. 将返回值传递到PL/SQL记录类型;同样也可用%rowtype变量
      
       declare
       type empdtlrec is record (empno number(4),
                    ename varchar2(20),
                    deptno number(2));
       empdtl empdtlrec;
       begin
       execute immediate 'select empno, ename, deptno ' ||
                'from emp where empno = 7934'
        into empdtl;
       end;
      
      6. 传递并检索值.INTO子句用在USING子句前
      
       declare
       l_dept  pls_integer := 20;
       l_nam   varchar2(20);
       l_loc   varchar2(20);
       begin
       execute immediate 'select dname, loc from dept where deptno = :1'
        into l_nam, l_loc
        using l_dept ;
       end;
      
      7. 多行查询选项.对此选项用insert语句填充临时表,用临时表进行进一步的处理,也可以用REF cursors纠正此缺憾.
      
       declare
       l_sal  pls_integer := 2000;
       begin
       execute immediate 'insert into temp(empno, ename) ' ||
                '     select empno, ename from emp ' ||
                '     where sal > :1'
        using l_sal;
       commit;
       end;
      
      对于处理动态语句,EXECUTE IMMEDIATE比以前可能用到的更容易并且更高效.当意图执行动态语句时,适当地处理异常更加重要.应该关注于捕获所有可能的异常.