【问题标题】:Make Sequence Column Increment Based On Conditions?根据条件使序列列增加?
【发布时间】:2019-09-20 10:00:26
【问题描述】:

背景信息

所以这是这个问题的背景。目前我们有多个物料清单编号标识符(UNPN、UDEN、UXXN 等),每个都有自己的序列号(UNPN0001、UNPN0002、UNPN0003 等)

当用户请求新的物料清单编号时,假设是一个新的 UNPN 编号。如果最后一个数字是 UNPN0003,那么用户应该能够保留 UNPN0004。

我的初步想法:

所以最初我想,我可以简单地在表中创建一个序列列。因此,如果我们有一个 UNPN 表,我们可以轻松地添加一条新记录并自动对其进行排序,并返回 UNPN + Generated Sequence number 的组合。

问题:

所以我发现的问题是,对于这种方法,我们目前有 50 多个不同的物料清单标识符。所以这意味着我必须为每个标识符创建一个表,并使用它自己的自动序列列。

我在寻找什么:

我宁愿避免创建 50 多个不同的表。我不确定我是否可以为我的数据库使用不同的模式,或者我是否应该放弃这个方法来做别的事情。我不相信您可以在一个表中拥有多个序列列,这些列仅基于输入的内容进行排序,当然我不完全了解所有可能的情况

任何建议将不胜感激。

谢谢,

【问题讨论】:

  • 您的插入频率如何?你想确保你得到正确的 ACID 东西,但你可以考虑的一件事是只拥有一个包含每种账单类型的行和最新序列号的表——当你进行插入时,只需使用该序列号和为特定的账单类型增加它。
  • 创建一个表来保存账单和序列,因此对于每个请求,获取该账单增量的最后一个序列并存储回来
  • 感谢您的建议。我已经考虑过这一点,我宁愿避免自己增加价值。如果同时发出两个请求,则存在重复的可能性。我更喜欢数据库增加序列本身。 @Slothario
  • 如果您编写了一个可以为您执行插入操作的存储过程怎么办?您可以为每种可能的订单类型创建一个序列,而您不必自己维护任何类型的计数。
  • 如果您试图为每个 BOM 代码实现“无间隙”编号(或任何用途的无间隙编号),那么您就大错特错了。自动增量列只是一种自动将列与序列联系起来的方法。而甲骨文从不保证无间隙序列。如果您尝试编写自己的创建序列的方法,您将遇到相同的固有多用户问题,从而阻止 oracle 保证无间隙序列。

标签: c# sql asp.net sql-server entity-framework


【解决方案1】:

您已表明您正在使用 Oracle。 Oracle 有一个数据库级对象,称为为此类事物制作的序列。它们非常高效。您可能希望为每个标识符制作一个序列。您只需为每个标识符执行一次。

CREATE SEQUENCE UNPN;  -- Starts a 1 by default
CREATE SEQUENCE UDEN START WITH 50;
CREATE SEQUENCE UXXN MAXVALUE 9999 CYCLE; -- This one will recycle back to 0001 after it hits 9999

接下来,当您需要给定序列的新值时,您只需选择它:

SELECT 'UNPN'||TO_CHAR(UNPN.NEXTVAL,'FM0000') FROM DUAL;

为了使它更容易/更动态,您可以定义一个函数来按名称获取新值:

create or replace function get_named_seq(p_sequence varchar2) return varchar2
is
  l_sql VARCHAR2(4000);
  l_Result varchar2(30);
begin
  select 'select '''||sequence_name||'''||to_char('||sequence_name||'.nextval,''FM0000'') from dual'
    into l_sql
    from user_sequences
   where sequence_name = upper(p_sequence);

  execute immediate l_sql
     into l_Result;
   return l_result;
end;
/

如果请求的序列不存在,上述函数将抛出 NO_DATA_FOUND 异常,即使它使用的是动态 SQL,它也应该不会被 SQL 注入,因为实际的动态 SQL 语句从不直接接触输入参数。你会像这样使用它或任何你可以使用函数的地方:

INSERT into MyTable (ID, Data) values (get_named_seq('UXXN'), 'some data');

【讨论】:

  • 我很抱歉我犯了一个错误。我们正在使用 Microsoft SQL 服务器数据库。
  • 没关系,我刚刚发现 SQL Server 在 2012 年开始支持序列。
猜你喜欢
  • 1970-01-01
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
  • 2016-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多