问题:
Sql Server 企业管理器下的导入导出功能很强大,可以在很多数据库之间互导数据。不过在把Sql Server数据库导入到Oracle数据库时,表名和列名会出现一些大小写的问题。
如:
Sql Server数据库下有一表"T_abcd",包含字段"id"、"name",这样导入到Oracle数据库时,会执行大致如下的DDL语句
create table "T_abcd"
(
"id" number,
"name" varchar2(50)
);
导入完成后,在Oracle数据库中执行sql查询语句
select id, name from t_abcd t;
会出现ORA-00942:表或视图不存在的错误
原因:
在Oracle数据库下,表名和列名默认是不区分大小写的,当需要区分大小写时,可以使用双引号(")把名称引起来,上面的查询语句改为下面的形式,则不会出错
select "id", "name" from "T_abcdE";
但是每次拼接这些标识符,很麻烦,尤其是在高级语言(java、C#)中做这些拼接工作,工作的任务量会直线上升的。
Oracle数据库在默认情况下,大概是这样处理sql语句的,先把sql语句中的字符串全部转换成大写,然后再根据这些大写的表名和列名去基础字典表中查找相应的对象,最后再查询这些对象关联的数据。之所以报ORA-00942:表或视图不存在的错误,是因为在基础字典表中Oracle服务没有找到于指定表名大写形式相同的对象名。
解决办法:
出现问题的原因就是因为在基础字典中的对象名称是以小写的情况存储的(如上例创建表时,表名"T_abcdE"是使用区分大小写的引号引起的,所以表名在基础字典表中也会存为"T_abcdE"),一个很简单的办法就是,把基础字典的表名、列名都改为大写即可。
--查询用户SCOTT下所有名称包含小写字母的表
select *
from sys.obj$ o
where o.obj# in (select t.obj# from sys.tab$ t)
and o.owner# = (select u.user# from sys.user$ u where u.name = 'SCOTT')
and o.name != upper(o.name)
--把用户SCOTT下所有包含小写字母的表名改为大小形式
update sys.obj$ o
set o.name = upper(o.name)
where o.obj# in (select t.obj# from sys.tab$ t)
and o.owner# = (select u.user# from sys.user$ u where u.name = 'SCOTT')
and o.name != upper(o.name)
--查询用户SCOTT下所有名称包含小写字母的列
select * from sys.col$ c
where exists (select *
from sys.obj$ o
where o.obj# = c.obj#
and o.owner# =
(select u.user# from sys.user$ u where u.name = 'SCOTT'))
and c.name != upper(c.name)
--把用户SCOTT下所有包含小写字母的列名修改为大写形式
update sys.col$ c
set c.name = upper(c.name)
where exists (select *
from sys.obj$ o
where o.obj# = c.obj#
and o.owner# =
(select u.user# from sys.user$ u where u.name = 'SCOTT'))
and c.name != upper(c.name)
--Oracle在启动时会把,这些基础字典的数据加载到缓冲区,所以需要
--更新缓冲区或者重新启动Oracle服务,这些名称才会生效,更新缓冲区的sql语句为
ALTER SYSTEM FLUSH SHARED_POOL;
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SYSTEM FLUSH GLOBAL CONTEXT;