在Teradata中为具有一对一关系的表插入策略

时间:2018-01-18 11:09:24

标签: sql teradata etl

在我们的数据模型(源自Teradata行业模型)中,我们观察到一种常见模式,其中逻辑数据模型中的超类和子类关系转换为父表和子表之间的一对一关系。

我知道您可以汇总或汇总属性以最终得到一个表,但我们并没有整体使用此选项。最后我们得到的是这样一个模型:

enter image description here

City Id引用地理区域ID。

我正在努力采用一种好的策略来加载这些表中的记录。

选项1:我可以选择最大值(地理区域ID)并计算批次插入的下一个ID并将其重新用于城市表。

选项2:我可以使用地理区域表中的标识列,并在插入每条记录后将其检索,以便将其用于City表。

还有其他选择吗?

我需要在性能,可靠性和维护方面评估解决方案。

任何评论都将不胜感激。

亲切的问候,

保罗

1 个答案:

答案 0 :(得分:1)

当您说"将记录加载到这些表格中时,您是在谈论一次性数据迁移还是为新地理区域/城市创建记录的功能?

如果您正在寻找代理键并且ID值中存在间隙,那么请使用IDENTITY列并指定NO CYCLE子句,因此它不会重复任何数字。然后只需为值传递NULL,让TD处理它。

如果您确实需要顺序ID,那么您可以只维护一个单独的" NextId"表并使用它来生成ID值。这是最灵活的方式,可以让您更轻松地管理BATCH操作。它需要您更多的代码/维护,但比在数据表上执行MAX()+ 1以获得下一个ID值更有效。这是基本的想法:

BEGIN TRANSACTION

  • 获取" next"查找表中的ID
  • 使用该值为您的下一条记录生成新的ID值
  • 创建新记录
  • 更新" next"查找表中的ID值,并按新插入的#行递增(您可以通过在执行INSERT / MERGE语句后直接将值存储在ACTIVITY_COUNT值变量中来捕获此值)
  • 确保在交易开始时锁定查找表,以便在事务完成之前修改它

END TRANSACTION

这是Postgres的一个例子,你可以适应TD:

CREATE TABLE NextId (
    IDType VARCHAR(50) NOT NULL,
    NextValue INTEGER NOT NULL,
    PRIMARY KEY (IDType)
);

INSERT INTO Users(UserId, UserType)
SELECT 
    COALESCE(
        src.UserId, -- Use UserId if provided (i.e. update existing user)
        ROW_NUMBER() OVER(ORDER BY CASE WHEN src.UserId IS NULL THEN 0 ELSE 1 END ASC) + 
        (id.NextValue - 1) -- Use newly generated UserId (i.e. create new user)
    )
    AS UserIdFinal,
    src.UserType
FROM (
    -- Bulk Upsert (get source rows from JSON parameter)
    SELECT src.FirstName, src.UserId, src.UserType
    FROM JSONB_TO_RECORDSET(pUserDataJSON->'users') AS src(FirstName VARCHAR(100), UserId INTEGER, UserType CHAR(1))
) src
CROSS JOIN ( 
    -- Get next ID value to use
    SELECT NextValue
    FROM NextId 
    WHERE IdType = 'User'
    FOR UPDATE -- Use "Update" row-lock so it is not read by any other queries also using "Update" row-lock
) id
ON CONFLICT(UserId) DO UPDATE SET
UserType = EXCLUDED.UserType;

-- Increment UserId value
UPDATE NextId
SET NextValue = NextValue + COALESCE(NewUserCount,0)
WHERE IdType = 'User'
;   

只需将锁定语句更改为Teradata语法(LOCK TABLE NextId FOR WRITE),并在INSERT / MERGE之后添加ACTIVITY_COUNT变量以捕获受影响的#行。这假设您在存储过程中执行了所有这些操作。

让我知道它是怎么回事......