在windows x64环境下使用oracle instant client配置pl/sql developer

在x64的环境下,即便安装了oracle数据库,但是如果使用pl/sql developer,那么是使用不了的。原因很简单,pl/sql 是32位的,而所安装的oracle为64位的。当然,如果再安装一个32位的客户端工具,那么就可以使用了。但是,仅仅为使用pl/sql而安装一个600M左右的oracle客户端,这个代价是不是太大了。

而实际上,pl/sql工具只需要依赖一个叫oci.dll的动态链接库就可以了。然后就是基于tnsname.ora的配置文件,以让pl/sql知道需要以何种方式访问数据库信息,即可以了。那么,哪些东西可以满足这两个条件呢,那就是oracle instant client。

网上的大多数的配置都需要建立developer.bat文件,或者修改环境变量,或者修改注册表。这些修改都对现有的使用方式以及会有潜在的问题,比如本机已有oracle数据库的情况。本文仅从pl/sql本身所支持的信息出发,不修改文件,环境变量以及注册表信息,采用最常用的惯例配置达到让pl/sql自动发现配置信息的目的。

1    首先下载oracle instant client文件,下载地址为 http://download.oracle.com/otn/nt/instantclient/112010/instantclient-basic-win32-11.2.0.1.0.zip。将其解压在某一个目录,暂称之为 F:\plsql\instantclient_11_2目录。

2    打开pl/sql,在tools->Preference->Connection里,修改配置里面的Oracle Home项,将其修改为我们刚才解压的目录。同时修改下面的OCI Library项,将其修改为解压目录\oci.dll。即可。保存配置

3    从别处或者已安装oracle的安装目录copy一个tnsname.ora文件,将其放在 解压目录\NETWORK\ADMIN目录下即可。

经过以上3个步骤,再重新打开pl/sql,我们就会发现pl/sql已经能够自动地从我们刚copy的tnsname.ora文件中读取数据库配置信息了,输入帐号名/密码,就和平时所使用的情况一样了。
这里需要注意的是,pl/sql读取的不是已安装的数据库的tnsnames.ora,而是我们copy过去的新的tnsnames.ora文件。一个系统中有2个tnsnames.ora是不是很难维护,那么还有办法。如下所示.

如果你的电脑是windows 7,windows 8或者windows 2008,那么恭喜你,你可以使用linux中的link,即软连接。何为软连接,这里不再叙述。我们只需要在新的解压目录下的NETWORK\ADMIN目录下,创建一个名为tnsnames.ora的软连接,并连接到64位的oracle下的tnsnames.ora文件,就可以了。这样,修改其中1个,都修改了(实际就是一个文件),就不需要再费心维护2个文件了。以下代码即可(请在cmd下运行):

F:\plsql\instantclient_11_2\NETWORK\ADMIN>mklink tnsnames.ora F:\oracle\product\11.2.0\dbhome_1\NETWORK\ADMIN\tnsnames.ora

这样就创建一个软连接,所有的问题都解决了。

后记:其实道理很简单,在pl/sql里面,我们配置的ORACLE_HOME目录,即解压目录。所以,按照默认的惯例,在ORACLE_HOME\NETWORK\ADMIN\tnsnames.ora即是相应的oracle访问信息配置。我们所做的,只不过按照oracle的配置方式将文件放到正确的地方而已。

使用impdp在同一个数据库之间复制用户数据(转)

之前有同事问如何在一个数据库中复制一个用户信息,即将一个用户下的所有数据复制到另一个用户下,以方便进行开发测试,而不直接操作原有数据。当前,想到如何导出数据再导入之外,还没有其他方法,今天看到一个通过network_link来使用impdp复制数据的方法,可以解决这个问题,并且还不需要将数据先导出到本地中。

以下内容转自:http://tomszrp.itpub.net/post/11835/293879,原文为 使用数据泵复制schema,作者: Thomas Zhang.

impdp 的数据源既可以是expdp 导出来的DMP文件,也可以是一数据库.
通过network_link 参数来指定数据源
schemas 参数说明要复制的用户
remap_schema 参数说明源用户与目标用户的匹配关系
remap_tablepace 来调整原schemas使用的表空间与目标数据库用户要表空间的对应关系。

首先创建一个dblink: 
我是在一个db自身上创建的dblink,用来模拟2个不同的库。同样的道理也说明了一种在同一个库上复制一个schema的方法

继续阅读“使用impdp在同一个数据库之间复制用户数据(转)”

Hibernate中criteria一对多关联查询时distinct的分页和数量问题

数据模型
班级:clazz(id,name,studentList)
学生:student(id,name,address,clazz)

经典查询
查询有地址在成都的班级信息,并分页显示。

一般情况下,以上的条件更多,也更复杂,且查询主体必须从班级入手。那么,使用Hibernate的criteria查询的话,一般情况下,编码如下:

