Wstawianie wierszy do tabeli zawierającej tylko jedną kolumnę IDENTITY

83

Mam administratora tabeli z tylko jedną kolumną, adminId, która jest kluczem podstawowym. Ze względu na reguły biznesowe musi tak być.

Chciałbym raz na zawsze zrozumieć, w jaki sposób mogę pisać procedury składowane, które wstawiają wartości w takich tabelach. Używam SQL Server i T-SQL i próbowałem użyć SCOPE_IDENTITY (), ale to nie działa, ponieważ tabela ma wartość INSERT_IDENTITY na false lub off.

Naprawdę nie chciałbym wstawiać wartości fikcyjnej tylko po to, aby móc wstawić nowy wiersz. Dzięki!

Phil
źródło
1
Dla wyjaśnienia: Twoje pytanie brzmi „jak wstawić wiersze do tabeli programu SQL Server z pojedynczą kolumną IDENTITY”?
gbn
Tak, masz rację, dziękuję za wyjaśnienie
Phil
2
W przypadku osób lądujących tutaj zostało to wcześniej zadane, a prawidłowa odpowiedź jest tutaj: stackoverflow.com/questions/850327/…
BJury,

Odpowiedzi:

140

Jeśli masz jedną kolumnę, która jest TOŻSAMOŚCIĄ, po prostu zrób to

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

Jeśli nie masz tożsamości, czy możesz ją ustawić? To jest najlepszy sposób ... i użyj powyższego kodu SQL.

Jeśli nie, chcesz wstawić nowy wiersz

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

Uwagi:

  • Przy dużych obciążeniach rozwiązanie MAX może zawieść z duplikatami
  • SCOPE_IDENTITY jest po fakcie, a nie wcześniej
  • SCOPE_IDENTITY działa tylko z kolumną IDENTITY. Podobnie jak każdy idiotyzm przy użyciu IDENT_CURRENT
  • Klauzula wyjściowa zastępuje SCOPE_IDENTITY dla rozwiązania MAX
gbn
źródło
1

Musisz dodać IDENTITY_INSERT do wybranej instrukcji:

SET IDENTITY_INSERT MyTable ON

INSERT INTO MyTable
(AdminCol)

SELECT AdminColValue

 FROM Tableb

Kiedy skończysz, pamiętaj o tym

SET IDENTITY_INSERT MyTable OFF

Oto dobry opis tego, jak to działa w BOL: http://msdn.microsoft.com/en-us/library/aa259221(SQL.80).aspx

DataWriter
źródło
Czy mam to zrobić w ten sposób: USTAWIĆ Administratora IDENTITY_INSERT ON WSTAW DO Administratora (SCOPE_IDENTITY ()) WYŁĄCZYĆ Administratora IDENTITY_INSERT?
Phil
Tak. To wszystko, co musisz zrobić. Ustaw na, napisz swój kod, WYŁĄCZ na końcu.
DataWriter
Myślę, że to nie jest właściwa odpowiedź. Jeśli jest to kolumna tożsamości, nie powinieneś dodawać do niej wartości. Zaakceptowana odpowiedź jest poprawną odpowiedzią.
Mmm
0

@Phil: Czy nie masz na myśli, że twoja tabela ma dwie (2) kolumny, kolumnę PK z automatyczną inkrementacją i kolumnę AdminName? Jeśli ma tylko jedną kolumnę, w której znajduje się AdminName, AdminName jest PK i oczywiście nie można automatycznie zwiększać ciągu. Czy reguły biznesowe wymagają, aby w pełni kwalifikowana nazwa użytkownika systemu Windows była kluczem podstawowym? Byłoby to wykonalne i sensowne, ponieważ wtedy nie byłby potrzebny alternatywny unikalny indeks w kolumnie AdminName.

Ale jeśli twoja tabela ma dwie kolumny, a nie jedną:

W SQLServer autoincrement jest częścią definicji tabeli / kolumny. Definiujesz kolumnę jako liczbę całkowitą, a następnie ustawiasz ją jako kolumnę tożsamości, określając przyrost, zwykle 1, ale może to być 2, 5 lub 10 lub cokolwiek. Aby wstawić wiersz, wystarczy wstawić inne wartości kolumn i nic nie robić z kolumną PK:

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

