MSSQL 2008 R2 を使用しています。更新可能なビューの便利な機能があります。たとえば、id を名前にマッピングする 1 つのテーブル t があるとします。
create table t (id int not null primary key, name varchar(100) not null unique)
次に、いくつかの ID とその他の情報を示す別のテーブル:
create table u (id int not null primary key references t, info varchar(100) not null)
便宜上、名前列で拡張された u からの行を表示できるビューを示します。
create view v as select u.*, t.name from u u join t t on u.id = t.id
次に、ID ではなく名前で更新できるようになりました。
update v set info = 'foo' where name = 'fred'
最も便利です。しかし、「fred」の行を削除したい場合はどうなりますか?
delete v where name = 'fred' -- Fails
エラーが発生します
変更は複数のベース テーブルに影響するため、ビューまたは関数 'v' は更新できません。
結合されたテーブルを使用した SQL 更新可能ビュー(Oracle を指しますが、MSSQL の場合も状況は同じように見えます)で説明されているように、キー保存テーブルが 1 つしかない限り、複数のベース テーブルに対して更新可能なビューを作成できます。大まかに言えば、これは、テーブルの行がビューに最大 1 回表示される場所です。上記のビューでは、t と u の両方がキー保存テーブルであることがわかります。しかし、ビューの定義を微調整することでごまかすことができます。
create view v as
select u.*, (select t.name from t t where t.id = u.id) as name
from u u
これにより、以前と同じ行が得られますが、更新が可能になりました。
update v set info = 'foo' where name = 'fred'
意味的には、t からのすべての行がビューに最大 1 回しか表示されないことは変わりませんが、通常の方法で t に結合していないため、更新制限に該当しません。さらに、このビューから削除することもできます:
delete from v where name = 'fred'
これは正しいことを行い、基になるテーブル u から削除しますが、t からは削除しません。明らかに、単純な結合として表された以前のビューでは、「削除」操作が行を u または t (または両方) から削除する必要があるかどうかを判断する方法はありません。
多くの「選択」クエリでは、書き換えられたビューを使用した実行計画が少し異なるため、場合によっては実行が少し遅くなることが予想されます。オプティマイザーが (この特定のケースでは、一意のインデックスが存在するため) 2 つのビューに同じデータがあることを確認できないのは残念です。
関数を使用して更新可能なビューを作成することもできます。
create function dbo.get_name(@id int) returns varchar(100) as begin
declare @r varchar(100)
select @r = name from t where id = @id
return @r
end
create view v as select *, dbo.get_name(id) as name from u
これにより、さらに異なる (多くの場合、より複雑な) クエリ プランが得られる可能性があるため、さらに遅くなる可能性があります。
したがって、更新可能なビューを作成する方法は 2 つありますが、完全に満足できるものではありません。更新操作と削除操作が機能するのは良いことですが、選択クエリでビューが 2 つのテーブルの単純な結合よりもパフォーマンスが低下しないことを確認してください。おそらく、クエリ エンジンに与えることができるヒントがいくつかあります。誰でも何か提案できますか?