复合增量列

时间:2016-03-15 05:51:04

标签: sql-server tsql sql-server-2012 sql-server-2008-r2 database-schema

我有一种情况,我需要将辅助列加1,假设另一列的值相同。

表架构:

CREATE TABLE [APP].[World]
(
    [UID] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
    [App_ID] [bigint] NOT NULL,
    [id] [bigint] NOT NULL,
    [name] [varchar](255) NOT NULL,
    [descript] [varchar](max) NULL,
    [default_tile] [uniqueidentifier] NOT NULL,
    [active] [bit] NOT NULL,
    [inactive_date] [datetime] NULL
)

首先,我UID完全独一无二,无论App_ID是什么。

在我的情况下,我希望idIncrement(1,1)相似,仅适用于App_ID

假设:

  1. 有3 App_Id:1,2,3
  2. 情景:

    • App_ID 1有3个世界
    • App_ID 2有5个世界
    • App_ID 3有1个世界

    理想的结果:

    App_ID  id
    1       1
    2       1
    3       1
    1       2
    2       2
    1       3
    2       3
    2       4
    2       5
    

    考虑将增量逻辑放在Insert存储过程中,但想知道在没有存储过程的情况下是否会有更简单或不同的方法产生相同的结果。

    图可用的选项是触发器或存储过程实现,但是想确保没有一些我遗漏的边缘案例模式。

    更新#1

    让我们重新考虑一下。

    这是关于存在一个PK UID,最终是一个分区列id,超过App_ID,对于关联的App_id每个新条目都会增加1 。

    • 这与您Row_Number()的方式类似,但每次插入新条目时都没有重新计算值的所有开销。
    • 同样App_IDid都有BIGINT的空间和潜力;因此,可能组合的组合数量为:BIGINT x BIGINT

3 个答案:

答案 0 :(得分:0)

这不可能实现您的要求。正如其他人在您对原始帖子的评论中指出的那样,您的数据库设计在多个表中分离会更好,这些表都有自己的身份,并在必要时使用外键约束。

但是,如果您在继续这种方法时已经死定,我会将app_id设为一个标识列,然后通过首先查询它来增加id列

MAX(identity)

然后将响应递增1.这种逻辑适合在存储过程中实现,无论如何都应该实现插入以防止直接sql注入等。这样一个过程的查询部分可能如下所示:

INSERT INTO
  [db].dbo.[yourtable]
SET
  (
    app_id
    , id
  ) 
VALUES
  (
   @app_id
   , (
        SELECT
          MAX(id)
        FROM
          [db].dbo.[table]
          WHERE
            App_id = @app_id
     )
   )

然而,这样做对性能的影响取决于您的评估。 此外,您需要考虑如何在没有该app_id的前一行时正确处理。

答案 1 :(得分:0)

最简单的解决方案如下:

    /* Adding Leading 0 to [App_ID] */
[SELECT RIGHT(CONCAT('0000', (([App_ID] - (([App_ID] - 1) % 3)) / 3) + 1), 4) AS [App_ID]

我在最近的代码中做了类似的事情,请找到下面的图片。

enter image description here

答案 2 :(得分:0)

希望以下示例对您有所帮助。

说明部分-在下面的代码中,使用MAX(Primary_Key Identity列),并借助ISNULL(NULL,1)处理第一个输入项。在所有其他情况下,它将加1并给出唯一值。根据要求和需求,我们可以进行更改并使用以下示例代码。只是添加了WHILE循环以显示演示(实际上不需要)。

IF OBJECT_ID('dbo.Sample','U') IS NOT NULL 
  DROP TABLE dbo.Sample 

CREATE TABLE [dbo].[Sample](
    [Sample_key] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,    
    [Student_Key] [int] UNIQUE NOT NULL,
    [Notes] [varchar](100) NULL,
    [Inserted_dte] [datetime] NOT NULL
)

DECLARE @A INT,@N INT
SET @A=1
SET @N=10
WHILE(@A<=@N)
BEGIN
    INSERT INTO [dbo].[Sample]([Student_Key],[Notes],[Inserted_dte])
    SELECT ISNULL((MAX([Student_Key])+1),1),'NOTES',GETDATE() FROM  [dbo].[Sample]
    SET @A+=1
END

SELECT * FROM [dbo].[Sample]