Twój zapisany proces, który wykonuje wstawianie, może uczynić SCOPE_IDENTITY wartością RETURN lub SCOPE_IDENTITY może zostać przekazany klientowi jako parametr OUT.

PS SCOPE_IDENTITY () zwraca ostatnio wygenerowaną wartość tożsamości automatycznie inkrementowaną w bieżącym zakresie; nie generuje następnej wartości tożsamości.

EDYTOWAĆ:

Przypuszczalnie twoja tabela Administratorzy zawiera zestaw administratorów. Ale jeśli nie ma żadnych kolumn poza kolumną klucza podstawowego w postaci liczby całkowitej, nie ma możliwości zidentyfikowania administratorów; jedyne, co możesz zrobić, to odróżnić je od siebie. To wcale nie prowadzi zbyt daleko. Ale jeśli twoja tabela administratora miała jedną z następujących struktur:

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

LUB

windowsusername varchar(50) primary key

mógłbyś odwołać się do tabeli Administratora z innych tabel, a klucze obce byłyby ZNACZNE. I właśnie tego brakuje tabeli składającej się z jednej kolumny całkowitej - czyli.

Mając dwie kolumny, możesz wtedy wykonać procedurę składowaną:

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

a program-klient odzyskałby jako wartość zwracaną automatycznie zwiększany identyfikator, który został wygenerowany automatycznie i przypisany do nowo wstawionego wiersza. Takie podejście jest zwykłą praktyką i posunąłbym się nawet do stwierdzenia, że ​​jest uważane za „najlepszą praktykę”.

PS Wspomniałeś, że nie wiedziałeś, jak „wstawić wartość”, jeśli „nie masz nic do wstawienia”. Jest w tym sprzeczność. Jeśli nie masz nic do wstawienia, po co wstawiać? Dlaczego miałbyś tworzyć, powiedzmy, nowy rekord KLIENT, jeśli nie wiesz absolutnie nic o kliencie? Nie imię, nazwisko, miasto, numer telefonu, nic?

Tim
źródło
2
Moja tabela ma JEDNĄ kolumnę, adminId, która jest przyrostową wartością int
Phil
To najdziwniejszy projekt, jaki kiedykolwiek widziałem, a jestem w branży od ponad 20 lat i widziałem dziwne rzeczy w ciągu moich dni. Więc twoje pytanie brzmi: jak wstawić do tabeli, która zawiera tylko kolumnę klucza podstawowego zdefiniowaną jako kolumna tożsamości z autoinkrementacją, kiedy tabela zawiera tę kolumnę PK i tylko tę kolumnę PK, żadnych innych kolumn ..
Tim
Więc po co głos przeciw? Błąd merytoryczny gdzieś czy za wyrażenie opinii o braku merytorycznego projektu?
Tim,
1
Tylko po to, by wyjaśnić powody stojące za projektem DB. Mamy użytkowników w jednej tabeli. Jeśli istnieje związek między użytkownikami i administratorami; są traktowani jak administratorzy. W tabeli administracyjnej nie ma nic więcej niż rzeczywisty unikalny identyfikator. „Rzeczywiste” dane znajdują się w tabeli użytkowników i mają związek (z sygnaturami czasowymi, kto przyznał itp.).
Phil
1
@Phil: Więc używasz tabeli i relacji klucza obcego, aby wyrazić, co mogłaby zrobić prosta kolumna logiczna / bitowa. Możesz nie być w stanie dodać takiej kolumny bitowej do swojej tabeli i musisz wymyślić jakieś obejście. But an autoincrementing integer whose autoincrementation must be disabled is a poor solution.Wszystko, czego potrzebujesz, to tabela równoległa z relacją jeden do jednego z tabelą użytkowników iw tej tabeli utworzysz kolumnę bitową. Kiedy ta kolumna jest prawdziwa, oznacza to, że użytkownik ma-admin. Czysty. Standard. Projekt.
Tim