0

虽然我不允许使用标识列或 HANA序列,但我不得不手动为表生成唯一的自动递增键。这是我的不安全和幼稚的密钥生成过程,它将唯一的计数器存储在表中TABLEKEYS并在每次执行时递增它们:

CREATE PROCEDURE NewKey
(   IN  SeqName   NVARCHAR( 32),
    OUT NewKey    BIGINT
)
AS  rec_exists  INT;
    row_num     INT;
BEGIN
    SELECT SUM(1) INTO rec_exists
    FROM ( SELECT TOP 1 1 FROM TABLEKEYS WHERE "Name" = :SeqName ) T;
    IF :rec_exists IS NULL THEN         
        SELECT COALESCE(SUM(1),0) INTO row_num FROM TABLEKEYS;

        INSERT INTO TABLEKEYS("Code",  "Name",    "U_CurrentKey")
        VALUES               (row_num, :SeqName,  -1            );
    END IF;

    UPDATE TABLEKEYS SET "U_CurrentKey" = "U_CurrentKey" + 1
    WHERE "Name" = :SeqName;

    SELECT "CurrentKey" INTO NewKey FROM TABLEKEYS
    WHERE "Name" = :SeqName;
END;

如何使其可靠,以使其在任何情况下都不会返回两个相同的密钥,即使它被一百个同时连接的密集调用?在 MSSQL Server 中,我应该将其主体包装在事务中并在初始查询中将锁定提示应用于表,但我不知道它们在 HANA 中的类似物。HANA 中是否有办法确保严格按顺序访问表行?

我的程序与 Lars 建议的更正并适用于 Business One 用户定义的表:

CREATE PROCEDURE GTGetNewKeyInt
(   IN  TableName NVARCHAR( 32),
    OUT NewKey    BIGINT
)
AS  cur_key     INT;
    row_num     INT;
    row_num_txt VARCHAR(8);
BEGIN
    BEGIN
        DECLARE EXIT HANDLER FOR SQLEXCEPTION
        BEGIN
        END;
        SELECT "U_CurrentKey" INTO cur_key FROM "@GTTABLEKEYS"
        WHERE "Name" = :TableName
        FOR UPDATE;
    END;

    IF :cur_key IS NULL THEN
        LOCK TABLE "@GTTABLEKEYS" IN EXCLUSIVE MODE;
        SELECT COALESCE(SUM(1),0) INTO row_num FROM "@GTTABLEKEYS";
        row_num_txt = LPAD( CAST( row_num AS varchar ), 8, '0' );
        NewKey = 0;
        INSERT INTO "@GTTABLEKEYS"("Code",      "Name",      "U_CurrentKey")
        VALUES                    (row_num_txt, :TableName,  :NewKey       );
    ELSE
        NewKey = :cur_key + 1;
        UPDATE "@GTTABLEKEYS" SET "U_CurrentKey" = :NewKey
        WHERE "Name" = :TableName;
    END IF;
END;
4

1 回答 1

1

首先:不使用序列或 IDENTITY 列等内置功能似乎不是一个好主意。

你在这里建立自己的任何东西,在一个或另一个方面都会逊色。但是,嘿,这毕竟是你的代码。

因此,对于锁定选择,有标准的 SQL 命令

SELECT ... FOR UPDATE FROM...

(另请参阅此处的文档)

您的程序逻辑将是

  1. 选择 ... 更新
  2. 做你必须做的事
  3. 更新序列表
  4. 提交或回滚

从步骤 1 开始,您的记录将被锁定。为了使整个过程更高效,并将管理序列的性能与实际数据表中的数据量解耦,您可能希望将序列保留在自己的表中(行存储可能是一个好主意,因为您要处理一条记录和大量更新)。这与序列的工作方式非常接近。

于 2016-11-23T16:59:43.963 回答