Вставка строк в таблицу только с одним столбцом IDENTITY

83

У меня есть администратор таблицы только с одним столбцом, adminId, который является первичным ключом. Так должно быть из-за бизнес-правил.

Я хотел бы раз и навсегда понять, как я могу писать хранимые процедуры, которые вставляют значения в такие таблицы. Я использую SQL Server и T-SQL и пробовал использовать SCOPE_IDENTITY (), но это не работает, поскольку для таблицы INSERT_IDENTITY установлено значение false или off.

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

Фил
источник
1
Чтобы уточнить: ваш вопрос: «как вставить строки в таблицу SQL Server с одним столбцом IDENTITY»?
gbn 07
Да, вы правы, спасибо за разъяснения
Фил
2
Для людей, приземляющихся здесь, об этом уже спрашивали, и правильный ответ здесь: stackoverflow.com/questions/850327/…
BJury

Ответы:

140

Если у вас есть один столбец, который является ИДЕНТИЧНОСТЬЮ, просто сделайте это

INSERT MyTable DEFAULT VALUES;  --allows no column list. The default will be the IDENTITY
SELECT SCOPE_IDENTITY();

Если у вас нет личности, вы можете ее установить? Это лучший способ ... и используйте приведенный выше SQL.

Если нет, вы хотите вставить новую строку

INSERT MyTable (admidid)
OUTPUT INSERTED.admidid --returns result to caller
SELECT ISNULL(MAX(admidid), 0) + 1 FROM MyTable

Ноты:

  • При высоких нагрузках решение MAX может выйти из строя с дублированием
  • SCOPE_IDENTITY это после того, как на самом деле, не раньше
  • SCOPE_IDENTITY работает только со столбцом IDENTITY. Как и любой идиотизм с IDENT_CURRENT
  • Предложение output заменяет SCOPE_IDENTITY для решения MAX
gbn
источник
1

Вам нужно добавить IDENTITY_INSERT в свой оператор выбора:

SET IDENTITY_INSERT MyTable ON

INSERT INTO MyTable
(AdminCol)

SELECT AdminColValue

 FROM Tableb

Когда вы закончите, не забудьте

SET IDENTITY_INSERT MyTable OFF

Вот хорошее описание того, как это работает из BOL: http://msdn.microsoft.com/en-us/library/aa259221(SQL.80).aspx

DataWriter
источник
Должен ли я сделать это так: SET IDENTITY_INSERT Administrator ON INSERT INTO Administrator (SCOPE_IDENTITY ()) SET IDENTITY_INSERT Administrator OFF?
Фил
Да. Это все, что вам нужно сделать. НАСТРОЙКА, напишите свой код, ВЫКЛЮЧИТЕ в конце.
DataWriter
Я не думаю, что это правильный ответ. Если это столбец идентичности, вам не следует добавлять в него значения. Принятый ответ - правильный ответ.
Ммм
0

@Phil: Разве вы не имеете в виду, что в вашей таблице есть два (2) столбца: столбец PK с автоинкрементом и столбец AdminName? Если у него есть только один столбец, в который идет AdminName, AdminName - это PK, и, конечно, вы не можете автоматически увеличивать строку. Ожидают ли бизнес-правила, что вы сделаете полное имя пользователя Windows в качестве первичного ключа? Это было бы жизнеспособным и имело смысл, потому что тогда вам не понадобился бы альтернативный уникальный индекс в столбце AdminName.

Но если в вашей таблице два столбца, а не один:

В SQLServer автоинкремент является частью определения таблицы / столбца. Вы определяете столбец как целое число, а затем также делаете его столбцом идентификации, указывая приращение, обычно 1, но это может быть 2, 5 или 10 или что-то еще. Чтобы вставить строку, вы просто вставляете значения другого столбца и ничего не делаете со столбцом PK:

insert into T
(foo)   -- column(s) list
values('bar') -- values list

Ваша сохраненная процедура, которая выполняет вставку, может сделать SCOPE_IDENTITY значением RETURN или SCOPE_IDENTITY может быть передано обратно клиенту в качестве параметра OUT.

PS SCOPE_IDENTITY () возвращает последнее сгенерированное автоматически увеличивающееся значение идентификатора в текущей области; он не генерирует следующее значение идентичности.

РЕДАКТИРОВАТЬ:

Предположительно, ваша таблица администраторов содержит набор администраторов. Но если у него нет каких-либо столбцов, кроме столбца целочисленного первичного ключа, нет никакого способа идентифицировать администраторов; единственное, что вы можете сделать, это отличить их друг от друга. Это совсем не уведет вас далеко. Но если ваша таблица администратора имеет одну из следующих структур:

ID   INTEGER PRIMARY KEY AUTOINCREMENT
windowsusername   varchar(50)  (unique index)

ИЛИ ЖЕ

windowsusername varchar(50) primary key

вы сможете ссылаться на таблицу администратора из других таблиц, а внешние ключи будут ЗНАЧИТЕЛЬНЫМИ. И именно этого не хватает в таблице, состоящей из одного целочисленного столбца, - смысла.

Имея два столбца, вы можете сделать это с помощью хранимой процедуры:

insert into Administrators
(windowsusername)
values('mydomain\someusername');
return SCOPE_IDENTITY();

и ваша клиентская программа вернет в качестве возвращаемого значения автоматически увеличенный идентификатор, который был автоматически сгенерирован и назначен вновь вставленной строке. Такой подход является обычной практикой, и я бы даже сказал, что он считается «лучшей практикой».

PS Вы упомянули, что не знали, как «вставить значение», если вам «нечего было вставлять». Здесь есть противоречие. Если вставлять нечего, зачем вставлять? Зачем вам создавать, скажем, новую запись CUSTOMER, если вы абсолютно ничего не знаете о клиенте? Ни имени, ни города, ни номера телефона, ничего?

Тим
источник
2
В моей таблице есть ОДИН столбец, adminId, который представляет собой инкрементное значение int
Фил
Это самый странный дизайн, который я когда-либо видел, я занимаюсь этим бизнесом более 20 лет и видел некоторые странные вещи в свое время. Итак, ваш вопрос: как вы вставляете в таблицу, которая содержит только столбец первичного ключа, определенный как столбец с автоинкрементным идентификатором, когда таблица содержит этот столбец PK и только этот столбец PK, никаких других столбцов ..
Тим,
Так что за отрицательный голос? Фактическая ошибка где-то или для выражения мнения о непригодности дизайна?
Тим
1
Просто чтобы прояснить причину создания DB. У нас есть пользователи в одной таблице. Если есть отношение между пользователями и администраторами; они рассматриваются как администраторы. В административной таблице больше нечего хранить, кроме фактического уникального идентификатора. «Настоящие» данные находятся в пользовательской таблице и в имеющем отношении (с отметками времени, предоставленными и т. Д.).
Фил
1
@Phil: Итак, вы используете таблицу и отношения внешнего ключа, чтобы выразить то, что может делать простой логический / битовый столбец. Возможно, вы не сможете добавить такой битовый столбец в свою таблицу, и вам придется искать обходной путь. But an autoincrementing integer whose autoincrementation must be disabled is a poor solution.Все, что вам нужно, это параллельная таблица с однозначным отношением к таблице пользователей, и в этой таблице вы создаете битовый столбец. Если этот столбец истинен, это означает, что у пользователя есть-admin. Чистый. Стандарт. Дизайн.
Тим