序列化对 HANA 中 table 行的访问
Serializing access to a table row in HANA
虽然不允许我使用任何一个 identity columns or HANA sequences,但我不得不手动为 table 生成唯一的自动递增键。这是我的不安全和幼稚的密钥生成过程,它在 table 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;
如何使其可靠,使其在任何情况下都不会 return 两个相同的密钥,即使它被一百个同时连接密集调用?在 MSSQL Server 中,我应该将其主体包装在一个事务中,并在初始查询中对 table 应用锁定提示,但我不知道它们在 HANA 中的类似物。 HANA 中有没有办法确保严格按顺序访问 table 行?
我的程序由 Lars 建议修改并适用于 Business One 用户定义 tables:
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;
首先:不使用序列或 IDENTITY 列等内置功能似乎不是一个好主意。
你在这里建造的任何东西,在某一方面都会逊色。
但是,嘿,毕竟这是你的代码。
因此,对于带锁定的选择,有标准的 SQL 命令
SELECT ... FOR UPDATE FROM...
(另请参阅文档 here)
您的程序逻辑将是
- SELECT ...更新
- 做你该做的事
- 更新序列table
- 提交或回滚
从第 1 步开始,您的记录将被锁定。
为了使整个过程更高效,并将管理序列的性能与实际数据中的数据量分离 table,您可能希望将序列保留在其自己的 table(行store 对于这个来说可能是个好主意,因为你处理单个记录和大量更新)。这也非常接近序列的工作方式。
虽然不允许我使用任何一个 identity columns or HANA sequences,但我不得不手动为 table 生成唯一的自动递增键。这是我的不安全和幼稚的密钥生成过程,它在 table 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;
如何使其可靠,使其在任何情况下都不会 return 两个相同的密钥,即使它被一百个同时连接密集调用?在 MSSQL Server 中,我应该将其主体包装在一个事务中,并在初始查询中对 table 应用锁定提示,但我不知道它们在 HANA 中的类似物。 HANA 中有没有办法确保严格按顺序访问 table 行?
我的程序由 Lars 建议修改并适用于 Business One 用户定义 tables:
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;
首先:不使用序列或 IDENTITY 列等内置功能似乎不是一个好主意。
你在这里建造的任何东西,在某一方面都会逊色。 但是,嘿,毕竟这是你的代码。
因此,对于带锁定的选择,有标准的 SQL 命令
SELECT ... FOR UPDATE FROM...
(另请参阅文档 here)
您的程序逻辑将是
- SELECT ...更新
- 做你该做的事
- 更新序列table
- 提交或回滚
从第 1 步开始,您的记录将被锁定。 为了使整个过程更高效,并将管理序列的性能与实际数据中的数据量分离 table,您可能希望将序列保留在其自己的 table(行store 对于这个来说可能是个好主意,因为你处理单个记录和大量更新)。这也非常接近序列的工作方式。