捕获 Teradata 中的插入错误

Capture insert error in Teradata

我有一个存储过程使用以下语句将记录插入我们的 Teradata 数据仓库中的 table:

INSERT INTO UAT_AUDIT_VIEWS.AUDIT_BATCH(
BATCH_KEY
,AUDIT_STATUS_KEY
,BATCH_START_DATETIME
,BATCH_END_DATETIME
,BATCH_OWNER
,BATCH_EXECUTION_START_DATETIME
,BATCH_EXECUTION_END_DATETIME
)
VALUES(
(SELECT COALESCE(MAX(BATCH_KEY),0)+1 FROM UAT_AUDIT_VIEWS.AUDIT_BATCH)
,5 --PENDING
,'1900-01-01 00:00:00'
,'2999-12-31 00:00:00'
,:P_BATCH_OWNER
,CURRENT_TIMESTAMP
,'2999-12-31 00:00:00'
);

请注意,我对主键有唯一性约束 BATCH_KEY。在某些情况下,我的插入语句会失败,因为主键已经存在于 table 中。当它发生时,我希望我的存储过程循环并重试插入直到成功。

我使用以下方法尝试了多种解决方案但未成功:

您能否描述一下您将如何应对这种情况? 这是我为测试它而构建的测试存储过程的简化版本(没有用):

REPLACE PROCEDURE DEV_AUDIT_NEW.ARO_TEST_INSERT()
BEGIN
      DECLARE V_BATCH_KEY_CREATED VARCHAR(100);
      DECLARE V_COUNTER SMALLINT DEFAULT 1;
      DECLARE CONTINUE HANDLER FOR SQLEXCEPTION

      SET V_BATCH_KEY_CREATED = NULL;
      WHILE V_BATCH_KEY_CREATED IS NULL
      DO
            INSERT INTO DEV_AUDIT_NEW.AUDIT_BATCH_TEST_LOG(LOG_DESC) VALUES(V_BATCH_KEY_CREATED);

            INSERT INTO DEV_AUDIT_NEW.AUDIT_BATCH_TEST(BATCH_KEY,BATCH_OWNER) VALUES(V_COUNTER,'B');
            SELECT BATCH_KEY
            INTO :V_BATCH_KEY_CREATED
            FROM DEV_AUDIT_NEW.AUDIT_BATCH_TEST 
            WHERE BATCH_KEY=V_COUNTER AND BATCH_OWNER='B';
            SET V_COUNTER=V_COUNTER+1;

            INSERT INTO DEV_AUDIT_NEW.AUDIT_BATCH_TEST_LOG(LOG_DESC) VALUES(V_BATCH_KEY_CREATED);
      END WHILE;
END;

这条评论太长了。

您当前的方法必须执行完整 Table 扫描以获得 MAX(默认为 table 级别的读锁),但插入默认为行哈希级别的写锁。当您请求写入 table 级别时,它应该可以防止死锁。

当您定义一种序列时 table 每个访问都是 UPI 访问,例如

CREATE SET TABLE Sequences
 (
   SequenceName VARCHAR(128) CHARACTER SET Unicode NOT CaseSpecific NOT NULL,
   nextVal BIGINT NOT NULL DEFAULT 1
 )
UNIQUE PRIMARY INDEX ( SequenceName )
;

REPLACE PROCEDURE NextVal (IN SequenceName VARCHAR(128) CHARACTER SET Unicode, OUT NextVal BIGINT)
BEGIN
   BEGIN REQUEST
      LOCK ROW WRITE
      SELECT nextVal INTO :nextVal FROM Sequences 
      WHERE SequenceName = :SequenceName;

      UPDATE Sequences SET nextVal = nextVal + 1 
      WHERE SequenceName = :SequenceName;
   END REQUEST; 
END;

初始化一个新序列:

INSERT INTO sequences ('mytable', 1);

获取下一个值:

CALL nextVal('mytable', nextval);`

编辑:

您可以使用 BTEQ 轻松测试它,并行记录多个会话,例如到 运行 10 个会话中的 1000 个呼叫:

.set session 10; 
.logon ...; 
select * from sequences where SequenceName = 'mytable';

.repeat 1000
CALL nextVal('mytable', nextval); 

select * from sequences where SequenceName = 'mytable';

观察按顺序返回的值,没有死锁:-)