获取插入 Snowflake Datawarehouse 中的行的标识
Get identity of row inserted in Snowflake Datawarehouse
如果我有一个带有自动递增 ID 列的 table,我希望能够在该 table 中插入一行,并获取我刚才的行的 ID创建。我知道一般来说,Whosebug 问题需要某种尝试过的代码或研究工作,但我不确定从哪里开始使用 Snowflake。我已经通过他们的 documentation 进行了挖掘,但我对此一无所获。
到目前为止我能做的最好的就是尝试 result_scan()
和 last_query_id()
,但是这些并没有给我关于插入行的任何相关信息,只是确认插入了一行.
我相信我要求的是 MS SQL 服务器的 SCOPE_IDENTITY()
功能。
MS SQL 服务器的 SCOPE_IDENTITY()
是否有 Snowflake 等效功能?
编辑:为了这里有代码:
CREATE TABLE my_db..my_table
(
ROWID INT IDENTITY(1,1),
some_number INT,
a_time TIMESTAMP_LTZ(9),
b_time TIMESTAMP_LTZ(9),
more_data VARCHAR(10)
);
INSERT INTO my_db..my_table
(
some_number,
a_time,
more_data
)
VALUES
(1, my_time_value, some_data);
我想为我刚刚插入的这一行获取自动增量 ROWID
。
注意:在极少数情况下,下面的答案可能不是 100% 正确,请参阅下面的更新部分
原回答
Snowflake 不提供相当于今天 SCOPE_IDENTITY
的功能。
但是,您可以利用 Snowflake 的 time travel 在执行给定语句后立即检索列的最大值。
这是一个例子:
create or replace table x(rid int identity, num int);
insert into x(num) values(7);
insert into x(num) values(9);
-- you can insert rows in a separate transaction now to test it
select max(rid) from x AT(statement=>last_query_id());
----------+
MAX(RID) |
----------+
2 |
----------+
你也可以将 last_query_id()
保存到一个变量中,如果你想稍后访问它,例如
insert into x(num) values(5);
set qid = last_query_id();
...
select max(rid) from x AT(statement=>$qid);
注意 - 它通常是正确的,但如果用户,例如手动向 rid
中插入一个较大的值,它可能会影响此查询的结果。
更新
注意,我意识到上面的代码可能很少会生成错误答案。
由于像 Snowflake
这样的分布式系统中查询的各个阶段的执行顺序可能是不确定的,并且 Snowflake 允许并发 INSERT 语句,因此可能会发生以下情况
- 两个查询,
Q1
和 Q2
,执行简单的单行 INSERT
,大致同时开始
Q1
开始,有点超前
Q2
开始
Q1
从 IDENTITY
列创建一个值为 1
的行
Q2
从 IDENTITY
列创建一个值为 2
的行
Q2
领先于 Q1
- 这是关键部分
Q2
提交,在时间 T2
标记为完成
Q1
提交,在时间 T1
标记为完成
请注意 T1
晚于 T2
。现在,当我们尝试执行 SELECT ... AT(statement=>Q1)
时,我们将看到截至 T1
的状态,包括之前语句的所有更改,因此包括 Q2
的值 2
。这不是我们想要的。
解决方法可能是向每个 INSERT
添加一个 unique identifier
(例如,从一个单独的 SEQUENCE 对象),然后使用 MAX
.
对不起。分布式事务很难:)
如果我有一个带有自动递增 ID 列的 table,我希望能够在该 table 中插入一行,并获取我刚才的行的 ID创建。我知道一般来说,Whosebug 问题需要某种尝试过的代码或研究工作,但我不确定从哪里开始使用 Snowflake。我已经通过他们的 documentation 进行了挖掘,但我对此一无所获。
到目前为止我能做的最好的就是尝试 result_scan()
和 last_query_id()
,但是这些并没有给我关于插入行的任何相关信息,只是确认插入了一行.
我相信我要求的是 MS SQL 服务器的 SCOPE_IDENTITY()
功能。
MS SQL 服务器的 SCOPE_IDENTITY()
是否有 Snowflake 等效功能?
编辑:为了这里有代码:
CREATE TABLE my_db..my_table
(
ROWID INT IDENTITY(1,1),
some_number INT,
a_time TIMESTAMP_LTZ(9),
b_time TIMESTAMP_LTZ(9),
more_data VARCHAR(10)
);
INSERT INTO my_db..my_table
(
some_number,
a_time,
more_data
)
VALUES
(1, my_time_value, some_data);
我想为我刚刚插入的这一行获取自动增量 ROWID
。
注意:在极少数情况下,下面的答案可能不是 100% 正确,请参阅下面的更新部分
原回答
Snowflake 不提供相当于今天 SCOPE_IDENTITY
的功能。
但是,您可以利用 Snowflake 的 time travel 在执行给定语句后立即检索列的最大值。
这是一个例子:
create or replace table x(rid int identity, num int);
insert into x(num) values(7);
insert into x(num) values(9);
-- you can insert rows in a separate transaction now to test it
select max(rid) from x AT(statement=>last_query_id());
----------+
MAX(RID) |
----------+
2 |
----------+
你也可以将 last_query_id()
保存到一个变量中,如果你想稍后访问它,例如
insert into x(num) values(5);
set qid = last_query_id();
...
select max(rid) from x AT(statement=>$qid);
注意 - 它通常是正确的,但如果用户,例如手动向 rid
中插入一个较大的值,它可能会影响此查询的结果。
更新
注意,我意识到上面的代码可能很少会生成错误答案。
由于像 Snowflake
这样的分布式系统中查询的各个阶段的执行顺序可能是不确定的,并且 Snowflake 允许并发 INSERT 语句,因此可能会发生以下情况
- 两个查询,
Q1
和Q2
,执行简单的单行INSERT
,大致同时开始 Q1
开始,有点超前Q2
开始Q1
从IDENTITY
列创建一个值为1
的行Q2
从IDENTITY
列创建一个值为2
的行Q2
领先于Q1
- 这是关键部分Q2
提交,在时间T2
标记为完成
Q1
提交,在时间T1
标记为完成
请注意 T1
晚于 T2
。现在,当我们尝试执行 SELECT ... AT(statement=>Q1)
时,我们将看到截至 T1
的状态,包括之前语句的所有更改,因此包括 Q2
的值 2
。这不是我们想要的。
解决方法可能是向每个 INSERT
添加一个 unique identifier
(例如,从一个单独的 SEQUENCE 对象),然后使用 MAX
.
对不起。分布式事务很难:)