同时使用数据库链和序列时的注意事项
一般情况下,如果在一个语句中同时包含数据库链和序列,会有潜在的问题,但是Oracle的官方文档在这里并不是很清楚。
以下示例用于说明包括数据库链和序列在内的几种情况。
首先,您需要构建一个测试环境(注意:两个数据库的GLOBAL_NAMES都是真的):
SQL > conn Scott/Tiger @ Yangtk
已连接。
SQL >创建表test_on_yangtk (id号);
表已经创建。
SQL >插入到test_on_yangtk值(1);
已创建1行。
SQL >提交;
提交完成。
SQL >创建序列seq _ on _ yangtk
序列已创建。
SQL > Connyangtk/yangtk @ test 4
已连接。
SQL >创建表test_on_test4 (id号);
表已经创建。
SQL > insert into test _ on _ test 4值(1);
已创建1行。
SQL >提交;
提交完成。
SQL >创建序列seq _ on _ test4
序列已创建。
SQL >创建数据库链接yangtk连接到tiger使用“yangtk”标识的scott
数据库链接已创建。
对于简单的查询语句,可以分为以下四种情况。
1.从本地表中读取数据,并参考本地序列。
SQL > select seq _ on _ test 4 . nextval from test _ on _ test 4;
NEXTVAL
-
1
2.当从本地表读取数据但访问远程序列时,需要在序列后添加数据库链名称。
SQL > select seq _ on _ yangtk . nextval @ yangtk from test _ on _ test 4;
NEXTVAL
-
1
3.读取远程数据表中的数据,同时访问远程序列。
SQL > select seq _ on _ yangtk . nextval @ yangtk from test _ on _ yangtk @ yangtk;
NEXTVAL
-
2
4.读取远程数据表中的数据,但访问本地序列。
SQL > select seq _ on _ test 4 . nextval from test _ on _ yangtk @ yangtk;
NEXTVAL
-
2
经过测试,这四个条件工作正常。
接下来,让我们考虑分布式事务——以INSERT INTO SELECT为例。
由于插入的表可以是本地表,也可以是远程表,因此在每种情况下,相应的子查询语句可能包含上述四种情况。下面我们分别具体分析一下
1。插入本地表。
1.从局部表中读取数据并引用局部序列。
SQL > insert into test _ on _ test4 select seq _ on _ test4 . nextval from test _ on _ test4;
已创建1行。
SQL >回滚;
回滚已完成。
2.从本地表中读取数据,但访问远程序列
SQL > insert into test _ on _ test 4 select
seq _ on _ yangtk . nextval @ yangtk from test _ on _ test 4;
已创建1行。
SQL >回滚;
回滚已完成。
3.读取远程数据表中的数据,同时访问远程序列。
SQL > insert into test _ on _ test 4 select seq _ on _ yangtk . nextval @ yangtk from test _ on _ yangtk @ yangtk;
已创建1行。
SQL >回滚;
回滚已完成。
4.读取远程数据表中的数据,但访问本地序列。
SQL > insert into test _ on _ test 4 select
seq _ on _ test 4 . nextval from test _ on _ yangtk @ yangtk;
已创建1行。
SQL >回滚;
回滚已完成。
经过测试,插入本地表有四种情况,没有错误
二、插入远程表。
1.从局部表中读取数据并引用局部序列。
SQL > insert into test _ on _ yangtk @ yangtk select
seq _ on _ test 4 . nextval from test _ on _ test 4;
INSERT INTO TEST _ ON _ YANGTK @ YANGTK SELECT
SEQ _ ON _ TEST 4。next val FROM TEST _ ON _ TEST4
*
错误在第一行:
ORA-02289:序列(编号)不存在
ORA-02063:紧跟在第一行之后(来自TEST4)
ORA-02063:紧跟在第二行之后(来自YANGTK)
2.从本地表中读取数据,但访问远程序列
SQL > insert into test _ on _ yangtk @ yangtk
select seq _ on _ yangtk . nextval @ yangtk from test _ on _ test 4;
已创建1行。
SQL >回滚;
回滚已完成。
3.读取远程数据表中的数据,同时访问远程序列。
SQL > insert into test _ on _ yangtk @ yangtk
select seq _ on _ yangtk . nextval @ yangtk from test _ on _ yangtk @ yangtk;
已创建1行。
SQL >回滚;
回滚已完成。
4.读取远程数据表中的数据,但访问本地序列。
SQL > insert into test _ on _ yantk @ yantk select seq _ on _ test 4 . nextval from test _ on _ yantk @ yantk;
INSERT INTO TEST _ ON _ YANGTK @ YANGTK SELECT SEQ _ ON _ TEST4。next val FROM TEST _ ON _ YANGTK @ YANGTK
*
错误在第一行:
ORA-02289:序列(编号)不存在
ORA-02063:紧跟在第一行之后(来自TEST4)
ORA-02063:紧跟在第二行之后(来自YANGTK)
根据测试,第一种情况和第四种情况具有相同的误差。
在与所有其他未报告错误的情况进行比较后,可以得出结论,当插入远程数据表并使用本地序列时,将会出现错误。
Oracle的错误文档对2289错误的描述如下:
ORA-02289序列不存在
原因:指定的序列不存在,
或者用户没有执行此操作所需的
权限。
操作:确保序列名称正确,
并且您有权对此序列执行
所需的操作。
根据当前的错误和Oracle给出的原因,初步怀疑这个插入远程数据表的分布式事务实际上是在远程端执行的。因此,YANGTK上的scott用户找不到序列SEQ_ON_TEST4。
将数据库链添加到yangtk上的scott用户到TEST4上的YANGTK用户。
SQL > conn Scott/Tiger @ Yangtk
已连接。
SQL >创建数据库链接test4使用“test4”连接到由yangtk标识的
yangtk;
数据库已创建。
SQL > Connyangtk/yangtk @ test 4
已连接。
SQL > insert into test _ on _ yantk @ yantk select
seq _ on _ test 4 . nextval from test _ on _ test 4;
已创建1行。
SQL >回滚;
回滚已完成。
SQL > insert into test _ on _ yantk @ yantk select
seq _ on _ test 4 . nextval from test _ on _ yantk @ yantk;
已创建1行。
SQL >回滚;
回滚已完成。
数据库链建立后,重新执行错误的语句,这次执行没有错误。
总结:
如果在一个语句中同时使用数据库链和序列,需要注意的是,目前可能不仅需要一个到远端的数据库链,还需要一个从远端到本地的数据库链。
位律师回复
0条评论