テーブルの最大行数を1に制限する方法


22

SQL Serverデータベースに構成テーブルがあり、このテーブルには1行しかありません。将来の開発者がこれを理解できるように、複数行のデータが追加されないようにしたいと思います。以下のように、このためにトリガーを使用することを選択しました...

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

これはエラーをスローしませんが、最初の行に入ることを許可していません。

また、テーブルに挿入できる行の数をこれよりも1つだけに制限する、より効果的で自己説明的な方法はありますか?組み込みのSQL Server機能がありませんか?


2
元のアプローチが機能しなかった理由の説明と同様に、Insert Ofトリガーを使用します。つまり、insertステートメントの代わりにコードが実行されます。したがって、挿入を実行するには、トリガーの一部として明示的に挿入する必要があります。
スコットM

回答:


52

これらの2つの制約は次のことを行います。

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

2つの行が同じ値を持たないように両方PRIMARY KEY(またはUNIQUE制約)が必要IDであり、CHECKすべての行が同じID値(任意に選択された1)を持つように制約が必要です。
組み合わせて、2つのほぼ反対の制約により、行の数が0または1に制限されます。


0列で構成される主キーを許可する架空のDBMS(現在のSQL実装ではこの構築が許可されていない)では、これも解決策になります。

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

24

定数値に評価される計算列としてIDを定義し、その列が一意であることを宣言できます。

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

9

トリガーを使用することもできます。

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

    if @tableCount > 50
    begin
        rollback
    end
go

1

少し奇妙な要件のように思えますが、ややこしいです:)テーブルに制約を設定して、テーブルの更新のみ(挿入または削除なし)を許可できますか?

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

しかし、それを行うにはちょっとした方法がありますが、このロジックをすべて処理できるストアドプロシージャを介して構成の変更を強制する方が良いでしょうか?


2
誰もテーブルから削除できないことを確認してください。誰かが削除してから再挿入しようとすると、許可されないID 2で挿入しようとします。
マット

5
これはID、の値0または負の値を持つことを禁止しません。また、@ Matが示すように、最初の行が削除された場合に別の行を挿入しようとすると失敗します。
ypercubeᵀᴹ

2
「奇妙な要件」であることに関しては、一見一般的なEAV設計ではなく、構成設定に単一行のテーブルを使用することを好みます。前者の利点は、適切なデータ型で列を作成でき、適切な制約を追加できることです(より簡単に)。
ケニーエビット

2
おそらく、以前のコメントではあまりはっきりしていなかったでしょう。「これにより、IDの値が0または負の値になることを禁止しません」という副作用は、テーブルが2行以上で終わる可能性があることです。identityプロパティは、一意の制約を意味するものではありません。
ypercubeᵀᴹ

3
@ypercubeᵀᴹが言ったことを説明するために、このソリューションを使用すると、たとえばINSERT INTO dbo.Config DEFAULT VALUES;1回だけ実行できますが、SET IDENTITY_INSERT dbo.Config ON; INSERT INTO dbo.Config (ID) VALUES (0); SET IDENTITY_INSERT dbo.Config OFF; 何度もフォローでき、最終的に複数行のテーブルになります。
アンドリーM
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.