添加不带 DEFAULT 但 WITH VALUES 的 NOT NULL 列
Add NOT NULL column without DEFAULT but WITH VALUES
我正在使用 SQL Server 2017,我想添加一个没有 DEFAULT
的 NOT 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
列提供值。很明显。
让我们考虑在项目table中有一些记录的情况。如果没有 DEFAULT
和 WITH 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;
所以现在我们的 table 看起来像预期的那样:
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
子句的空 table 进行比较时,它是不同的。我仍然想要关于 NULL
和 description
列的错误。
SQL 服务器为此列创建了一个我不想拥有的默认约束。
解决方案是在使用 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
我的问题:
有没有办法在不创建默认约束的情况下在单个查询中实现它?
如果可以只为查询使用默认值而不永久创建约束,那就太好了。
虽然您不能指定在添加列后自动删除的临时默认约束(即单语句操作),但您可以显式命名约束以方便之后立即删除它。
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 操作更容易。
我正在使用 SQL Server 2017,我想添加一个没有 DEFAULT
的 NOT 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
列提供值。很明显。
让我们考虑在项目table中有一些记录的情况。如果没有 DEFAULT
和 WITH 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;
所以现在我们的 table 看起来像预期的那样:
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
子句的空 table 进行比较时,它是不同的。我仍然想要关于 NULL
和 description
列的错误。
SQL 服务器为此列创建了一个我不想拥有的默认约束。
解决方案是在使用 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
我的问题:
有没有办法在不创建默认约束的情况下在单个查询中实现它?
如果可以只为查询使用默认值而不永久创建约束,那就太好了。
虽然您不能指定在添加列后自动删除的临时默认约束(即单语句操作),但您可以显式命名约束以方便之后立即删除它。
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 操作更容易。