确保SQLite表只有一行

use*_*531 13 sql sqlite

如何强制表只有一行?以下是我的尝试.该UPDATE触发器可以工作,但是,CREATE触发绝对不会.SET但是,对于CREATE,我想使用SETSQLite不支持.

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;
Run Code Online (Sandbox Code Playgroud)

CL.*_*CL. 18

在一般情况下,要限制表中的行数,必须阻止任何进一步的插入.在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;
Run Code Online (Sandbox Code Playgroud)

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

CREATE TABLE config (
    id INTEGER PRIMARY KEY CHECK (id = 0),
    [...]
);
Run Code Online (Sandbox Code Playgroud)


Tom*_*att 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`)
);
Run Code Online (Sandbox Code Playgroud)

由于通常只对最后写入的行(最新版本)感兴趣,因此查询将选择具有最新创建日期的行:

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 );
Run Code Online (Sandbox Code Playgroud)

create view config as在此查询前放置一个,您将拥有一个视图,该视图仅从表中选择一行,即最新的。对视图的任何查询都返回一行:

select  *
from    config;
Run Code Online (Sandbox Code Playgroud)

一个instead of对视图触发器可以更新转换为插入-你实际上并不想改变值,只写一个新行的新值。然后,这成为新的“当前”行。

现在,您的表似乎只有一行,但是您也保留了对该行过去所做的所有更改的完整历史记录。