具有备用序列的列

2024-04-19

我想创建一个 user_widgets 表,该表由 user_id 和 user_widget_id 主键,其中 user_widget_id 的工作方式类似于序列号,除了每个用户从 1 个开始。

对此有通用或实用的解决方案吗?我正在使用 PostgreSQL,但也希望有一个不可知的解决方案。

示例表:user_widgets

 |  user_id  |  user_widget_id  |  user_widget_name    |
 +-----------+------------------+----------------------+
 |  1        |  1               | Andy's first widget  |
 +-----------+------------------+----------------------+
 |  1        |  2               | Andy's second widget |
 +-----------+------------------+----------------------+
 |  1        |  3               | Andy's third widget  |
 +-----------+------------------+----------------------+
 |  2        |  1               | Jake's first widget  |
 +-----------+------------------+----------------------+
 |  2        |  2               | Jake's second widget |
 +-----------+------------------+----------------------+
 |  2        |  3               | Jake's third widget  |
 +-----------+------------------+----------------------+
 |  3        |  1               | Fred's first widget  |
 +-----------+------------------+----------------------+

Edit:

我只是想说明一下这种设计的一些原因。

1. 减少信息泄露,而不仅仅是“隐匿安全”

在一个用户不应该知道彼此的系统中,他们也不应该知道彼此的 widget_id。如果这是一张库存表、奇怪的商业秘密、发票或更敏感的东西,他们就能够开始为这些小部件拥有自己的不受影响的 ID 集。除了明显的例行安全检查之外,这还添加了一个隐式安全层,其中表has通过小部件 ID 进行过滤and用户 ID。

2. 数据导入

应允许用户从其他系统导入数据,而不必丢弃所有旧 ID(如果他们有整数 ID)。

3. 清洁度

与我的第一点并没有太大不同,但我认为创建内容少于其他人的用户可能会对其小部件 ID 的显着跳跃感到困惑或恼火。这当然比功能更肤浅,但仍然很有价值。

一个可能的解决方案

答案之一表明应用程序层可以处理这个问题。我可以在该用户的表上存储一个递增的 next_id 列。或者甚至可能只是计算每个用户的行数,并且不允许删除记录(而是使用删除/停用标志)。这可以通过触发器函数甚至存储过程而不是在应用程序层中完成吗?


如果你有一张桌子:

CREATE TABLE user_widgets (
  user_id int
 ,user_widget_name text  --should probably be a foreign key to a look-up table
  PRIMARY KEY (user_id, user_widget_name)
)

你可以分配user_widget_id动态并查询:

WITH x AS (
   SELECT *, row_number() OVER (PARTITION BY user_id
                                ORDER BY user_widget_name) AS user_widget_id 
   FROM   user_widgets
   )
SELECT *
FROM   x
WHERE  user_widget_id = 2;

user_widget_id在这种情况下,按每个用户的字母顺序应用,并且没有间隙,显然,添加、更改或删除条目可能会导致更改。

更多关于手册中的窗口功能 http://www.postgresql.org/docs/current/interactive/functions-window.html.


稍微更稳定(但不完全):

CREATE TABLE user_widgets (
  user_id int
 ,user_widget_id serial
 ,user_widget_name
  PRIMARY KEY (user_id, user_widget_id)
)

And:

WITH x AS (
   SELECT *, row_number() OVER (PARTITION BY user_id
                                ORDER BY user_widget_id) AS user_widget_nr 
   FROM   user_widgets
   )
SELECT *
FROM   x
WHERE  user_widget_nr = 2;

解决问题更新

You can实施一种制度来计算每个用户的现有小部件。但是您将很难使其对于并发写入来说无懈可击。您必须锁定整个表或使用SERIALIZABLE交易方式 http://www.postgresql.org/docs/current/interactive/transaction-iso.html#XACT-SERIALIZABLE- 两者都会真正降低性能并且需要额外的代码。

