添加 NOT NULL 列而不使用 DEFAULT 但 WITH VALUES

Posted

技术标签:

【中文标题】添加 NOT NULL 列而不使用 DEFAULT 但 WITH VALUES【英文标题】:Add NOT NULL column without DEFAULT but WITH VALUES 【发布时间】:2021-01-09 12:16:51 【问题描述】:

我正在使用 SQL Server 2017,我想添加一个不带 DEFAULTNOT NULL 列,但为当前记录提供一个值,例如在单个查询中使用 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 列提供值。很明显。

让我们考虑一下items表中有一些记录的情况。如果没有 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 列的错误。

SQL Server 已为此列创建了一个我不想拥有的默认约束。

解决方案是在使用 DEFAULT 子句添加新列后删除约束,或者将添加新列拆分为 3 个查询:

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) 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

我的问题:

有没有办法在单个查询中实现它,但没有创建默认约束?

如果可以只为查询使用默认值而不永久创建约束,那就太好了。

【问题讨论】:

只有一个查询,没有。在添加带有约束的列后,我会立即删除默认约束。 没有WITH VALUES。列创建表达式指定列的定义(类型、大小和约束)。您想要的是一次性插入。 @DanGuzman 问题是一个约束的名字是由 sqlserver 生成的。所以我需要进行另一个查询来获取它,然后删除它。 SQL Server 只生成一个名称,如果你不提供一个,你可以很容易地提供你的约束名称:ALTER TABLE items ADD description VARCHAR(255) NOT NULL CONSTRAINT DF_Items_Description DEFAULT 'no-description'; ALTER TABLE items DROP CONSTRAINT DF_Items_Description; 【参考方案1】:

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

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 操作更容易。

【讨论】:

以上是关于添加 NOT NULL 列而不使用 DEFAULT 但 WITH VALUES的主要内容,如果未能解决你的问题,请参考以下文章

C# 动态添加类动态添加类型代码添加类型

Eclipse IDE - 添加 jar?添加外部罐子?添加图书馆?

《VUE》怎么添加文字?添加文字操作流程

苹果cms10如何添加直播?

添加用户 之添加保存

vue如何动态添加多个li