Добавить столбец NOT NULL без значения по УМОЛЧАНИЮ, но СО ЗНАЧЕНИЯМИ

#sql-server #default-value #sql-null

#sql-server #значение по умолчанию #sql-null

Вопрос:

Я использую SQL Server 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 столбца. Это очевидно.

Давайте рассмотрим ситуацию, когда в таблице items есть несколько записей. Без DEFAULT WITH VALUES предложений and это приведет к сбою (очевидно), поэтому давайте использовать их сейчас:

 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 предложения), она отличается. Я все еще хочу ошибку, касающуюся NULL description столбца and .

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
  

Мой вопрос:

Есть ли способ достичь этого в одном запросе, но без создания константы по умолчанию?

Было бы неплохо, если бы можно было использовать значение по умолчанию только для запроса без постоянного создания ограничения.

Комментарии:

1. С одним запросом — нет. Я бы просто отбросил ограничение по умолчанию сразу после добавления столбца с ограничением.

2. Нет WITH VALUES . Выражение создания столбца определяет определение столбца (тип, размер и ограничения). Вам нужна одноразовая вставка.

3. @DanGuzman Проблема в том, что имя константы генерируется sqlserver. Поэтому мне нужно сделать еще один запрос, чтобы получить его, чтобы удалить его.

4. 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.