SQL Server: comment contraindre une table à contenir une seule ligne?

Je veux stocker une seule ligne dans une table de configuration pour mon application. Je voudrais faire respecter que cette table ne peut contenir qu'une seule ligne.

Quel est le moyen le plus simple d'appliquer la contrainte à une ligne?

59
demandé sur A-K 2010-10-19 14:25:25

10 réponses

Vous vous assurez que l'une des colonnes ne peut contenir qu'une seule valeur, puis en faire la clé primaire (ou appliquer une contrainte d'unicité).

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

J'ai un certain nombre de ces tables dans diverses bases de données, principalement pour stocker config. C'est beaucoup plus agréable de savoir que, si l'élément de configuration doit être un int, vous ne lirez jamais un int de la base de données.

74
répondu Damien_The_Unbeliever 2016-04-01 08:55:54

J'utilise habituellement L'approche de Damien, qui a toujours bien fonctionné pour moi, mais j'ajoute aussi une chose:

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')
)

En ajoutant le " par défaut 'X'", vous n'aurez jamais à gérer la colonne de verrouillage, et vous n'aurez pas à vous rappeler quelle était la valeur de verrouillage lors du chargement de la table pour la première fois.

42
répondu ACB 2010-10-19 18:54:50

Vous voudrez peut-être repenser cette stratégie. Dans des situations similaires, j'ai souvent trouvé inestimable de laisser les anciennes lignes de configuration traîner pour des informations historiques.

Pour ce faire, vous avez en fait une colonne supplémentaire creation_date_time (date / heure d'insertion ou de mise à jour) et un déclencheur insert ou insert/update qui le remplira correctement avec la date/heure actuelle.

Ensuite, afin d'obtenir votre configuration actuelle, vous utilisez quelque chose comme:

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

(en fonction de votre SGBD saveur).

De cette façon, vous pouvez toujours maintenir l'historique à des fins de récupération (vous pouvez instituer des procédures de nettoyage si la table devient trop grande mais cela est peu probable) et vous pouvez toujours travailler avec la dernière configuration.

14
répondu paxdiablo 2010-10-19 10:35:20

Vous pouvez implémenter un déclencheur au lieu de pour appliquer ce type de logique métier dans la base de données.

Le déclencheur peut contenir une logique pour vérifier si un enregistrement existe déjà dans la table et si c'est le cas, annuler L'insertion.

Maintenant, en prenant un peu de recul pour regarder l'image plus grande, je me demande s'il existe peut-être un moyen alternatif et plus approprié pour stocker ces informations, peut-être dans un fichier de configuration ou une variable d'environnement par exemple?

4
répondu John Sansom 2010-10-19 11:47:16

J'utilise un champ de bits pour la clé primaire avec le nom IsActive. Donc, il peut y avoir 2 lignes au plus et et le sql pour obtenir la ligne valide est: sélectionnez * dans les paramètres où IsActive = 1 si la table est nommée Paramètres.

2
répondu user3382925 2014-03-05 09:52:12

Voici une solution que j'ai trouvée pour une table de type verrou qui ne peut contenir qu'une seule ligne, contenant un Y ou N (un État de verrouillage d'application, par exemple).

Créez la table avec une colonne. J'ai mis une contrainte de vérification sur une colonne afin que seul un Y ou N puisse y être mis. (Ou 1 ou 0, ou autre)

Insérer une ligne dans le tableau, avec l'état "normal" (par exemple N signifie non verrouillé)

Créez ensuite un déclencheur D'insertion sur la table qui n'a qu'un SIGNAL (DB2) ou RAISERROR (SQL Serveur) ou RAISE_APPLICATION_ERROR (Oracle). Cela fait en sorte que le code d'application peut mettre à jour la table, mais tout INSERT échoue.

DB2 exemple:

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';

Fonctionne pour moi.

2
répondu David A Beamer 2015-03-11 14:35:08

Vous pouvez écrire un déclencheur sur l'action d'insertion sur la table. Chaque fois que quelqu'un essaie d'insérer une nouvelle ligne dans la table, lancez la logique de suppression de la dernière ligne dans le code de déclenchement d'insertion.

1
répondu Karan 2010-10-19 10:28:38

Ancienne question Mais Que diriez-vous d'utiliser IDENTITY(MAX,1) d'un petit type de colonne?

CREATE TABLE [dbo].[Config](
[ID] [tinyint] IDENTITY(255,1) NOT NULL,
[Config1] [nvarchar](max) NOT NULL,
[Config2] [nvarchar](max) NOT NULL
1
répondu NeutronCode 2015-04-13 13:55:54
IF NOT EXISTS ( select * from table )
BEGIN
    ///Your insert statement
END
0
répondu Sachin Shanbhag 2010-10-19 10:27:42

Ici, nous pouvons également faire une valeur invisible qui sera la même après la première entrée dans la base de données.Exemple: Table Des Étudiants: Id: int prénom:char Ici, dans la zone d'entrée,nous devons spécifier la même valeur pour la colonne id qui se limitera comme après la première entrée autre que l'écriture lock bla bla en raison de la contrainte de clé primaire n'ayant ainsi qu'une seule ligne pour toujours. Espérons que cette aide!

0
répondu Yishagerew 2013-02-26 16:15:55