但如果你保证没有行被删除你可以采用我的第二种方法 - 一个序列user_widget_id桌子对面,给你一个"raw"ID。序列是并发加载的一种经过验证的解决方案,保留了相对顺序user_widget_id and is fast。您可以使用以下方式提供对表的访问view动态替换“原始”user_widget_id与相应的user_widget_nr就像我上面的查询一样。

您还可以(此外)“实现”无间隙user_widget_id将其替换为user_widget_nr在下班时间或由您选择的事件触发。

为了提高性能,我将有以下顺序user_widget_id从一个非常高的数字开始。似乎每个用户只能有几个小部件。

SELECT setval(user_widgets_user_widget_id_seq', 100000);

如果没有足够高的数字来保证安全,请添加一个标志。使用条件WHERE user_widget_id > 100000快速识别“原始”ID。如果您的桌子很大,您可能需要添加一个部分索引 http://www.postgresql.org/docs/current/interactive/indexes-partial.html使用条件(该条件会很小)。用于上述视图中CASE陈述。在这个“具体化”ID 的语句中:

UPDATE user_widgets w
SET    user_widget_id = u.user_widget_nr
FROM (
   SELECT user_id, user_widget_id
         ,row_number() OVER (PARTITION BY user_id
                             ORDER BY user_widget_id) AS user_widget_nr 
   FROM   user_widgets
   WHERE  user_widget_id > 100000
   ) u
WHERE  w.user_id = u.user_id
AND    w.user_widget_id = u.user_widget_id;

可能会跟进REINDEX甚至VACUUM FULL ANALYZE user_widgets下班时间。考虑一个FILLFACTOR http://www.postgresql.org/docs/current/interactive/sql-createtable.html#SQL-CREATETABLE-STORAGE-PARAMETERS低于 100,因为列将至少更新一次。

我当然会not将其留给应用程序。这会带来多个额外的故障点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有备用序列的列 的相关文章

随机推荐

  • 如何获取对话框/窗口的背景颜色?

    如何获取 RGB 格式的对话框 窗口的背景颜色 Use QWidget palette访问小部件的调色板和QPalette color获取背景颜色 color widget palette color QPalette Background
  • cmake 发现错误的 python 库

    我是 CMake 新手 无法理解一些使用概念 我正在从 C 程序调用 python 脚本 include
  • 使用预加载图像以外的其他内容

    首先 我应该使用预加载图像 还是应该使用其他东西来完成我想做的事情 我开始认为预加载图像与我想要完成的任务无关 我想做的是 我想防止图像的转换效果 即您看到的闪烁 我有一个播放按钮 初始屏幕上没有图像 当您单击它时 会出现一个图像 这就是您
  • 本地主机上的服务器 App Engine Standard 无法启动

    从 eclipse 中 我创建了一个 Google App Engine 标准项目 并尝试在本地 App Engine 上运行它 它没有启动并抛出以下错误 java lang NullPointerException at java bas
  • 根据所选数字指定数字范围

    当用户选择数字 1000243 时 我想要另一个选项来从该输入的数字中选择 200 个数字 所以它会是 User Input Number Here
  • 需要用jquery将h3和div包装在包装器div中

    我有以下 HTML div class accordion h3 My title h3 div My content div h3 My title h3 div My content div h3 My title h3 div My
  • 如何从 Ionic 选项卡打开 Ionic 模态

    我有一个用例 我想通过单击 Ion 选项卡来打开 Ionic Modal 我们的应用程序有 4 个固定的ion tabs 其中一个选项卡当前转到评论表单 但它更适合作为模式 因此用户可以快速完成表单并返回到他们正在做的事情 模态框通常附加到
  • Python CSV 编写器截断长数字

    我目前正在开发一个项目 该项目需要生成一个包含大量信息的 CSV 文件作为最终输出 目前 我将所有数据存储在一个非常大的列表中 然后使用 CSV 包将其写入 CSV 文件 我的问题是其中一个数据字段包含一个非常长的数字 存储为字符串 但第
  • Swift 栈和堆的理解

    我想快速了解堆栈和堆中存储的内容 我有一个粗略的估计 您打印的所有内容和内存地址都不是值 它们存储在堆栈中 而作为值打印出来的内容则在堆上 基本上根据值和引用类型 我完全错了吗 或者 您可以提供堆栈 堆的可视化表示吗 As Juul htt
  • 如何在 Firebase 实时数据库中保存本地数据?

    我对 Kotlin 和编程非常陌生 目前正在制作包含事件的日历 当我想将这些事件连接到 firebase 时 我的问题就出现了 我正在使用在 git 中找到的一个示例 https github com kizitonwose Calenda
  • 使用鼠标滚动 DataGridView

    因此 我们都熟悉单击并按住鼠标按钮 然后将鼠标移动到网格边缘 列 行滚动并且选择范围增加的功能 我有一个基于 DataGridView 的控件 由于性能问题 我必须关闭 MultiSelect 并自行处理选择过程 现在单击 按住滚动功能也被
  • 在matlab中对矩阵元素求和的有效(最快)方法

    让我们有矩阵A say A magic 100 我见过两种计算矩阵所有元素之和的方法A sumOfA sum sum A Or sumOfA sum A 其中一个比其他更快 或更好的练习 吗 如果有的话是哪一个 或者它们都同样快 看来你无法
  • 使用 PHPMailer 附加文​​件

    我有一个 HTML 表单 可以选择上传文件 然后 我想将该文件作为附件与其余表单数据一起发送到电子邮件地址 我正在使用 PHP Mailer 我获取要发送的表单数据 例如姓名 电话号码等 我无法将图像与它一起发送 我已经提供了迄今为止的代码
  • 如何在 Android 应用程序中播放和停止 mp3 文件

    我在 eclipse 中创建了一个应用程序来播放和停止 mp3 文件 一切都很好 除了当我播放音频文件并停止它并且我想重播它时 播放 btn 不起作用 我想知道是否有人可以帮助我 提前致谢 代码如下 package ir polyglotc
  • 更改 NUnit 测试的名称

    我希望我的单元测试基于NUnit在 Visual Studio 测试资源管理器中命名的框架更易于理解 例如 而不是有Test Case 1 or TestCase1我最好有类似的东西Test Case 1 Category First Ca
  • Android Room:应用与嵌入对象相关的多列

    在我的 Android 应用程序中 我使用 Room 进行数据存储 我目前面临的问题是 我需要在嵌入对象的 Relation 中放入 2 列 因为关系依赖于 2 列 结构见下图 Entity tableName damages public
  • 从通用平面获取轴对齐坐标

    标题可能是错误的 因为我不知道足够的数学知识来实际用一个小句子描述我的问题 我有一个 3D 矢量闭环 我将其称为 3D 多边形 我需要对其执行仅 2D 操作 这将返回一个 不同的 2D 点集 我需要将这些新的 2D 点转换回 3D 我目前的
  • 如何将下拉菜单置于父选项卡下居中?

    我有以下 CSS HTML 设置http jsfiddle net UDAUY http jsfiddle net UDAUY 如何对齐下拉菜单字段使其在父选项卡下居中 如下所示 MENU 1 MENU 2 MENU 3 MENU 4 Fi
  • 如何让 ko.compated 处理对象内的可观察值

    我有一个相当简单的视图模型来保存数据数组并获取一个我想用来过滤数据的字符串 我有一些非常简单的标记来渲染它 如下所示 section class task list ul li li ul section
  • 具有备用序列的列

    我想创建一个 user widgets 表 该表由 user id 和 user widget id 主键 其中 user widget id 的工作方式类似于序列号 除了每个用户从 1 个开始 对此有通用或实用的解决方案吗 我正在使用 P