添加不带DEFAULT但带值的NOT NULL列

问题描述

我正在使用MSsql 2017,我想添加一个NOT NULL而不包含DEFAULT的列,但要提供当前记录的值,例如在单个查询中使用WITH VALUES

让我解释一下。我了解以下事实:如果不提供值就无法创建NOT NULL列。但是DEFAULT子句也为我不希望的将来插入设置了此列的认值。我想要一个认值仅用于添加此新列,仅此而已。

让我解释一下。 假设这样的查询序列:

CREATE TABLE items (
    id INT NOT NULL PRIMARY KEY IDENTITY(1,1)
);

ALTER TABLE items ADD name VARCHAR(255) NOT NULL; -- No default value because table is empty

INSERT INTO items(name) VALUES( 'test'); -- ERROR

最后一个查询给出错误(按预期):

Error: Cannot insert the value NULL into column 'description',table 'suvibackend.dbo.items'; column does not allow nulls. INSERT fails.

之所以如此,是因为我们没有为description列提供价值。很明显。

让我们考虑项目表中有一些记录的情况。如果没有DEFAULTWITH VALUES子句,它将失败(显然),所以现在就使用它们:

CREATE TABLE items (
    id INT NOT NULL PRIMARY KEY IDENTITY(1,1),name varchar(255) NOT NULL
);

INSERT INTO items(name) VALUES ('name-test-1');
INSERT INTO items(name) VALUES ('name-test-2');

ALTER TABLE items ADD description VARCHAR(255) NOT NULL DEFAULT 'no-description' WITH VALUES;

所以现在我们的表如下所示:

SELECT * FROM items;

--------------------------------------
| id  | name        | description    |
| --- | ----------- | -------------- |
| 1   | name-test-1 | no-description |
| 2   | name-test-2 | no-description |
--------------------------------------

但是从现在开始,有INSERT条记录可能没有description

INSERT INTO items(name) VALUES ('name-test-3'); -- No description column

SELECT * FROM ITEMS;

--------------------------------------
| id  | name        | description    |
| --- | ----------- | -------------- |
| 1   | name-test-1 | no-description |
| 2   | name-test-2 | no-description |
| 3   | name-test-3 | no-description |
--------------------------------------

但是,当我们将其与第一种情况(没有DEFAULT子句的空表)进行比较时,情况就不同了。我仍然想要有关NULLdescription列的错误

MSsql为此列创建了一个我不想拥有的认约束。

解决方案是在添加带有DEFAULT子句的新列之后删除约束,或者将添加新列分为3个查询

CREATE TABLE items (
    id INT NOT NULL PRIMARY KEY IDENTITY(1,name varchar(255) NOT NULL
);

INSERT INTO items(name) VALUES ('name-test-1');
INSERT INTO items(name) VALUES ('name-test-2');

ALTER TABLE items ADD description VARCHAR(255) NULL;
UPDATE items SET description = 'no description'
ALTER TABLE items ALTER COLUMN description VARCHAR(255) NOT NULL;

INSERT INTO items(name) VALUES ('name-test-3'); -- ERROR as expected

我的问题:

是否有一种方法可以在单个查询中实现它,但又没有创建认约束? 如果可以在不永久创建约束的情况下仅将认值用于查询,那就太好了。

解决方法

尽管您不能指定添加列后会自动删除的临时默认约束(即单条语句操作),但您可以显式命名该约束以方便之后立即删除它。

ALTER TABLE dbo.items
    ADD description VARCHAR(255) NOT NULL
    CONSTRAINT DF_items_description DEFAULT 'no-description' WITH VALUES;
ALTER TABLE dbo.items
    DROP CONSTRAINT DF_items_description;

显式约束名称是一种最佳做法,恕我直言,因为它使后续的DDL操作更加容易。