SQL Server:如何限制一个表包含单行?

我想在我的应用程序的configuration表中存储一行。 我想强制这个表只能包含一行。

什么是最简单的方法来执行单行约束?

您确保其中一个列只能包含一个值,然后将其作为主键(或应用唯一性约束)。

 CREATE TABLE T1( Lock char(1) not null, /* Other columns */, constraint PK_T1 PRIMARY KEY (Lock), constraint CK_T1_Locked CHECK (Lock='X') ) 

我在各种数据库中有许多这些表,主要是用于存储configuration。 知道如果configuration项应该是一个int,你将只能从DB中读取一个int。

我通常使用Damien的方法,这对我来说一直很好,但我还补充一点:

 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列,并且在第一次加载表格时不必记住哪个是locking值。

你可能想重新思考这个策略。 在类似的情况下,我经常发现保留旧的configuration行以获取历史信息是非常宝贵的。

为此,您实际上有一个额外的列creation_date_time (插入或更新的date/时间)和一个插入或插入/更新触发器,它将使用当前date/时间正确填充它。

然后,为了获得您当前的configuration,您使用如下所示:

 select * from config_table order by creation_date_time desc fetch first row only 

(取决于你的DBMS风味)。

这样,您仍然可以维护历史logging以进行恢复(如果表格变得太大,您可以执行清理过程,但这种情况不太可能),而且您仍然可以使用最新的configuration。

您可以实施一个INSTEAD OF 触发器来在数据库中执行这种types的业务逻辑。

触发器可以包含逻辑来检查表中是否已经存在一个logging,如果是的话,ROLLBACK插入。

现在,回过头来看看更大的图景,我想知道是否有其他更合适的方式来存储这些信息,例如可能是在configuration文件或环境variables中?

我使用名字为IsActive的主键位字段。 所以最多可以有2行,而sql得到有效的行是:select * from Settings其中IsActive = 1如果表名为Settings。

这里有一个解决scheme,我想出了一个锁types的表,它只能包含一行,保持Y或N(例如应用程序locking状态)。

用一列创build表。 我把一个检查约束放在一列,只有一个Y或N可以放在里面。 (或1或0,或其他)

在表格中插入一行,使用“正常”状态(例如N表示未locking)

然后在只有SIGNAL(DB2)或RAISERROR(SQL Server)或RAISE_APPLICATION_ERROR(Oracle)的表上创build一个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'; 

为我工作。

 IF NOT EXISTS ( select * from table ) BEGIN ///Your insert statement END 

您可以在表上的插入操作上编写触发器。 无论何时有人试图在表中插入一个新行,都要消除插入触发代码中删除最新行的逻辑。

在这里,我们也可以创build一个不可见的值,在数据库的第一个入口之后是相同的。例子:学生表:Id:int firstname:char这里在input框中,我们必须指定相同的值id列,这将限制作为第一次进入之后,由于主键约束而不能写入lockingbla,因而永远只有一行。 希望这可以帮助!

老问题,但如何使用小列types的IDENTITY(MAX,1)?

 CREATE TABLE [dbo].[Config]( [ID] [tinyint] IDENTITY(255,1) NOT NULL, [Config1] [nvarchar](max) NOT NULL, [Config2] [nvarchar](max) NOT NULL