Bir tablodaki maksimum satır sayısını sadece 1 ile sınırlama


22

SQL Server veritabanımda bir konfigürasyon tablosu var ve bu tablonun sadece bir satırı olmalı. Gelecekteki geliştiricilerin bunu anlamasına yardımcı olmak için birden fazla veri satırının eklenmesini önlemek istiyorum. Bunun için bir tetikleyici kullanmayı seçtim, aşağıdaki gibi ...

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

Bu bir hata atmaz, ancak ilk satırın girmesine izin vermez.

Ayrıca bir tabloya eklenebilecek sıra sayısını sadece 1 ile sınırlamanın daha etkili / daha öz açıklayıcı bir yolu var mı? Herhangi bir yerleşik SQL Server özelliğinde eksik miyim?


2
Orijinal yaklaşımınızın neden işe yaramadığının bir açıklaması gibi: Bunun yerine bir tetikleyici kullanırsınız, bu kodunuzun insert ifadesi yerine çalıştırıldığı anlamına gelir. Bu nedenle, ekin gerçekleşmesi için, açıkça tetikleyicinin bir parçası olarak eklemeniz gerekir.
Scott M,

Yanıtlar:


52

Bu iki kısıtlama yapacaktır:

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

Her ikisine de PRIMARY KEY(veya bir UNIQUEkısıtlamaya) gereksiniminiz vardır, bu nedenle hiçbir iki satır aynı IDdeğerde olmaz ve CHECKkısıtlama da tüm satırların aynı IDdeğerde olmasını sağlar (isteğe bağlı olarak seçilir 1).
Kombinasyonda, neredeyse iki karşıt kısıtlama, satır sayısını sıfır veya bir ile sınırlandırır.


0 sütundan oluşan bir birincil anahtara izin veren kurgusal bir DBMS'de (şu anki SQL uygulamasına bu yapıya izin verilmez), bu da bir çözüm olacaktır:

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

24

Kimliği sabit bir değere göre hesaplanan sütun olarak tanımlayabilir ve bu sütunun benzersiz olduğunu beyan edebilirsiniz:

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

9

Ayrıca tetikleyici kullanabilirsiniz.

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

    if @tableCount > 50
    begin
        rollback
    end
go

1

Biraz tuhaf bir ihtiyaç gibi görünüyor ama ho-hum :) Masada sadece bir kısıtlama olabilir ve ardından sadece masaya güncelleme (ekleme veya silme işlemi yapmaz) izin verebilir misiniz?

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

Yine de bunu yapmak için bir hokey yolu, sadece tüm bu mantığı sizin için halledebilecek saklı bir prosedürle sadece yapılandırma değişikliklerini uygulamak daha iyi olmaz mıydı?


2
Sadece kimsenin masadan silmediğinden emin olun. Birisi siler ve yeniden eklemeye çalışırsa, izin vermeyeceği 2 kimliğini eklemeye çalışır.
Mat

5
Bu IDdeğere 0veya negatif değere sahip olmayı yasaklamaz . @Mat işaret ettiği gibi, birincisi silinirse başka bir satır eklemeye çalışırsanız başarısız olur.
ypercubeᵀᴹ

2
“Tuhaf bir gereklilik” olduğu için, görünüşte daha yaygın olan EAV tasarımı yerine, yapılandırma ayarları için tek satırlık bir tablo kullanmayı tercih ediyorum . Önceki varlıkların avantajı, sütunların uygun bir veri türü ile oluşturulabilmesi ve uygun kısıtların eklenmesi (daha kolay).
Kenny Evitt,

2
Belki de önceki yorumumda çok net değildim. "Bu, ID'nin 0 veya negatif bir değere sahip olmasını yasaklamaz" yan etkisi , tablonun 2 veya daha fazla satırla bitebilmesidir. Kimlik özelliği, benzersiz bir kısıtlama anlamına gelmez.
ypercubeᵀᴹ

3
@ Ypercubeᵀᴹ ne söylediğini göstermek için, bu çözüm ile örneğin INSERT INTO dbo.Config DEFAULT VALUES;sadece bir kez yapabilirsiniz, ancak bunu SET IDENTITY_INSERT dbo.Config ON; INSERT INTO dbo.Config (ID) VALUES (0); SET IDENTITY_INSERT dbo.Config OFF; birçok kez izleyebilir ve çok satırlı bir tablo ile sonuçlanırsınız.
Andriy M,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.