web-dev-qa-db-fra.com

Comment limiter le nombre maximum de lignes dans une table à seulement 1

J'ai une table de configuration dans ma base de données SQL Server et cette table ne doit avoir qu'une seule ligne. Pour aider les futurs développeurs à comprendre cela, j'aimerais empêcher l'ajout de plusieurs lignes de données. J'ai choisi d'utiliser un déclencheur pour cela, comme ci-dessous ...

ALTER TRIGGER OnlyOneConfigRow
    ON [dbo].[Configuration]
    INSTEAD OF INSERT
AS
BEGIN
    DECLARE @HasZeroRows BIT;
    SELECT  @HasZeroRows = CASE
        WHEN COUNT (Id) = 0 THEN 1
        ELSE 0
    END
    FROM
        [dbo].[Configuration];

    IF EXISTS(SELECT [Id] FROM inserted) AND @HasZeroRows = 0
    BEGIN
        RAISERROR ('You should not add more than one row into the config table. ', 16, 1)    
    END
END

Cela ne génère pas d'erreur mais ne permet pas à la première ligne d'entrer.

Existe-t-il également un moyen plus efficace/plus explicite de limiter le nombre de lignes pouvant être insérées dans une table à seulement 1? Suis-je en train de manquer une fonctionnalité SQL Server intégrée?

23
Dib

Ces deux contraintes feraient:

CREATE TABLE dbo.Configuration
( ConfigurationID TINYINT NOT NULL DEFAULT 1,
  -- the rest of the columns
  CONSTRAINT Configuration_PK 
    PRIMARY KEY (ConfigurationID),
  CONSTRAINT Configuration_OnlyOneRow 
    CHECK (ConfigurationID = 1)
) ;

Vous avez besoin à la fois du PRIMARY KEY (ou une contrainte UNIQUE) donc deux lignes n'ont pas la même valeur ID et la contrainte CHECK donc toutes les lignes ont la même valeur ID (arbitrairement choisi pour 1).
En combinaison, les deux contraintes presque opposées limitent le nombre de lignes à zéro ou à un.


Sur un SGBD fictif (aucune implémentation SQL actuelle ne permet cette construction) qui autorise une clé primaire composée de 0 colonnes, ce serait aussi une solution:

CREATE TABLE dbo.Configuration
( -- no ConfigurationID needed at all
  -- the rest of the columns
  CONSTRAINT Configuration_PK 
    PRIMARY KEY ()                -- 0 columns!
) ;
53
ypercubeᵀᴹ

Vous pouvez définir l'ID comme une colonne calculée évaluant une valeur constante et déclarer cette colonne comme unique:

CREATE TABLE dbo.Configuration
(
  ID AS CAST(1 AS tinyint),  -- or: AS bit
  ...  -- other columns
  CONSTRAINT UQ_Configuration_ID UNIQUE (ID)
);
24
Andriy M

Vous pouvez également utiliser le déclencheur.

create trigger LimitTable
on YourTableToLimit
after insert
as
    declare @tableCount int
    select @tableCount = Count(*)
    from YourTableToLimit

    if @tableCount > 50
    begin
        rollback
    end
go
9
user98113

Semble un peu une exigence étrange mais ho-hum :) Vous pourriez simplement avoir une contrainte sur la table et autoriser uniquement les mises à jour (pas d'insertion ou de suppression) de la table?

CREATE TABLE dbo.Config (
    ID INT identity(1,1), 
    CONFIGURATION VARCHAR(MAX),
    constraint ck_limitrows CHECK (ID <=1) 
    );

Cependant, c'est un peu une manière hackey de le faire, ne serait-il pas préférable d'appliquer simplement des changements à la configuration via une procédure stockée qui peut alors gérer toute cette logique pour vous?

1
Mat