アプリケーションの構成テーブルに単一の行を格納したいと思います。このテーブルに含めることができる行は1つだけにするように強制したいと思います。
単一行の制約を適用する最も簡単な方法は何ですか?
アプリケーションの構成テーブルに単一の行を格納したいと思います。このテーブルに含めることができる行は1つだけにするように強制したいと思います。
単一行の制約を適用する最も簡単な方法は何ですか?
Name
?に存在しない値を指定したため
ar
sのコメントへの応答であったことに注意してください。問題は、名前と値のペアを格納するだけの場合、値は文字列である必要があり、データベースで検証を強制する手段がないことです。(OPが必要とするように)設定ごとに個別の列を持つ単一行テーブルを使用する場合、チェック制約を介して各構成設定の検証を簡単に実施できます。
回答:
列の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を読み取るだけになることを知っていると、はるかに便利です。
comp.databases.theory
、usenetグループ(Googleグループで表示)の省略形で、最近はあまり読んでいないことを認めています。SQLよりもリレーショナル理論に重点を置いていましたが、dportas / sqlvogelも同じグループに頻繁にアクセスしていることを偶然知っていました。TTMは、SQLではなく関係理論について(再び)話している優れた本であるThe ThirdManifestoへの参照でした。
私は通常、ダミアンのアプローチを使用します。これは常に私にとってうまく機能していますが、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列を処理する必要がなくなり、テーブルを初めてロードするときにどちらがロック値であったかを覚えておく必要がなくなります。
Lock char(1) not null CONSTRAINT DF_T1_Lock DEFAULT 'X'
この戦略を再考することをお勧めします。同様の状況で、履歴情報のために古い構成行をそのままにしておくことは非常に貴重であることがよくあります。
これを行うには、実際には追加の列creation_date_time
(挿入または更新の日付/時刻)と、現在の日付/時刻を正しく入力する挿入または挿入/更新トリガーがあります。
次に、現在の構成を取得するには、次のようなものを使用します。
select * from config_table order by creation_date_time desc fetch first row only
(DBMSフレーバーによって異なります)。
そうすれば、リカバリの目的で履歴を維持することができ(テーブルが大きくなりすぎた場合はクリーンアップ手順を開始できますが、これは起こりそうにありません)、最新の構成で作業することができます。
SELECT TOP 1 ... ORDER BY creation_date_time DESC
INSTEAD OF Triggerを実装して、データベース内でこのタイプのビジネスロジックを適用できます。
トリガーには、レコードがテーブルにすでに存在するかどうかを確認するロジックを含めることができます。存在する場合は、挿入をロールバックします。
さて、全体像を見てみると、おそらく構成ファイルや環境変数など、この情報を保存するための代替のより適切な方法があるのではないかと思います。
IsActiveという名前の主キーにビットフィールドを使用します。したがって、最大2つの行があり、有効な行を取得するためのSQLは次のとおりです。テーブルの名前がSettingsの場合、IsActive = 1であるSettingsから*を選択します。
これは、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';
私のために働きます。
古い質問ですが、小さな列タイプのIDENTITY(MAX、1)を使用するのはどうですか?
CREATE TABLE [dbo].[Config](
[ID] [tinyint] IDENTITY(255,1) NOT NULL,
[Config1] [nvarchar](max) NOT NULL,
[Config2] [nvarchar](max) NOT NULL
IF NOT EXISTS ( select * from table )
BEGIN
///Your insert statement
END
(Name, Value)
Nameに主キーを持つ列を持つテーブルを使用してみませんか。そうすればselect Value from Table where Name = ?
、行が返されないか、1行が返されることを確実に確認できます。