web-dev-qa-db-ja.com

SQL Server:テーブルに単一行を含めるように制約する方法は?

アプリケーションの構成テーブルに単一の行を格納したい。このテーブルには1行のみを含めることができるようにしたいと思います。

単一行の制約を強制する最も簡単な方法は何ですか?

70
Martin

列の1つに1つの値のみを含めることができることを確認してから、その主キーを作成します(または一意性制約を適用します)。

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

主に設定を保存するために、さまざまなデータベースにこれらのテーブルが多数あります。構成アイテムがintである場合、DBからintのみを読み取ることを知っている方がずっといいです。

87

私は通常、ダミアンのアプローチを使用しますが、これは常に私にとってはうまくいきましたが、1つ追加します:

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列を扱う必要がなくなり、テーブルを初めてロードするときにどちらがロック値であったかを覚える必要がなくなります。

47
ACB

この戦略を再考することができます。同様の状況で、履歴情報のために古い構成行を残しておくことは非常に貴重であることがよくあります。

これを行うには、実際に余分な列creation_date_time(挿入または更新の日付/時刻)と、現在の日付/時刻を正しく挿入する挿入または挿入/更新トリガーがあります。

次に、現在の構成を取得するには、次のようなものを使用します。

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

(DBMSフレーバーによる)。

こうすることで、リカバリの目的で履歴を維持することができ(テーブルが大きくなりすぎてもクリーンアップ手順を設定できますが、これはほとんどありません)、最新の構成で作業することができます。

14
paxdiablo

INSTEAD OF Trigger を実装して、データベース内でこのタイプのビジネスロジックを適用できます。

トリガーには、テーブルにレコードが既に存在するかどうかを確認するロジックを含めることができます。存在する場合は、挿入をロールバックします。

さて、大きな画像を見るために一歩下がって、おそらくあなたがこの情報を、例えば設定ファイルや環境変数に保存するための代替的でより適切な方法があるのだろうか?

5
John Sansom

これは、YまたはN(たとえば、アプリケーションロック状態)を保持する1行のみを含むことができるロックタイプのテーブルに対して考え出したソリューションです。

1列のテーブルを作成します。 YまたはNのみを挿入できるように、1つの列にチェック制約を設定します。 (または1または0、または何でも)

「通常の」状態でテーブルに1行挿入します(たとえば、Nはロックされていないことを意味します)

次に、SIGNAL(DB2)またはRAISERROR(SQL Server)またはRAISE_APPLICATION_ERROR(Oracle)のみを持つテーブルに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';

私のために働く。

2
David A Beamer

IsActiveという名前の主キーにビットフィールドを使用します。したがって、最大で2つの行があり、有効な行を取得するsqlは次のとおりです。

2
user3382925

テーブルの挿入アクションでトリガーを作成できます。誰かがテーブルに新しい行を挿入しようとするたびに、挿入トリガーコードの最新の行を削除するロジックを起動します。

1
Karan

古い質問ですが、小さな列タイプのIDENTITY(MAX、1)を使用するのはどうですか?

CREATE TABLE [dbo].[Config](
[ID] [tinyint] IDENTITY(255,1) NOT NULL,
[Config1] [nvarchar](max) NOT NULL,
[Config2] [nvarchar](max) NOT NULL
1
NeutronCode
IF NOT EXISTS ( select * from table )
BEGIN
    ///Your insert statement
END
0
Sachin Shanbhag

ここでは、データベースの最初のエントリの後に同じになる非表示値を作成することもできます。例:Student Table:Id:int firstname:charここのエントリボックスでは、制限するid列に同じ値を指定する必要があります主キー制約のためにロックbla blaを書き込むこと以外の最初のエントリの後、永久に1つの行のみを持つように。お役に立てれば!

0
Yishagerew