我有一个关于父表和子表的外键约束的问题。我有下面的脚本来从远程数据库插入数据。下面是创建表脚本
CREATE TABLE "S695_LANGUAGE"
( "ID" NUMBER(5,0) GENERATED ALWAYS AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE ,
"CODE" NVARCHAR2(5),
"DESCRIPTION" NVARCHAR2(50),
"IS_ACTIVE" NUMBER(1,0) DEFAULT 1
) ;
CREATE TABLE "S695_TEXT_CONTENT"
( "ID" NUMBER(19,0),
"TEXT_CONTENT_ID" NVARCHAR2(500)
);
CREATE TABLE "S695_TRANSLATIONS"
( "ID" NUMBER(19,0) GENERATED ALWAYS AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE ,
"TEXT_CONTENT_ID" NUMBER(19,0),
"LANGUAGE_ID" NUMBER(5,0),
"TRANSLATION" NVARCHAR2(500)
)
ALTER TABLE "S695_LANGUAGE" MODIFY ("ID" NOT NULL ENABLE);
ALTER TABLE "S695_LANGUAGE" ADD CONSTRAINT "S695_LANGUAGE_PK" PRIMARY KEY ("ID");
ALTER TABLE "S695_TEXT_CONTENT" ADD CONSTRAINT "S695_TEXT_CONTENT_PK" PRIMARY KEY ("ID");
ALTER TABLE "S695_TRANSLATIONS" MODIFY ("ID" CONSTRAINT "S695_TRANSLATIONS_CK_ID_NOT_NULL" NOT NULL ENABLE);
ALTER TABLE "S695_TRANSLATIONS" ADD CONSTRAINT "S695_TRANSLATIONS_PK" PRIMARY KEY ("ID");
ALTER TABLE "S695_TRANSLATIONS" ADD CONSTRAINT "S695_TRANSLATIONS_TEXT_CONTENT_ID_FK" FOREIGN KEY ("TEXT_CONTENT_ID")
REFERENCES "S695_TEXT_CONTENT" ("ID") ENABLE;
ALTER TABLE "S695_TRANSLATIONS" ADD CONSTRAINT "S695_TRANSLATIONS_LANGUAGE_FK" FOREIGN KEY ("LANGUAGE_ID")
REFERENCES "S695_LANGUAGE" ("ID") ENABLE;
Here the language table and translation table have a constraint relationship on language id field.
DECLARE
v_seq_name VARCHAR2(20);
v_str VARCHAR2(200);
v_val NUMBER;
v_Nederlands_LanguageId NUMBER(5);
v_French_LanguageId NUMBER(5);
v_English_LanguageId NUMBER(5);
v_Deutsch_LanguageId NUMBER(5);
v_TextContent_Id NUMBER(19);
V_MAX_TEXT_CONTENT_ID NUMBER(19);
BEGIN
SELECT
sequence_name
INTO v_seq_name
FROM
user_tab_identity_cols@DBLINK1
WHERE
table_name = 'S695_LANGUAGE';
v_str := 'select '
|| v_seq_name
|| '.nextval@DBLINK1 from dual';
dbms_output.put_line('v_str = ' || v_str);
EXECUTE IMMEDIATE v_str
INTO v_Nederlands_LanguageId;
dbms_output.put_line('Value = ' || v_val);
INSERT INTO s695_language@DBLINK1 (
code,
description,
is_active
) VALUES (
'NL',
'NEDERLANDS',
'1'
);
INSERT INTO s695_RESERVATION_language@DBLINK2 (
id,
code,
description,
is_active
) VALUES (
v_Nederlands_LanguageId,
'NL',
'NEDERLANDS',
'1'
);
-- Channel
--commit;
SELECT S695_TEXT_CONTENT_SEQ.NEXTVAL@DBLINK1 INTO v_TextContent_Id FROM DUAL;
INSERT INTO S695_TEXT_CONTENT@DBLINK1 (ID,TEXT_CONTENT_ID) VALUES(v_TextContent_Id,CONCAT(u'TextContent_',v_TextContent_Id));
select max(id) into V_MAX_TEXT_CONTENT_ID from S695_TEXT_CONTENT@DBLINK1;
INSERT INTO S695_RESERVATION_TEXT_CONTENT@DBLINK2 (ID,TEXT_CONTENT_ID) VALUES(V_MAX_TEXT_CONTENT_ID,CONCAT(u'TextContent_',V_MAX_TEXT_CONTENT_ID));
INSERT INTO S695_TRANSLATIONS@DBLINK1(TEXT_CONTENT_ID,LANGUAGE_ID,TRANSLATION) VALUES(V_MAX_TEXT_CONTENT_ID,v_Nederlands_LanguageId,u'MobileApp');
INSERT INTO S695_RESERVATION_TRANSLATIONS@DBLINK2(TEXT_CONTENT_ID,LANGUAGE_ID,TRANSLATION) VALUES(V_MAX_TEXT_CONTENT_ID,v_Nederlands_LanguageId,u'MobileApp');
INSERT INTO S695_CHANNEL@DBLINK1(CODE,DESCRIPTION,TEXT_CONTENT_ID,IS_ACTIVE) VALUES (u'MO', u'MobileApp', V_MAX_TEXT_CONTENT_ID, 1);
INSERT INTO S695_RESERVATION_CHANNEL@DBLINK2 (CODE,DESCRIPTION,TEXT_CONTENT_ID,IS_ACTIVE) VALUES (u'MO', u'MobileApp', V_MAX_TEXT_CONTENT_ID, 1);
commit;
--rollback;
END;
/
分布式更新操作失败;需要回滚。ORA-02291:已违反完整性约束(S695_TRANSLATIONS_LANGUAGE_FK)-找不到父项。
它看起来像插入到语言表没有提交,因为它给了一个外键约束违反。(我认为)
1条答案
按热度按时间vsdwdz231#
被违反的外键是:
使用时:
它将当前序列值递增1并返回该值。
执行
INSERT
时:然后自动生成
ID
列,它将序列号再增加1并插入新值。然后,当您插入转换表时,您使用的序列值是手动生成的,并且不等于插入表中的值,因此您试图引用错误的
id
值。使用
RETURNING ... INTO
:但是,
RETURNING ... INTO
子句可能不受DB链路的支持。要解决这个问题,可以在远程数据库上创建一个过程,并在该过程中使用
RETURNING ... INTO ...
,这样就不必使用DB链接(除了调用该过程)。另一种方法是用途:
插入到语言表后得到当前序列值。
如果你有一个小批量的插入从一个单一的用户,那么这可能会工作;然而,如果你有来自多个用户的插入,并且它们几乎同时发生,那么你可能会发现两个用户同时执行
INSERT
到语言表中,序列号增加两次,当他们读取当前值时,他们都得到相同的序列值。用一种健壮的方式来解决这个问题可能会更好,使用RETURNING ... INTO
,而不是使用一种只在某些环境中有效的方法。