2015-10-13 16 views
5

Jak mogę wymusić tabelę, aby mieć tylko jeden wiersz? Poniżej jest to, co próbowałem. Wyzwalacz UPDATE może zadziałać, jednak wyzwalacz CREATE zdecydowanie nie zadziała. Dla CREATE, chciałbym użyć SET, jednak SET nie jest obsługiwany przez SQLite.Upewnij się, że tabela SQLite ma tylko jeden wiersz

CREATE TABLE IF NOT EXISTS `config` (
    `id` TINYINT NOT NULL DEFAULT 0, 
    `subdomain` VARCHAR(45) NOT NULL, 
    `timezone` CHAR(3) NOT NULL, 
    `timeout` TINYINT NOT NULL, 
    `offline` TINYINT NOT NULL, 
    `hash_config` CHAR(32) NOT NULL, 
    `hash_points` CHAR(32) NOT NULL, 
    PRIMARY KEY (`id`)); 

INSERT INTO config(id,subdomain,timezone,timeout,offline,hash_config,hash_points) VALUES(0,'subdomain','UTC',5,0,'hash_config','hash_points'); 

CREATE TRIGGER `config_insert_zero` 
BEFORE INSERT ON `config` 
FOR EACH ROW 
BEGIN 
    -- SET NEW.id=0; 
    NEW.id=OLD.id; 
END; 

CREATE TRIGGER `config_update_zero` 
BEFORE UPDATE ON `config` 
FOR EACH ROW 
BEGIN 
    -- SET NEW.id=0; 
    NEW.id=OLD.id; 
END; 

Odpowiedz

7

W ogólnym przypadku, aby ograniczyć liczbę wierszy w tabeli, należy uniemożliwić dalsze wstawianie. W SQLite, odbywa się to z RAISE():

CREATE TRIGGER config_no_insert 
BEFORE INSERT ON config 
WHEN (SELECT COUNT(*) FROM config) >= 1 -- limit here 
BEGIN 
    SELECT RAISE(FAIL, 'only one row!'); 
END; 

Jednakże, jeśli limit jest jeden, można zamiast po prostu ograniczyć klucz podstawowy do ustalonej wartości:

CREATE TABLE config (
    id INTEGER PRIMARY KEY CHECK (id = 0), 
    [...] 
); 
+0

Podoba mi się twoje drugie rozwiązanie! Dzięki za wyjaśnienie dotyczące "RAISE". Nie, że będę musiał użyć wyzwalacza, biorąc pod uwagę twoje drugie rozwiązanie, w jaki sposób wymusić ograniczenie 'UPDATE'? Jak pokazałem to za pomocą 'CREATE TRIGGER config_update_zero PRZED AKTUALIZACJĄ DLA konfiguracji DLA KAŻDEGO WIERSZA BEGIN NEW.id = OLD.id; END; NEW.id = OLD.id; '? – user1032531

+0

Do czego potrzebny byłby wyzwalacz UPDATE? –

+0

Nie można zezwolić na 'UPDATE config SET id = 2'. To prawda, twoje drugie rozwiązanie temu zapobiega i po prostu ciekawiło się, jak to zrobić z wyzwalaczem. – user1032531

1

Jednym z pomysłów może chcesz należy rozważyć, aby wyglądało tak, jakby stół miał tylko jeden rząd. W rzeczywistości zachowujesz wszystkie poprzednie wiersze, ponieważ jest całkiem możliwe, że pewnego dnia będziesz chciał zachować historię wszystkich przeszłych wartości.

Ponieważ istnieje tylko jeden wiersz, tak naprawdę nie ma potrzeby stosowania kolumny identyfikacyjnej, której celem jest jednoznaczne odróżnienie każdego wiersza od pozostałych. Potrzebny jest jednak znacznik czasu, który będzie używany do identyfikacji "jednego wiersza", który będzie ostatnim wierszem zapisanym w tabeli.

CREATE TABLE `config_history` (
    `created` timestamp default current_timestamp, 
    `subdomain` VARCHAR(45) NOT NULL, 
    `timezone` CHAR(3) NOT NULL, 
    `timeout` TINYINT NOT NULL, 
    `offline` TINYINT NOT NULL, 
    `hash_config` CHAR(32) NOT NULL, 
    `hash_points` CHAR(32) NOT NULL, 
    PRIMARY KEY (`created`) 
); 

Ponieważ są zazwyczaj zainteresowani tylko w ostatnim rzędzie pisemnej (najnowsza wersja), kwerenda wybiera wiersz z najnowszej data utworzenia:

select ch.created effective_date, ch.subdomain, ch.timezone, ch.timeout, 
     ch.offline, ch.hash_config, ch.hash_points 
from config_history ch 
where ch.created =(
     select max(created) 
     from config_history); 

umieścić create view config as przed tego zapytania i masz widok, który wybiera tylko jeden wiersz, ostatni, z tabeli. Wszelkie zapytania przeciwko widoku zwraca jeden wiersz:

select * 
from config; 

instead of spust na widoku można przekształcić Aktualizacje dla wkładek - w rzeczywistości nie chcą zmienić wartość, wystarczy napisać nowy wiersz z nowymi wartościami . To staje się nowym "bieżącym" rzędem.

Teraz masz coś, co wydaje się być stołem z jednym rzędem, ale zachowujesz także pełną historię wszystkich dotychczasowych zmian, które kiedykolwiek zostały wprowadzone w tym wierszu.

Powiązane problemy