Chcę przechowywać pojedynczy wiersz w tabeli konfiguracji dla mojej aplikacji. Chciałbym wymusić, aby ta tabela zawierała tylko jeden wiersz.
Jaki jest najprostszy sposób na wymuszenie ograniczenia jednego wiersza?
sql-server
database-design
singleton
Jaskółka oknówka
źródło
źródło
(Name, Value)
z kluczem podstawowym w nazwie. Wtedy możesz miećselect Value from Table where Name = ?
pewność, że nie zostaną zwrócone żadne wiersze lub jeden wiersz.Name
?ar
komentarz s. Problem polega na tym, że jeśli przechowujesz tylko pary nazwa / wartość, wartość całkiem dobrze musi być ciągiem i nie masz możliwości wymuszenia walidacji w bazie danych. Gdy używasz jednorzędowej tabeli z oddzielnymi kolumnami dla każdego ustawienia (zgodnie z wymaganiami OP), możesz łatwo wymusić walidację dla każdego ustawienia konfiguracji za pomocą ograniczeń sprawdzających.Odpowiedzi:
Upewnij się, że jedna z kolumn może zawierać tylko jedną wartość, a następnie ustaw ją jako klucz podstawowy (lub zastosuj ograniczenie niepowtarzalności).
CREATE TABLE T1( Lock char(1) not null, /* Other columns */, constraint PK_T1 PRIMARY KEY (Lock), constraint CK_T1_Locked CHECK (Lock='X') )
Mam wiele takich tabel w różnych bazach danych, głównie do przechowywania konfiguracji. O wiele przyjemniej jest wiedzieć, że jeśli element konfiguracyjny powinien być intem, zawsze będziesz czytać tylko int z DB.
źródło
comp.databases.theory
grupy usenet (widocznej przez grupy Google), o której przyznaję, że ostatnio niewiele czytałem. Był bardziej zorientowany na teorię relacyjną niż na SQL - ale akurat wiedziałem, że dportas / sqlvogel również uczęszczał do tej samej grupy. TTM było nawiązaniem do Trzeciego Manifestu , który jest dobrą książką mówiącą (znowu) o teorii relacyjnej, a nie o SQL.Zwykle stosuję podejście Damiena, które zawsze działało świetnie, ale dodam też jedną rzecz:
CREATE TABLE T1( Lock char(1) not null DEFAULT 'X', /* Other columns */, constraint PK_T1 PRIMARY KEY (Lock), constraint CK_T1_Locked CHECK (Lock='X') )
Dodając „DEFAULT 'X'”, nigdy nie będziesz musiał zajmować się kolumną Lock i nie będziesz musiał pamiętać, która była wartością blokady podczas ładowania tabeli po raz pierwszy.
źródło
Lock char(1) not null CONSTRAINT DF_T1_Lock DEFAULT 'X'
Możesz przemyśleć tę strategię. W podobnych sytuacjach często uważałem za nieocenione pozostawienie starych rzędów konfiguracji w poszukiwaniu informacji historycznych.
Aby to zrobić, faktycznie masz dodatkową kolumnę
creation_date_time
(data / godzina wstawienia lub aktualizacji) i wyzwalacz wstawiania lub wstawiania / aktualizacji, który wypełni ją poprawnie bieżącą datą / godziną.Następnie, aby uzyskać aktualną konfigurację, użyj czegoś takiego:
select * from config_table order by creation_date_time desc fetch first row only
(w zależności od twojego smaku DBMS).
W ten sposób nadal możesz zachować historię do celów odzyskiwania (możesz wprowadzić procedury czyszczenia, jeśli tabela stanie się zbyt duża, ale jest to mało prawdopodobne) i nadal możesz pracować z najnowszą konfiguracją.
źródło
SELECT TOP 1 ... ORDER BY creation_date_time DESC
Możesz zaimplementować wyzwalacz INSTEAD OF Trigger, aby wymusić ten typ logiki biznesowej w bazie danych.
Wyzwalacz może zawierać logikę, aby sprawdzić, czy rekord już istnieje w tabeli, a jeśli tak, ROLLBACK wstawkę.
Teraz, cofając się, by spojrzeć na szerszą perspektywę, zastanawiam się, czy może istnieje alternatywny i bardziej odpowiedni sposób przechowywania tych informacji, na przykład w pliku konfiguracyjnym lub zmiennej środowiskowej?
źródło
Używam pola bitowego dla klucza podstawowego o nazwie IsActive. Więc mogą być maksymalnie 2 wiersze, a sql, aby uzyskać prawidłowy wiersz, to: wybierz * z Ustawień, gdzie IsActive = 1, jeśli tabela ma nazwę Ustawienia.
źródło
Oto rozwiązanie, które wymyśliłem dla tabeli typu blokady, która może zawierać tylko jeden wiersz, zawierający Y lub N (na przykład stan blokady aplikacji).
Utwórz tabelę z jedną kolumną. Położyłem ograniczenie sprawdzające na jednej kolumnie, aby można było w niej umieścić tylko Y lub N. (Lub 1 lub 0 lub cokolwiek)
Wstaw jeden wiersz w tabeli ze stanem „normalnym” (np. N oznacza niezablokowane)
Następnie utwórz wyzwalacz INSERT w tabeli, która ma tylko SIGNAL (DB2) lub RAISERROR (SQL Server) lub RAISE_APPLICATION_ERROR (Oracle). To sprawia, że kod aplikacji może aktualizować tabelę, ale każda operacja INSERT kończy się niepowodzeniem.
Przykład DB2:
create table PRICE_LIST_LOCK ( LOCKED_YN char(1) not null constraint PRICE_LIST_LOCK_YN_CK check (LOCKED_YN in ('Y', 'N') ) ); --- do this insert when creating the table insert into PRICE_LIST_LOCK values ('N'); --- once there is one row in the table, create this trigger CREATE TRIGGER ONLY_ONE_ROW_IN_PRICE_LIST_LOCK NO CASCADE BEFORE INSERT ON PRICE_LIST_LOCK FOR EACH ROW SIGNAL SQLSTATE '81000' -- arbitrary user-defined value SET MESSAGE_TEXT='Only one row is allowed in this table';
Pracuje dla mnie.
źródło
Stare pytanie, ale co powiesz na użycie IDENTITY (MAX, 1) małego typu kolumny?
CREATE TABLE [dbo].[Config]( [ID] [tinyint] IDENTITY(255,1) NOT NULL, [Config1] [nvarchar](max) NOT NULL, [Config2] [nvarchar](max) NOT NULL
źródło
Możesz napisać wyzwalacz dla akcji wstawiania na stole. Za każdym razem, gdy ktoś próbuje wstawić nowy wiersz do tabeli, odpal logikę usuwania ostatniego wiersza w kodzie wyzwalacza wstawiania.
źródło
IF NOT EXISTS ( select * from table ) BEGIN ///Your insert statement END
źródło
Tutaj możemy również stworzyć niewidoczną wartość, która będzie taka sama po pierwszym wpisie do bazy danych Przykład: Tabela uczniów: Id: int firstname: char Tutaj w polu wejściowym musimy podać tę samą wartość dla kolumny id, która ograniczy jak po pierwszym wpisie innym niż zapis lock bla bla ze względu na ograniczenie klucza podstawowego, a zatem posiadanie tylko jednego wiersza na zawsze. Mam nadzieję że to pomoże!
źródło