Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 具有交替序列的列_Sql_Postgresql_Database Design_Auto Increment - Fatal编程技术网

Sql 具有交替序列的列

Sql 具有交替序列的列,sql,postgresql,database-design,auto-increment,Sql,Postgresql,Database Design,Auto Increment,我想创建一个user_widgets表,该表由user_id和user_widget_id主键控制,其中user_widget_id的工作方式类似于一个序列,只是它从每个用户1开始 是否有一个通用或实用的解决方案?我使用的是PostgreSQL,但如果能提供一个不可知论的解决方案,我将不胜感激 示例表:用户_小部件 | user_id | user_widget_id | user_widget_name | +-----------+------------------+-

我想创建一个user_widgets表,该表由user_id和user_widget_id主键控制,其中user_widget_id的工作方式类似于一个序列,只是它从每个用户1开始

是否有一个通用或实用的解决方案?我使用的是PostgreSQL,但如果能提供一个不可知论的解决方案,我将不胜感激

示例表:用户_小部件

 |  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  |
 +-----------+------------------+----------------------+
编辑: 我只是想为这个设计加入一些理由

1。减少信息披露,而不仅仅是“通过默默无闻实现安全”

在一个系统中,用户不应该知道彼此,他们也不应该知道彼此的widget_id。如果这是一张清单、奇怪的商业秘密、发票或其他更敏感的东西的表格,他们就可以开始为这些小部件设置自己的未受影响的ID。除了明显的例行安全检查之外,这还添加了一个隐式安全层,在该层中,表必须通过小部件id和用户id进行过滤

2。数据导入

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

3。清洁度

与我的第一点并没有太大的不同,但我认为创建的内容比其他人少的用户可能会对他们的widget ID的显著跳跃感到困惑或恼火。这当然是表面的,而不是功能性的,但仍然有价值

可能的解决方案

其中一个答案表明,应用程序层可以处理这个问题。我可以在该用户的表中存储一个递增的下一个_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\u widget\u 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\u widget\u id
在此场景中按每个用户的字母顺序应用,并且没有间隙,添加、更改或删除条目显然会导致更改

更多关于


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

以及:


解决问题更新 您可以实现一个机制来统计每个用户的现有小部件。但是,要使并发写操作防弹,您将很难。您必须锁定整个表或使用-这两个都是真正的性能下降,需要额外的代码

但是,如果您保证不删除任何行,那么您可以使用我的第二种方法-在整个表中为
user\u widget\u id
设置一个序列,这将为您提供一个“原始”id。序列是一个经验证的并发加载解决方案,保留了
user\u widget\u id
中的相对顺序,而且速度很快。您可以使用视图提供对表的访问,该视图动态地将“原始”
user\u widget\u id
替换为相应的
user\u widget\u nr
,就像我上面的查询一样

您还可以(另外)在非工作时间或由您选择的事件触发,通过将其替换为
user\u widget\u nr
来“具体化”一个无间隙的
user\u widget\u id

为了提高性能,我会让
user\u widget\u id
的序列从一个非常高的数字开始。似乎每个用户只能有几个小部件

SELECT setval(user_widgets_user_widget_id_seq', 100000);
如果没有足够高的数字可以确保安全,则添加一个标志。使用user\u widget\u id>100000的条件
快速识别“原始”id。如果您的表很大,您可能需要使用条件(将是小的)添加一个表。用于
案例中提到的视图中
语句。在此语句中,要“具体化”ID:

可能在非工作时间使用
REINDEX
或甚至
真空全分析用户小部件
。考虑低于100,因为列将至少更新一次。


我当然不会把这件事留给应用程序处理。这会带来多个额外的失败点。

我将加入进来,对具体要求提出质疑。一般来说,如果您试图对这类事情进行排序,最好由应用程序来完成。如果你认识我,你就会意识到这是在说些什么。我担心的是,我所能想到的每一个案例都可能需要申请者重新排序,因为否则这些数字就无关紧要了

所以我只想:

CREATE TABLE user_widgets (
      user_id int references users(id),
      widget_id int,
      widget_name text not null,
      primary key(user_id, widget_id)
);
我就不说了

现在根据您的理由,这解决了您所有的问题(导入)。然而,我曾经在很长一段时间内做过类似的事情。我遇到的用例是一个地方税务管辖区要求装箱单(!)与发票分开,按顺序编号,没有空白。计数记录,顺便说一句,这不符合您的进口要求


我们所做的是创建一个表,每个序列有一行,并使用它,然后将其与触发器绑定。

这些是数据库中的ID。我想不出任何实际的理由来强制存储的ID遵循这种模式。现在,如果您希望以这种方式对它们进行编号以便于显示,有几种方法可以在不更改基础数据的情况下解决这一问题。那么如何通过这些参数查询表?您可以为如何尝试查询的问题添加更多详细信息吗?我仍然认为没有必要强制对存储的ID进行任意排序。我在回答中添加了一点内容以解决您的更新问题。我倾向于同意这一点,但我确实希望在数据库中管理它。我已经用更多的细节更新了我的问题。我已经适当地更新了我的答案。当然,计算记录以确定id将无法满足从客户导入任意整数id的要求。我建议将其放在应用程序层t中的主要原因
SELECT setval(user_widgets_user_widget_id_seq', 100000);
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;
CREATE TABLE user_widgets (
      user_id int references users(id),
      widget_id int,
      widget_name text not null,
      primary key(user_id, widget_id)
);