GreenPlum中的序列
Tags: GreenPlumpermission denied for sequence序列权限权限不足
Greenplum数据库序列对象是一个特殊的单行表,用作数字生成器。 您可以使用序列为添加到表中的行生成唯一的整数标识符。 声明SERIAL类型的列会隐式创建一个序列计数器,以便在该表列中使用。
Greenplum数据库提供了创建,更改和删除序列的命令。 Greenplum数据库还提供内置函数来返回序列中的下一个值(nextval())或将序列设置为特定的起始值(setval())。
Note: Greenplum数据库不支持PostgreSQL currval()和lastval()序列函数。
序列对象的属性包括序列的名称,其增量值以及序列计数器的最后,最小和最大值。 序列还有一个名为is_called的特殊布尔属性,用于控制序列计数器上nextval()操作的自动递增行为。 当序列的is_called属性为true时,nextval()会在返回值之前递增序列计数器。 当序列的is_called属性值为false时,nextval()在返回值之前不会递增计数器。
创建一个序列
CREATE SEQUENCE命令使用给定的序列名称和可选的起始值创建和初始化序列。 序列名称必须与同一Schema中任何其他序列,表,索引或视图的名称不同。 例如:
1 | CREATE SEQUENCE myserial START 101; |
创建新序列时,Greenplum数据库将序列is_called属性设置为false。 在新创建的序列上调用nextval()不会递增序列计数器,但会返回序列起始值并将is_called设置为true。
CREATE SEQUENCE 定义一个新的序列生成器。
概要
1 2 3 4 5 6 7 8 | CREATE [TEMPORARY | TEMP] SEQUENCE name [INCREMENT [BY] value] [MINVALUE minvalue | NO MINVALUE] [MAXVALUE maxvalue | NO MAXVALUE] [START [ WITH ] start] [CACHE cache] [[NO] CYCLE] [OWNED BY { table.column | NONE }] |
描述
CREATE SEQUENCE创建一个新的序列生成器。 这涉及创建和初始化新的特殊单行表。 生成器将由发出命令的用户所有。
如果指定了模式名称,则会在指定的模式中创建序列。 否则,它将在当前模式中创建。 临时序列存在于特殊模式中,因此在创建临时序列时可能不会给出模式名称。 序列名称必须与同一模式中任何其他序列,表,索引,视图或外部表的名称不同。
创建序列后,可以使用nextval()函数对序列进行操作。 例如,要将行插入到获取序列的下一个值的表中:
1 | INSERT INTO distributors VALUES (nextval('myserial'), 'acme'); |
您还可以使用函数setval()对序列进行操作,但仅用于不对分布式数据进行操作的查询。 例如,允许以下查询,因为它会重置master上序列生成器进程的序列计数器值:
1 | SELECT setval('myserial', 201); |
但是以下查询在Greenplum数据库中将被拒绝,因为它对分布式数据进行操作:
1 | INSERT INTO product VALUES (setval('myserial', 201), 'gizmo'); |
在常规(非分布式)数据库中,对序列进行操作的函数会转到本地序列表以根据需要获取值。 但是,请记住,在Greenplum数据库中,每个segment都是其自己不同的数据库进程。 因此,segment需要一个真实单点来获取序列值,以便所有segment正确递增,并且序列以正确的顺序前进。 序列服务器进程在master上运行,并且是Greenplum分布式数据库中序列的真实点。 segment在运行时从master获取序列值。
由于这种分布式序列设计,因此在Greenplum数据库中对序列操作的函数存在一些限制:
- lastval()和currval()函数不被支持。
- setval()仅可用于在master上设置序列生成器的值,而不能在子查询中用于更新分布式表数据上的记录。
- 根据查询的不同,nextval()有时会从master获取一个值块以供segment使用。 因此,如果在segment级别不需要所有块,有时可能会跳过序列中的值。 请注意,常规PostgreSQL数据库也可以执行此操作,因此这并不是Greenplum数据库所独有的。
尽管您无法直接更新序列,但可以使用类似以下的查询:
1 | SELECT * FROM sequence_name; |
检查序列的参数和当前状态。 特别是,序列的last_value字段显示了任何会话分配的最后一个值。
参数
TEMPORARY | TEMP
如果指定,则仅为此会话创建序列对象,并在会话退出时自动将其删除。 具有相同名称的现有永久序列在临时序列存在时不可见(在此会话中),除非使用模式限定名称引用它们。
name
要创建的序列的名称(可以由模式指定)。
increment
指定将哪个值添加到当前序列值以创建新值。 正值将形成一个升序,负值将形成一个降序。默认值为1。
minvalue
NO MINVALUE
确定序列可以生成的最小值。 如果未提供此子句或指定了NO MINVALUE,则将使用默认值。 升序和降序的默认值分别为1和-263-1。
maxvalue
NO MAXVALUE
确定序列的最大值。 如果未提供此子句或指定了NO MAXVALUE,则将使用默认值。 升序和降序的默认值分别为263-1和-1。
start
允许序列从任何地方开始。 默认的起始值为升序的最小值和降序的最大值。
cache
指定要预分配多少序号并将其存储在内存中,以加快访问速度。 最小(默认)值为1(无高速缓存)。
CYCLE
NO CYCLE
当达到最大值(递增)或最小值(递减)时,允许序列回绕。 如果达到限制,则生成的下一个数字将是最小值(升序)或最大值(降序)。 如果指定了NO CYCLE,则在序列达到最大值之后,对nextval()的任何调用都将返回错误。 如果未指定,则默认为NO CYCLE。
OWNED BY table.column
OWNED BY NONE
使序列与特定的表列相关联,这样,如果该列(或其整个表)被删除,该序列也将被自动删除。 指定的表必须具有相同的所有者,并且与序列具有相同的模式。 OWNED BY NONE(默认值)指定不存在这种关联。
注解
序列基于bigint算术,因此范围不能超过八字节整数的范围(-9223372036854775808至9223372036854775807)。
尽管保证多个会话分配不同的序列值,但是当考虑所有会话时,这些值可能会不按顺序生成。 例如,会话A可能保留值1..10并返回nextval=1, 然后会话B可能保留值11..20并在会话A生成nextval=2之前返回nextval=11。 因此,您仅应假设nextval()值都是不同的,而不是纯粹按顺序生成它们。 同样,last_value将反映任何会话保留的最新值,无论nextval()是否已返回该值。
示例
创建一个名为myseq的序列:
1 | CREATE SEQUENCE myseq START 101; |
在表中插入一行,以获取名为idseq的序列的下一个值:
1 | INSERT INTO distributors VALUES (nextval('idseq'), 'acme'); |
在master上重置序列计数器值:
1 | SELECT setval('myseq', 201); |
在Greenplum数据库中非法使用setval()(在分布式数据上设置序列值):
1 | INSERT INTO product VALUES (setval('myseq', 201), 'gizmo'); |
兼容性
CREATE SEQUENCE符合SQL标准,但以下情况除外:
- 不支持SQL标准中指定的ASdata_type表达式。
- 使用nextval()函数代替SQL标准中指定的NEXT VALUE FOR表达式来获取下一个值。
- OWNED BY子句是Greenplum数据库扩展。
使用一个序列
使用CREATE SEQUENCE命令创建序列后,可以检查序列并使用序列内置函数。
检查序列属性
要检查序列的当前属性,请直接查询序列。 例如,要检查名为myserial的序列:
1 | SELECT * FROM myserial; |
返回下一个序列计数器值
您可以调用nextval()内置函数来返回并使用序列中的下一个值。 以下命令将名为myserial的序列的下一个值插入名为vendors的表的第一列:
1 | INSERT INTO vendors VALUES (nextval('myserial'), 'acme'); |
nextval()使用序列的is_called属性值来确定在返回值之前是否递增序列计数器。 当is_called为true时,nextval()使计数器前进。 nextval()在返回之前将序列is_called属性设置为true。
nextval()操作永远不会回滚。 即使执行nextval()的事务失败,获取的值也会被使用。 这意味着失败的事务可能会在指定值的序列中留下未使用的漏洞。
Note: 如果在Greenplum数据库中启用了镜像,则不能在UPDATE或DELETE语句中使用nextval()函数。
设置序列计数器值
您可以使用Greenplum数据库setval()内置函数来设置序列的计数器值。 例如,以下命令将名为myserial的序列的计数器值设置为201:
1 | SELECT setval('myserial', 201); |
setval()有两个函数签名:setval(sequence, start_val)和setval(sequence, start_val, is_called)。 setval(sequence, start_val)的默认行为设置序列is_called属性值为true。
如果您不希望序列计数器在下一个nextval()调用时递增, 请使用setval(sequence, start_val, is_called)函数签名,传递false参数:
1 | SELECT setval('myserial', 201, false); |
setval()操作永远不会回滚。
修改一个序列
ALTER SEQUENCE命令更改现有序列的属性。 您可以更改序列的开始,最小,最大和增量值。 您也可以在起始值或指定值处重新启动序列。
未在ALTER SEQUENCE命令中设置的任何参数都保留其先前的设置。
ALTER SEQUENCE sequence START WITH start_value将序列的start_value属性设置为新的起始值。 它对last_value属性或nextval(sequence)函数返回的值没有影响。
ALTER SEQUENCE sequence RESTART 将序列的last_value属性重置为start_value属性的当前值,并将is_called属性重置为false。 对nextval(sequence)函数的下一次调用将返回start_value。
ALTER SEQUENCE sequence RESTART WITH restart_value 将序列的last_value属性设置为新值,将is_called属性设置为false。 下一次调用nextval(sequence)会返回restart_value。 这等效于调用setval(sequence, restart_value, false)。
以下命令在值105处重新启动名为myserial的序列:
1 | ALTER SEQUENCE myserial RESTART WITH 105; |
ALTER SEQUENCE更改一个序列发生器的定义。
概要
1 | ALTER SEQUENCE [ IF EXISTS ] name [INCREMENT [ BY ] increment] [MINVALUE minvalue | NO MINVALUE] [MAXVALUE maxvalue | NO MAXVALUE] [START [ WITH ] start ] [RESTART [ [ WITH ] restart] ] [CACHE cache] [[ NO ] CYCLE] [OWNED BY {table.column | NONE}]ALTER SEQUENCE [ IF EXISTS ] name OWNER TO new_ownerALTER SEQUENCE [ IF EXISTS ] name RENAME TO new_nameALTER SEQUENCE [ IF EXISTS ] name SET SCHEMA new_schema |
描述
ALTER SEQUENCE 更改一个现有序列发生器的参数。任何没有被明确设置的参数在 ALTER SEQUENCE 命中,都要维持他们之前的设置。
用户必须拥有该序列才能使用ALTER SEQUENCE。 要更改一个序列 的模式,用户还必须拥有新模式上的CREATE特权。 注意超级用户自动拥有所有的特权。.
要改变所有者,用户必须是新角色的直接或者间接成员,而且新角色必须在序列的模式上拥有CREATE权限 (这些限制迫使更改所有者不能执行删除和重新创建序列所无法做的任何事情。 但是,超级用户仍然可以更改任何序列的所有权。)
参数
name
要修改的序列的名称(可选方案限定)。
IF EXISTS
如果序列不存在不会抛出错误,而只会触发一次提醒。
increment
子句 INCREMENT BY increment 是可选的。一个正值将产生一个上升序列,一个负值会产生一个下降序列。如果未被指定,则旧的增量值将被保持。
minvalue
NO MINVALUE
可选的子句 MINVALUE minvalue 决定一个序列 能产生的最小值。 如果 NO MINVALUE 被指定, 上升序列和下降序列的默认值分别是 1 和 -263-1。如果这些选项都没有被指定,将保持当前的 最小值。
maxvalue
NO MAXVALUE
可选子句 MAXVALUE maxvalue 决定一个序列 能产生的最大值。 如果 NO MAXVALUE 被指定, 上升序列和下降序列的默认值分别是 263-1 和 -1。如果这些选项都没有被指定,将保持当前的最大值。
start
可选子句START WITH start更改记录的序列起始值。 这对current 序列值没有影响。 它只是设置将来的ALTER SEQUENCE RESTART 命令将使用的值。
restart
可选子句 RESTART [ WITH restart ] 更改序列的当前值。 这等效于使用 is_called = false 调用 setval(sequence, start_val, is_called) 函数。 指定的值将由 nextval(sequence) 函数的下一次调用返回。 在没有 restart 值的情况下写入RESTART等同于提供由 CREATE SEQUENCE 记录或由 ALTER SEQUENCE START WITH 最后设置的开始值。
new_owner
序列新所有者的用户名。
cache
CACHE cache子句中使序列号可以预先分配并存储在内存中,以加快访问速度。 最小值为1(一次只能生成一个值,即没有高速缓存)。 如果未指定,则将保留旧的缓存值
CYCLE
可选的CYCLE关键字可用于在序列由升序或降序达到maxvalue或minvalue时使序列回绕。 如果达到限制,则生成的下一个数字将是各自的minvalue或maxvalue。
NO CYCLE
如果指定了可选的NO CYCLE关键字,则在序列达到最大值后,对nextval()的任何调用都将返回错误。 如果未指定CYCLE或NO CYCLE,则将保留旧的循环行为。
OWNED BY table.column
OWNED BY NONE
OWNED BY选项使序列与特定的表列相关联,这样,如果该列(或其整个表)被删除,该序列也将被自动删除。 如果指定,则此关联替换该序列的任何先前指定的关联。 指定的表必须具有相同的所有者,并且与序列具有相同的架构。 指定OWNED BY NONE会删除任何现有的表列关联。
new_name
序列的新名称。
new_schema
序列的新模式。
注意
为了避免阻塞从同一序列中获取数字的并发事务,永远不会回滚ALTER SEQUENCE对序列生成参数的影响。 这些更改将立即生效,并且不可逆。 但是,OWNED BY, OWNER TO, RENAME TO 和SET SCHEMA子句是普通的目录更新,可以回滚。
ALTER SEQUENCE 不会立即影响除当前会话以外的具有预分配(缓存)序列值的会话中的nextval()结果。 在注意到更改的序列生成参数之前,它们将用尽所有缓存的值。 当前会话将立即受到影响。
由于历史原因, ALTER TABLE 也可以与序列一起使用。 但是序列允许的 ALTER TABLE的唯一变体与上述形式等效。
示例
重启一个被称为serial的序列在105:
1 | ALTER SEQUENCE serial RESTART WITH 105; |
兼容性
ALTER SEQUENCE符合SQL标准,START WITH, OWNED BY, OWNER TO, RENAME TO和 SET SCHEMA子句除外,它们是Greenplum数据库的扩展。
删除一个序列
DROP SEQUENCE命令可以删除序列。 例如,以下命令将删除名为myserial的序列:
1 | DROP SEQUENCE myserial; |
DROP SEQUENCE删除序列。
概要
1 | DROP SEQUENCE [IF EXISTS] name [, ...] [CASCADE | RESTRICT] |
描述
DROP SEQUENCE删除序列生成器表。 您必须拥有删除的序列(或成为超级用户)。
参数
IF EXISTS
如果该序列不存在,请不要报错。在这种情况下会发出通知。
name
要删除的序列的名称(可以由模式指定)。
CASCADE
自动删除依赖于序列的对象。
RESTRICT
如果有任何对象依赖该序列,则拒绝删除该序列。 这是默认值。
示例
删除序列myserial:
1 | DROP SEQUENCE myserial; |
兼容性
DROP SEQUENCE完全符合SQL标准,但该标准仅允许每个命令删除一个序列。 另外,IF EXISTS选项是Greenplum数据库扩展。
将序列指定为列的默认值
除了使用SERIAL或BIGSERIAL类型之外, 您还可以直接在CREATE TABLE命令中引用序列。例如:
1 | CREATE TABLE tablename ( id INT4 DEFAULT nextval('myserial'), name text ); |
您还可以更改表列以将其默认值设置为序列计数器:
1 | ALTER TABLE tablename ALTER COLUMN id SET DEFAULT nextval('myserial'); |
序列回绕
默认情况下,序列不会回绕。 这意味着当一个序列到达了最大值 (SMALLSERIAL的+32767, SERIAL的+2147483647, BIGSERIAL的+9223372036854775807), 再调用nextval()会失败。 可以修改一个序列让它从1开始回绕:
1 | ALTER SEQUENCE myserial CYCLE; |
也可以在创建序列时指定回绕行为:
1 | CREATE SEQUENCE myserial CYCLE; |
报错:ERROR: permission denied for sequence report_seq
ERROR: permission denied for sequence report_seq (entry db 192.110.216.117:5432 pid=46623) Call getNextException to see other errors in the batch
原因:用户权限不足。
解决办法:
1 2 3 4 5 6 | -- 授权单个序列给对应用户即可 GRANT USAGE,SELECT,UPDATE ON SEQUENCE lhrdb.report_seq TO user01; -- 授权所有序列给对应用户即可 GRANT USAGE,SELECT,UPDATE ON ALL SEQUENCES IN SCHEMA public TO user01; |
参考
https://www.bookstack.cn/read/greenplum-admin_guide-6.0-zh/3ba0ac9a80cb1638.md