2015-10-13 46 views
5

如何強制一個表只有一行?以下是我的嘗試。 UPDATE觸發器可能工作,但是,CREATE觸發器肯定不會。對於CREATE,我想使用SET,但是SQLite不支持SET確保SQLite表只有一行

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; 

回答

7

在一般情況下,要限制表中的行數,必須防止進一步插入。 在SQLite的,這與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; 

但是,如果限制是,你可以,而不是簡單地限制主鍵爲固定值:

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

我喜歡你的第二個解決方案!感謝有關'RAISE'的解釋。不是因爲給出第二個解決方案,我需要使用觸發器,'UPDATE'約束如何執行?我如何使用CREATE TRIGGER顯示它config_update_zero BEFORE UPDATE ON config FOR EACH ROW BEGIN NEW.id = OLD.id; END; NEW.id = OLD.id;'? – user1032531

+0

你需要什麼UPDATE觸發器? –

+0

不想允許'UPDATE config SET id = 2'。當然,你的第二種解決方案可以防止這種情況發生,並且只是好奇它將如何完成觸發。 – user1032531

1

一個想法,你可能希望要考慮的是使它看起來像表格只有一行。事實上,你保留了以前的所有行,因爲很有可能你有一天想保持所有過去值的歷史記錄。

由於只有一行,實際上不需要一個ID列,其目的是唯一地區分每一行和其他行。但是,您確實需要一個時間戳,用於標識寫入表中最後一行的「一行」。

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`) 
); 

既然你是隻寫了最後一行(最新版本)的正常興趣,查詢選擇具有最新的創建日期行:

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); 

在此查詢前加上create view config as並且您有一個視圖只從表格中選擇最新的一行。對視圖的任何查詢返回的一行:

select * 
from config; 

instead of扳機上視圖可以更新轉換爲插入 - 你實際上並不想改變值,只寫一個新行的新值。然後這成爲新的「當前」行。

現在你擁有了只有一行的表格,但是你也保存了對該行所做的所有過去的更改的完整歷史記錄。