确保SQLite表只有一行

时间:2015-10-13 13:34:15

标签: sql sqlite

如何强制表只有一行?以下是我的尝试。 UPDATE触发器可能有效,但CREATE触发器肯定不会。对于CREATE,我想使用SET,但SQLite不支持SET

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;

2 个答案:

答案 0 :(得分:17)

在一般情况下,要限制表中的行数,必须阻止任何进一步的插入。 在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;

但是,如果限制为1,则可以简单地将主键限制为固定值:

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

答案 1 :(得分:5)

您可能想要考虑的一个想法是让它看起来像表只有一行。实际上,您保留以前的所有行,因为很可能您有一天会想要保留所有过去值的历史记录。

由于只有一行,所以实际上不需要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触发器可以将更新转换为插入 - 您实际上并不想更改值,只需使用新值写入新行。然后它成为新的"当前"行。

现在您看起来只有一行的表格,但您也保留了以前对该行所做的所有过去更改的完整历史记录。