在Teradata中捕获插入错误

时间:2017-02-20 10:01:22

标签: loops error-handling insert teradata

我有一个存储过程将记录插入Teradata数据仓库中的表中,并带有以下语句:

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有一个unicity约束。在某些情况下,我的insert语句失败,因为主键已存在于表中。当它发生时,我希望我的存储过程循环并重试插入,直到它成功。

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

  • DECLARE CONTINUE HANDLER FOR SQLEXCEPTION以避免插入失败时存储过程失败
  • 重试插入的WHILE DO循环

您能描述一下如何管理这种情况吗? 这是我为测试它而构建的测试存储过程的简化版本(它不起作用):

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;

1 个答案:

答案 0 :(得分:1)

这个评论太长了。

您当前的方法必须执行全表扫描以获取MAX(默认为表级别的读锁定),但Insert默认为在行哈希级别上写锁定。当您在表级请求Write时,它应该防止死锁。

当您定义一种序列表时,每次访问都是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个CALL:

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

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

select * from sequences where SequenceName = 'mytable';

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