私は2つのテーブルを持っています
Table A
Column A1 Column A2 and
Table B
Column B1 Column B2
列 A1 は一意ではなく、PK でもありませんが、列 B1 に、列 A1 にある値以外の値を設定できないという制約を設定したいのですが、できますか?
私は2つのテーブルを持っています
Table A
Column A1 Column A2 and
Table B
Column B1 Column B2
列 A1 は一意ではなく、PK でもありませんが、列 B1 に、列 A1 にある値以外の値を設定できないという制約を設定したいのですが、できますか?
FK を使用して行うことはできません。代わりに、チェック制約を使用して、B 値が A で使用可能かどうかを確認できます。
例:
alter table TableB add constraint CK_BValueCheck check dbo.fn_ValidateBValue(B1) = 1
create function dbo.fn_ValidateBValue(B1 int)
returns bit as
begin
declare @ValueExists bit
select @ValueExists = 0
if exists (select 1 from TableA where A1 = B1)
select @ValueExists = 1
return @ValueExists
end
テーブル B の値を制限するための動的な制約を設定することはできません。代わりに、TableB でトリガーを設定するか、TbaleB ですべての挿入または更新を制限して、列 A のみから値を選択する必要があります。
Insert into TableB
Select Col from Table where Col in(Select ColumnA from TableA)
また
Update TableB
Set ColumnB= <somevalue>
where <somevalue> in(Select columnA from TableA)
また、非常に設計上の慣行であり、常に精度を保証することはできません。
TableA
データベースにテーブルとトリガーを自由に作成でき、複数の値を許可したい場合は、次の設計を使用しA1
ます。新しいテーブルを紹介します。
create table TableA (ID int not null,A1 int not null)
go
create table UniqueAs (
A1 int not null primary key,
Cnt int not null
)
go
create trigger T_TableA_MaintainAs
on TableA
after insert, update, delete
as
set nocount on
;With UniqueCounts as (
select A1,COUNT(*) as Cnt from inserted group by A1
union all
select A1,COUNT(*) * -1 from deleted group by A1
), CombinedCounts as (
select A1,SUM(Cnt) as Cnt from UniqueCounts group by A1
)
merge into UniqueAs a
using CombinedCounts cc
on
a.A1 = cc.A1
when matched and a.Cnt = -cc.Cnt then delete
when matched then update set Cnt = a.Cnt + cc.Cnt
when not matched then insert (A1,Cnt) values (cc.A1,cc.Cnt);
そしてそれをテストしてください:
insert into TableA (ID,A1) values (1,1),(2,1),(3,2)
go
update TableA set A1 = 2 where ID = 1
go
delete from TableA where ID = 2
go
select * from UniqueAs
結果:
A1 Cnt
----------- -----------
2 2
TableB
これで、 からまでの正規の外部キーを使用できますUniqueAs
。これはすべて比較的効率的です。通常の FK メカニズムは と の間で利用できTableB
、UniqueAs
このテーブルのメンテナンスは常に PK 参照によって行われます。すべてを不必要に再スキャンする必要はありませんTableA
。トリガー疑似テーブルを使用するだけです。