Oracle 11gR2 Exadata
我需要唯一标识何时创建记录。序列缓存意味着我不能使用基于序列的 ID,而批量插入意味着在一个批次中插入的所有记录都将具有相同的时间戳值(即使使用 TIMESTAMP(9))。类似于 Twitter 的since_id 概念。
到目前为止我想到的最好的选择
这是我的要求:我有一个 API,它允许用户提供一个序列作为标记并请求自那时以来的所有记录。例如,他们请求 1000 条标记为 7 的记录,他们将从我的表中获得 1000 条 ID 大于 1007 的记录。例如,假设返回的 1000 条记录的数字最大 ID 是 2045,因此我们返回 2045 作为标记 后来客户端请求 1000 条记录,标记为 2045,期望获得下一批 1000 条记录和一个新标记。
一种非常简单的方法,允许他们获取适合他们的任何大小的所有记录而不会丢失任何记录。但是,由于跨多个 Exadata 节点的序列缓存,在客户端请求 1000 条标记为 1007 的记录时,可能尚未创建 ID 为 2020 的记录。因此,当他们使用标记 2045 执行下一个请求时,他们将永远错过记录 2020。使用 ID 获取关联记录的时间戳可以解决这个问题,但是我必须确保始终将记录单独插入表中以保证唯一的时间戳。
假设:
希望我只是没有找到正确的术语来搜索现有答案。我觉得这是一个多年来应该通过某些模式解决的问题。我认为 Twitter 已经解决了它......
我有一个带OrderSequence列的表。该架构大致如下所示:
id
Name
OrderSequence
Run Code Online (Sandbox Code Playgroud)
我有一个来自应用程序的 id ["1", "2", "3", "4"] 数组,我想设置 id 以OrderSequence进行排序。我不想遍历应用程序中的行,一次执行 'n' 个 SQL 查询。如何使用存储过程执行此操作?
样本数据
id Name OrderSequence
1 A 0
2 B 0
3 C 0
Run Code Online (Sandbox Code Playgroud)
想要的结果
id Name OrderSequence
1 A 1
2 B 2
3 C 3
Run Code Online (Sandbox Code Playgroud) ROWID仅插入表时假设顺序或升序有多安全?为什么?
我遇到过一种情况,我必须验证是否将新记录添加到没有用作参考的序列或日期列的表中。我发现ROWID最近添加的记录高于所有相关记录。因此我假设它们比参考记录更旧。然而,环顾网络,似乎有一些关于ROWID,有些甚至声称这ROWID甚至不能保证是恒定的!
我知道依赖ROWIDfor 顺序可能不是一个好主意,但这让我思考:在使用语句和仅插入时ROWID,关于值的顺序和变化提供了什么保证DELETE。oracle 有没有详细说明这些要点的官方文档?另外,ROWID在表级别或数据库级别是唯一的吗?
我想防止显式插入串行列。我想到了以下触发器:
drop table test_table;
create table test_table(
id bigserial primary key,
foobar text
);
create or replace function serial_id_check() returns trigger as
$$
begin
if new.id != currval(TG_TABLE_NAME||'_id_seq') then
raise exception 'Explicit insert into serial id, currval = %, tried to insert = %', currval(TG_TABLE_NAME||'_id_seq'), new.id;
end if;
return new;
end;
$$ language plpgsql;
create trigger test_table_serial_id_check
before insert on test_table
for each row
execute procedure serial_id_check();
Run Code Online (Sandbox Code Playgroud)
也许有更好的方法?也许这种方法被打破了,这根本无法实现?
PS 我也考虑不授予插入和更新的权限,而只授予 pgplsql 插入/更新程序的权限 - 但这种方法现在对我来说是不可能的。
每次在下表中添加新行时,我希望序列(Import Permit No)在新的一年中增加1....20160001、20160002等并重置为20170001、20170002等。
CREATE TABLE [dbo].[tblPermits](
[ImportPermitID] [int] IDENTITY(1,1) NOT NULL,
[ImportPermitNo] [nchar](20) NULL,
[ImporterName] [int] NULL,
[Province] [varchar](50) NULL,
[LodgementDate] [datetime] NULL,
[PortofEntry] [int] NOT NULL,
[EstDateofArrival] [datetime] NULL,
[ConsignmentInvoicePONo] [varchar](50) NULL,
[OtherImportConditions] [varchar](400) NULL,
[Supplier] [int] NOT NULL,
[SupplierCountry] [varchar](50) NULL,
[CountryofOrigion] [int] NOT NULL,
CONSTRAINT [PK_tblPermits] PRIMARY KEY CLUSTERED
(
[ImportPermitID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)
目前我拥有的是一个触发器,如下所示。
ALTER TRIGGER …Run Code Online (Sandbox Code Playgroud) 我需要复制同一个表中的记录,只更改一个字段。我的表有默认生成的序列entry_id_seq,但是我不确定id列是 SERIAL(如何检查?)。
\d tab 只返回这个
Column | Type | Modifiers
-----------------+--------------------------------+------------------------
id | integer | not null
...
Indexes:
"tab_entry_pkey" PRIMARY KEY, btree (id)
Run Code Online (Sandbox Code Playgroud)
所以问题是:当我尝试以简化的方式复制记录时:
insert into tab_entry select * from tab_entry where id = 3052;
Run Code Online (Sandbox Code Playgroud)
它抛出错误
ERROR: duplicate key value violates unique constraint "tab_entry_pkey"
DETAIL: Key (id)=(3052) already exists.
Run Code Online (Sandbox Code Playgroud)
默认情况下,默认序列不会生成下一个值。是否有任何简洁的语法允许在没有完整表规范的情况下插入和更改单个字段FROM tab(col1, col2, col3, ..., col N)?
该表有很多字段,所以我不想把它们都写出来,因为这会影响代码的可读性。我想要这样的东西,但这种语法不起作用
insert into tab_entry(id, *) select nextval('seq'), * from tab_entry where id = 3052;
Run Code Online (Sandbox Code Playgroud)
SELECT …
我在 sys.sequences 中出现的 SQL Server 2012 数据库中有一个序列。如何确定哪些表使用此序列?我没有足够的权限来查看此系统视图的定义,因此无法四处寻找线索。
我已经用 Postgres 玩了一个星期左右,我正在看看是否可以使用表达式设置序列的最小值/最大值。具体目标是为服务器之间的不相交范围自动创建脚本,以避免多主设置中的密钥冲突。
例如,使用 psql:
CREATE SEQUENCE key_seq MINVALUE (:servernum * :stride)
MAXVALUE ((:servernum + 1) * :stride - 1);
Run Code Online (Sandbox Code Playgroud)
这给了我一个语法错误。变量是逐字内插的,不进行计算。
另一种方法是根据表达式的输出设置变量:
\set minvalue (:servernum * :stride)
Run Code Online (Sandbox Code Playgroud)
但该\set语句不计算表达式。
所以是一个 postgres 数据库(特别是一个 AmazonRDS 实例 fwiw)。
安排事情以获取任何记录的最后更新(或创建)时间很容易。
该信息将是日期时间。
我想要实现的是:想象一个整数,sequenceNumber,它对数据库来说是原子的和全局的。
简单地说,每个表都会有一个 sequenceNumber 字段。
任何时候任何记录(即,在任何表中)被更新(或创建),它都会获得下一个序列号。
您知道如何拥有对数据库一无所知的程序员朋友。海浪。我的白痴解决方案是,在整个代码库中,每次创建或修改记录时,一定要记得更新它的序列号。(当然,只需要一个全局系统来给出下一个原子序列号。)
对此的声音解决方案是什么?
事实上,它是否已经以某种我不知道的方式完全可用,或者?
在 PostgreSQL 中,由于本文/sf/ask/698893751/中提到的原因,序列被设计为有间隙。我的问题是:是否可以通过定期(假设每天一次)检查哪些序列号未使用并将其添加回序列中以供使用,从而使序列几乎无间隙?
我假设当前 postgres 实现了一个序列作为计数器,每次访问它时它都会递增。相反,它可以通过自由值列表和计数器来实现。该序列将按如下方式工作:
# python style pseudo code
class Sequence:
def __init__(self):
self.free_numbers_set = []
self.counter = 0
def get_next_sequence_value(self):
if not isempty(self.free_numbers_set):
id = self.free_numbers_set.pop(0)
else:
id = self.counter
id ++
return id
def add_free_numbers(self, column):
for i in range(0:self.counter):
if not i in column:
free_numbers_set.append(i)
free_numbers_set.sort()
Run Code Online (Sandbox Code Playgroud)
每当我们需要一个新的 id 时,get_next_sequence_value()我们就会定期运行add_free_numbers(column)
更新解决一些问题
我相信这个解决方案可以提供更少的稀疏序列,这将允许用户使用更小的 id 类型(int 与 bigint),同时向后兼容当前的实现。
sequence ×10
postgresql ×5
sql-server ×3
oracle ×2
amazon-rds ×1
ddl ×1
dynamic-sql ×1
insert ×1
permissions ×1
primary-key ×1
psql ×1
query ×1
row ×1
timestamp ×1
trigger ×1
update ×1