Paw*_*wel 0 sql-server default-value table
声明默认列值时不允许使用列名。有没有解决方法来实现这样的目标?
CREATE TABLE [dbo].[Tasks]
(
[TaskId] INT IDENTITY(1,1) NOT NULL,
[TaskName] NVARCHAR(255) NULL,
[Priority] INT NOT NULL UNIQUE DEFAULT Max(Priority)+1, -- not allowed
)
Run Code Online (Sandbox Code Playgroud)
要求是默认情况下最新的任务获得最低优先级(最高 int 值)。在任务在表中之后,它可以被优先化/去优先化,例如优先级值与表中的任何其他任务交换。
我会使用序列来实现这一点。
每次调用该序列时都会生成一个唯一编号,它满足UNIQUE您在[Priority]列上定义的约束。我们将使用它作为列值的默认值。
USE tempdb;
DROP TABLE IF EXISTS dbo.[Tasks];
DROP SEQUENCE IF EXISTS dbo.[tasks_priority_sequence]
GO
CREATE SEQUENCE dbo.[tasks_priority_sequence]
AS int
START WITH 1
INCREMENT BY 1
NO CYCLE
CACHE;
GO
CREATE TABLE dbo.[Tasks]
(
[TaskId] int NOT NULL
IDENTITY(1,1)
, [TaskName] nvarchar(255) NULL
, [Priority] int NULL
UNIQUE
DEFAULT (NEXT VALUE FOR dbo.[tasks_priority_sequence])
);
GO
INSERT INTO dbo.[Tasks] ([TaskName])
VALUES ('test1')
, ('test2');
SELECT *
FROM dbo.[Tasks];
Run Code Online (Sandbox Code Playgroud)
结果:
| 任务 ID | 任务名称 | 优先事项 |
|---|---|---|
| 1 | 测试1 | 1 |
| 2 | 测试2 | 2 |
| 3 | 测试1 | 3 |
虽然使用序列可能会引入间隙,但您可以向列提供任意值这一事实向我表明您不需要[Priority]列中严格单调递增的值。如果间隙对您来说是个问题,您可以使用NO CACHE编译指示重新定义序列,以确保序列不会产生间隙。
这种方法的一个警告是,如果您手动为序列尚未生成的列分配值,序列将导致错误。您可以使用触发器而不是序列来解决这个问题,但是使用基于触发器的解决方案的性能不会像使用序列那样线性。以下是会导致错误的代码示例:
--this works just fine
INSERT INTO dbo.[Tasks] (TaskName, [Priority])
VALUES ('test3', 3);
--this fails since the next value for the sequence already exists in the UNIQUE index.
INSERT INTO dbo.[Tasks] (TaskName)
VALUES ('test4')
Run Code Online (Sandbox Code Playgroud)
错误:
消息 2627,级别 14,状态 1,第 36 行
违反 UNIQUE KEY 约束“UQ__Tasks__534DF97B192F9781”。
无法在对象“dbo.Tasks”中插入重复键。重复的键值为 (3)。