DetachedCriteria criteria = DetachedCriteria.forClass(Clazz,"c");
criteria.createAlias("studentList", "sl");
criteria.add(Restrictions.eq("sl.address", "成都");

//保证Distinct
criteria.setResultTransformer(DetachedCriteria.DISTINCT_ROOT_ENTITY);

//分页
listByCriteria(criteria,page);

单就逻辑本身,看似没有什么问题,且在数据较少(如没有分页数据时),会返回正确的结果。但是一旦出现分页数据时,你就会发现,分页数据是错的。表现结果为page对象所表现的数据总数明确不对,且每页所显示的数据也并不是分页信息中的20条,而是不确定的几条(明显少于默认的20条)。这就表明,在这个查询中,肯定有一步出问题了。

没错,在这个查询中,我们要求返回的主体为班级,即Clazz。但Hibernate出生的sql却并不能如我们所愿,它直接使用连接来组装sql语句,并尝试返回包括学生在类的一个复合对象,然后再组装成班级对象,最后根据集合信息进行distinct操作,最后就形成了不正确的结果。整个操作看起来如下所示:

//第一步:生成sql,使用联接查询
select a.*,b.* from clazz a inner join student b on b.aId = a.id where b.address = '成都'

//第二步:带参数 page信息,查询前20条,返回结果为 page.setTotal(XX条),当页数据条数:20
班级一 李一 成都
班级一 李二 成都
班级一 李三 成都
班级二 李四 成都
班级二 李五 成都
班级三 李六 成都
......
//第三步:组装班级对象,去重,此步操作在hibernate程序中进行,返回结果
班级一
班级二
班级三

//返回结果,实际情况:当前page显示数量:20,实际所看到数量 3!

继续阅读“Hibernate中criteria一对多关联查询时distinct的分页和数量问题”

使用hibernate更新和删除时不能使用关系联接操作

在使用hibernate进行更新时,经常会碰到以下的操作。如将name为xxx的a下的bList的code信息更新为code+'f'。在使用hibernate时,经常会写下以下的hibernate操作:

update b set b.code='f' + b.code where b.a.name='xxx'

然而,这句看似没有错误的hql语句,在hibernate进行运行时,却会产生一个奇怪的现象。在生成的hql中,会在表b后面出现一下奇怪的逗号,会报一个错误的sql解析错误的异常,并且在生成的hql中,所没有出现在链接时所使用的a。

原因在于hibernate在进行更新以及删除时候时,并不支持联接操作,包括含有隐式的联接也是不行的。在相应的hibernate jira界面,可以看到以问题的错误:https://hibernate.onjira.com/browse/HHH-2408。在官方的hibernate手册时,有一条很不起眼的描述。http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/batch.html#batch-direct。描述的描述如下:

15.4. DML-style operations
Some points to note: 
No joins, either implicit or explicit, can be specified in a bulk HQL query. Sub-queries can be used in the where-clause, where the subqueries themselves may contain joins. 

继续阅读“使用hibernate更新和删除时不能使用关系联接操作”

oracle中使用oo4o(vc)添加图片

使用oo4o已经是很多年的事情了,前段时间有同事使用这个东西往oracle中添加图片等blob数据,一直找不到方法。经本人测试,找到一个很简单的方法,现记录如下。

过程就是先添加一个空的blob数据,然后再去修改这个blob数据,在oracle的oo4o的workbook中,也采用了这种方式,不过是源代码的blob填充数据没有使用copyFromFile的方法,而是采用数据读写,这相对于日常存照片文件,还是过于繁琐。本段代码直接使用copyFromFile,简单一点。代码总共不超过10行(核心代码)。

#include "stdafx.h"
#include "obound.h"
#include "ORACL.H"

#include 
using namespace std;

//oracle定义了表为xa,两个字段id和vv,其中id为主键,vv为blob类型。
	OStartup();//启动,必须要

	ODatabase x;
//打开数据库
	x.Open("tnsname", "用户名", "密码");
//取得一个结果集,这个结果集没数据,为了添加使用的
	ODynaset os(x,"select id,vv from xa where 1 = 0");//专门使用1=0不查询任何数据
	os.AddNewRecord();
	os.SetFieldValue("id",i);
	OValue ov;
	ov.SetEmpty();
	os.SetFieldValue("vv", ov);
	os.Update();	
	//以上为添加一个图片为空的记录,下面准备添加图片了。

	os.StartEdit();
	OBlob ob;
	os.GetFieldValue("vv", &ob);//读取数据
	ob.CopyFromFile("d:/x.jpg");//将文件写入blob
	os.Update();
	ob.Close();//关闭blob,必须调用,否则在oshutdown之后,会出现内存出错

	os.Close();//关闭记录集
	x.Close();//关闭会话
	OShutdown();

以上代码相当简单,需要注意的是,由于oracle把所有权力都交由了开发者,开发者必须在分配内存之后,关闭内存。否则就会在运行时出现"内存报错"的情况。以上的close方法,一个都不能少,少一个都会报错,需要注意。
以上代码,在vs2005下运行通过

在windows下未启动oracle服务时访问idle database时出现 protocal adapter error的问题解决(转)

 本文转自:http://www.dbforums.com/oracle/1635283-how-connect-idle-instance-ora10gr1-windows2k.html,原文作者:dayneo.

 现在有一个oracle数据库还未启动,但我要手动地启动它。因此,按理说可以通过连接到一个idle的数据库,但是却发生了以下的错误(这些错误在linux下是不会发生的)

1) sqlplus sys/password@sid as sysdba
which gives
ORA-12514: TNS: listener does not currently know of service requested in connect descriptor
2) set ORACLE_SID=SID
sqlplus sys/password as sysdba
which gives
ORA-12560: TNSrotocol adapter error
3) set ORACLE_SID=SID
sqlplus / as sysdba
which gives 
ORA-12560: TNSrotocol adapter error
That one works on my Linux server by the way....
4) sqlplus "/ as sysdba"
which gives 
ORA-12560: TNSrotocol adapter error

非常让人奇怪的是监听器根本不知道还没有启动的oracle服务,那么如何让监听器知道这个服务呢,或者通过什么样的方式注册这个sid信息?

继续阅读“在windows下未启动oracle服务时访问idle database时出现 protocal adapter error的问题解决(转)”