复合增量列
Composite increment column
我有一种情况需要将辅助列递增 1,假设另一个列的值相同。
Table 架构:
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
是什么,它都是独一无二的。
在我的情况下,我希望 id
与 Increment(1,1)
相似,只是为了相同的 App_ID
。
假设:
- 有3个
App_Id
: 1, 2, 3
场景:
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
让我们重新考虑一下。
这是关于在 App_ID
上有一个 PK UID
和最终的分区列 id
,关联 [=25] 的每个新条目都会增加 1 =].
- 这与您的做法类似
Row_Number()
,但没有每次插入新条目时重新计算值的所有开销。
- 以及
App_ID
和 id
都具有 space 和成为 BIGINT
的潜力;因此可能组合的组合数将是:BIGINT x BIGINT
这不可能实现您要求的方式。正如其他人在对您的原始 post 的评论中指出的那样,您的数据库设计最好拆分成多个表,这些表都有自己的身份并在必要时使用外键约束。
但是,如果您坚持使用这种方法,我会让 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.
最简单的解决方案如下:
/* Adding Leading 0 to [App_ID] */
[SELECT RIGHT(CONCAT('0000', (([App_ID] - (([App_ID] - 1) % 3)) / 3) + 1), 4) AS [App_ID]
我在最近的代码中做了类似的事情,请找到下图。
希望下面的例子对您有所帮助。
解释部分 - 在下面的代码中,使用了 MAX(Primary_Key 标识列) 并在 ISNULL(NULL,1) 的帮助下处理了第一个条目的情况。在所有其他情况下,它将加起来 1 并给出唯一值。根据要求和需要,我们可以进行更改并使用以下示例代码。 WHILE循环只是为了展示demo(其实不需要)。
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]
我有一种情况需要将辅助列递增 1,假设另一个列的值相同。
Table 架构:
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
是什么,它都是独一无二的。
在我的情况下,我希望 id
与 Increment(1,1)
相似,只是为了相同的 App_ID
。
假设:
- 有3个
App_Id
: 1, 2, 3
场景:
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
让我们重新考虑一下。
这是关于在 App_ID
上有一个 PK UID
和最终的分区列 id
,关联 [=25] 的每个新条目都会增加 1 =].
- 这与您的做法类似
Row_Number()
,但没有每次插入新条目时重新计算值的所有开销。 - 以及
App_ID
和id
都具有 space 和成为BIGINT
的潜力;因此可能组合的组合数将是:BIGINT x BIGINT
这不可能实现您要求的方式。正如其他人在对您的原始 post 的评论中指出的那样,您的数据库设计最好拆分成多个表,这些表都有自己的身份并在必要时使用外键约束。
但是,如果您坚持使用这种方法,我会让 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.
最简单的解决方案如下:
/* Adding Leading 0 to [App_ID] */
[SELECT RIGHT(CONCAT('0000', (([App_ID] - (([App_ID] - 1) % 3)) / 3) + 1), 4) AS [App_ID]
我在最近的代码中做了类似的事情,请找到下图。
希望下面的例子对您有所帮助。
解释部分 - 在下面的代码中,使用了 MAX(Primary_Key 标识列) 并在 ISNULL(NULL,1) 的帮助下处理了第一个条目的情况。在所有其他情况下,它将加起来 1 并给出唯一值。根据要求和需要,我们可以进行更改并使用以下示例代码。 WHILE循环只是为了展示demo(其实不需要)。
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]