如果数据库的GLOBAL_NAME中包含'-',就可能导致通过数据库链创建的物化视图、视图和同义词出现这个错误。
重现一下这个错误:
SQL> CONN yangtk/yangtk@192.25.1.103/ora11g_p.ytk_thinkpad
已连接。
SQL> CREATE DATABASE LINK TEST101
2 USING '192.25.1.101/TEST101';
数据库链接已创建。
SQL> SELECT * FROM DUAL@TEST101;
D
-
X
SQL> CREATE SYNONYM MY_DUAL FOR DUAL@TEST101;
同义词已创建。
SQL> SELECT * FROM MY_DUAL;
SELECT * FROM MY_DUAL
*
第 1 行出现错误:
ORA-02083: 数据库名含有非法字符 '-'
可以看到,直接访问DUAL@TEST101是没有问题的,但是通过同义词等这种创建到数据库中的对象进行访问,就会出现ORA-2083错误。
这是由于GLOBAL_NAME中包含了'-',从而导致数据库链和创建的对象都包含了'-'字符,使得最终访问对象时报错。
SQL> SELECT * FROM GLOBAL_NAME;
GLOBAL_NAME
-----------------------------------------------------------------------------------------
ORA11G.YTK-THINKPAD
SQL> SELECT DB_LINK FROM USER_DB_LINKS;
DB_LINK
------------------------------
TEST101.YTK-THINKPAD
SQL> SELECT * FROM USER_SYNONYMS;
SYNONYM_NAME TABLE_OWNER TABLE_NAME DB_LINK
--------------- --------------- ------------------------------ --------------------------
MY_DUAL DUAL TEST101.YTK-THINKPAD
解决这个错误的根本办法是修改GLOBAL_NAME,当然如果数据库的GLOBAL_NAMES参数为FALSE,可以在创建数据库链的时候人为添加一个后缀,避免数据库链中包含'-':
SQL> SHOW PARAMETER GLOBAL_NAMES
NAME TYPE VALUE
------------------------------------ ----------- ------------------------
global_names boolean FALSE
SQL> CREATE DATABASE LINK TEST101.YTK
2 USING '192.25.1.101/TEST101';
数据库链接已创建。
SQL> CREATE OR REPLACE SYNONYM MY_DUAL
2 FOR DUAL@TEST101.YTK;
同义词已创建。
SQL> SELECT * FROM MY_DUAL;
D
-
X
查询METALINK文档,发现Doc ID: Note:331169.1对这个问题进行比较详细的描述,不过Oracle给出的方法也是更新GLOBAL_NAME:
SQL> DROP DATABASE LINK TEST101;
数据库链接已删除。
SQL> ALTER DATABASE RENAME GLOBAL_NAME TO ORA11G.YTK_THINKPAD;
数据库已更改。
SQL> CREATE DATABASE LINK TEST101
2 USING '192.25.1.101/TEST101';
数据库链接已创建。
SQL> CREATE OR REPLACE SYNONYM MY_DUAL
2 FOR DUAL@TEST101;
同义词已创建。
SQL> SELECT * FROM MY_DUAL;
D
-
X
SQL> SELECT * FROM GLOBAL_NAME;
GLOBAL_NAME
------------------------------------------------------------------------------------------
ORA11G.YTK_THINKPAD
SQL> SELECT DB_LINK FROM USER_DB_LINKS;
DB_LINK
------------------------------
TEST101.YTK
TEST101.YTK_THINKPAD
SQL> SELECT * FROM USER_SYNONYMS;
SYNONYM_NAME TABLE_OWNER TABLE_NAME DB_LINK
--------------- --------------- ------------------------------ ---------------------------
MY_DUAL DUAL TEST101.YTK_THINKPAD