我想在我的应用程序的配置表中存储一行。我想强制该表只能包含一行。
强制单行约束的最简单方法是什么?
确保其中一列只能包含一个值,然后将其设为主键(或应用唯一性约束)。
CREATE TABLE T1(
Lock char(1) not null,
/* Other columns */,
constraint PK_T1 PRIMARY KEY (Lock),
constraint CK_T1_Locked CHECK (Lock='X')
)
我在各种数据库中有许多这样的表,主要用于存储配置。知道如果配置项应该是 int,那么您只能从数据库中读取 int,这要好得多。
我通常使用达米安的方法,这对我来说一直很有效,但我还补充一件事:
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')
)
添加“DEFAULT 'X'”,您将永远不必处理 Lock 列,并且在第一次加载表时不必记住哪个是锁定值。
您可能需要重新考虑这一策略。在类似的情况下,我经常发现保留旧的配置行以获取历史信息是非常宝贵的。
为此,您实际上有一个额外的列
creation_date_time
(插入或更新的日期/时间)和一个插入或插入/更新触发器,它将使用当前日期/时间正确填充它。
然后,为了获取当前配置,您可以使用以下命令:
select * from config_table order by creation_date_time desc fetch first row only
(取决于您的 DBMS 风格)。
这样,您仍然可以维护用于恢复目的的历史记录(如果表变得太大,您可以制定清理程序,但这不太可能),并且您仍然可以使用最新的配置。
您可以实现 INSTEAD OF Trigger 以在数据库中强制执行此类业务逻辑。
触发器可以包含逻辑来检查表中是否已存在记录,如果存在,则回滚插入。
现在,退一步看一下更大的图景,我想知道是否有一种替代的、更合适的方式来存储这些信息,例如在配置文件或环境变量中?
我知道这已经很老了,但有时最好不要考虑大,而是使用像这样的恒等整数:
Create Table TableWhatever
(
keycol int primary key not null identity(1,1)
check(keycol =1),
Col2 varchar(7)
)
这样,每次您尝试插入另一行时,检查约束都会引发,阻止您插入任何行,因为身份 p 键不接受除 1 之外的任何值
这是我为锁定类型表提出的一种解决方案,该表只能包含一行,保存 Y 或 N(例如应用程序锁定状态)。
创建包含一列的表格。我在一列上放置了检查约束,以便只能在其中放入 Y 或 N。 (或 1 或 0,或其他)
在表中插入一行,状态为“正常”(例如N表示未锁定)
然后在只有 SIGNAL (DB2) 或 RAISERROR (SQL Server) 或 RAISE_APPLICATION_ERROR (Oracle) 的表上创建 INSERT 触发器。这使得应用程序代码可以更新表,但任何 INSERT 都会失败。
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';
对我有用。
我使用名为 IsActive 的位字段作为主键。 所以最多可以有2行,获取有效行的sql是: 从设置中选择 *,其中 IsActive = 1 如果该表名为“设置”。
最简单的方法是将 ID 字段定义为值 1(或任何数字,....)的计算列,然后考虑 ID 的唯一索引。
CREATE TABLE [dbo].[SingleRowTable](
[ID] AS ((1)),
[Title] [varchar](50) NOT NULL,
CONSTRAINT [IX_SingleRowTable] UNIQUE NONCLUSTERED
(
[ID] ASC
)
) ON [PRIMARY]
您可以在表上的插入操作上编写触发器。每当有人尝试在表中插入新行时,请消除插入触发器代码中删除最新行的逻辑。
老问题,但是使用小列类型的 IDENTITY(MAX,1) 怎么样?
CREATE TABLE [dbo].[Config](
[ID] [tinyint] IDENTITY(255,1) NOT NULL,
[Config1] [nvarchar](max) NOT NULL,
[Config2] [nvarchar](max) NOT NULL
CREATE TABLE T1(
id ENUM('') NOT NULL PRIMARY KEY,
/* Other columns */,
)
IF NOT EXISTS ( select * from table )
BEGIN
///Your insert statement
END
这里我们还可以创建一个不可见的值,该值在第一次输入数据库后将相同。例如: 学生表: 编号:整数 名字:char 在输入框中,我们必须为 id 列指定相同的值,该值将在第一个条目之后受到限制,而不是由于主键约束而写入锁定 bla bla,因此永远只有一行。 希望这有帮助!