すみません訂正です。
create table 会議室予約
(
id int identity primary key,
会議室ID varchar(20),
start_time datetime,
end_time datetime
)
go
create index idx_会議室 on 会議室予約 ( 会議室ID, start_time, end_time )
go
create function chk_会議室予約() returns int
begin
declare @i int
select @i = sum(t.CNT) from (
select count(*) CNT from 会議室予約 y where exists (
select 1 from 会議室予約 y2
where y.id <> y2.id
and y.会議室ID = y2.会議室ID
and y.start_time > y2.start_time and y.start_time < y2.end_time )
union all
select count(*) from 会議室予約 y where exists (
select 1 from 会議室予約 y2
where y.id <> y2.id
and y.会議室ID = y2.会議室ID
and y.end_time < y2.start_time and y.start_time < y2.end_time )
union all
select count(*) from 会議室予約 y where exists (
select 1 from 会議室予約 y2
where y.id <> y2.id
and y.会議室ID = y2.会議室ID
and y2.start_time > y.start_time and y2.start_time < y.end_time )
union all
select count(*) from 会議室予約 y where exists (
select 1 from 会議室予約 y2
where y.id <> y2.id
and y.会議室ID = y2.会議室ID
and y2.end_time > y.start_time and y2.start_time < y.end_time ) ) t
return @i
end;
go
制約の作成は変わりません。
質問者
お礼
1)'roomA','2011/1/1','2011/1/3' 【登録可】
2)'roomA','2011/1/2','2011/1/4' 【登録不可】
3)'roomA','2011/1/5','2011/1/6' 【登録不可】
4)'roomB','2011/1/5','2011/1/6' 【登録可】
上記データをテスト登録したところ、【】内の結果になりました。
2)がはじかれた時に「やった!」と思ったものの、3)が出来ず。
試しに4)をやったらできました。
そこで条件を以下の3つでやることにしました。
・y.start_time between y2.start_time and y2.end_time
・y.end_time between y2.start_time and y2.end_time
・y.start_time < y2.start_time and y2.end_time < y.end_time
UPDATE文でも上手く機能することを確認できました。
できましたが、、、レベルが高くわからないことが多いです。。。
図々しいお願いで申し訳ありませんが、簡単な解説願えませんでしょうか。
入力されたデータがfunctionに渡されていないのは、いったんテーブルに書き込んでから消しているイメージなのでしょうか?
登録不可だったINSERTの分もIDが増えているようなので、そうかなと思うものの、いかんせんDeleteに当たる部分がないもので、???です。。
それにしてもこんな複合技があるとは、、、nora1962さん凄いです。。
ベストアンサーは No4 の Siegruneさんの回答を待ってから選出しますが、とりあえずお礼までを。
本当にありがとうございました!!
> 1件1件のデータ追加間隔は十分な時間があるとした場合、何か方法はありませんでしょうか?
そうですね。
create table 会議室予約
(
id int identity primary key,
会議室ID varachar(20),
start_time datetime,
end_time datetime
)
go
create index idx_会議室 on 会議室予約 ( 会議室ID )
go
create function chk_会議室予約() returns int
begin
declare @i int
select @i = count(*) from 会議室予約 y where exists (
select 1 from 会議室予約 y2
where y.id <> y2.id
and y.会議室ID = y2.会議室ID
and ( y.start_time between y2.start_time and y2.end_time or
y.end_time between y2.start_time and y2.end_time or
y2.start_time between y.start_time and y.end_time or
y2.end_time between y.start_time and y.end_time ) )
return @i
end;
go
alter table 会議室予約 add constraint chk_会議室予約_time check ( dbo.chk_会議室予約() = 0 )
go
かなり無槍やりですね。
お礼
1)'roomA','2011/1/1','2011/1/3' 【登録可】 2)'roomA','2011/1/2','2011/1/4' 【登録不可】 3)'roomA','2011/1/5','2011/1/6' 【登録不可】 4)'roomB','2011/1/5','2011/1/6' 【登録可】 上記データをテスト登録したところ、【】内の結果になりました。 2)がはじかれた時に「やった!」と思ったものの、3)が出来ず。 試しに4)をやったらできました。 そこで条件を以下の3つでやることにしました。 ・y.start_time between y2.start_time and y2.end_time ・y.end_time between y2.start_time and y2.end_time ・y.start_time < y2.start_time and y2.end_time < y.end_time UPDATE文でも上手く機能することを確認できました。 できましたが、、、レベルが高くわからないことが多いです。。。 図々しいお願いで申し訳ありませんが、簡単な解説願えませんでしょうか。 入力されたデータがfunctionに渡されていないのは、いったんテーブルに書き込んでから消しているイメージなのでしょうか? 登録不可だったINSERTの分もIDが増えているようなので、そうかなと思うものの、いかんせんDeleteに当たる部分がないもので、???です。。 それにしてもこんな複合技があるとは、、、nora1962さん凄いです。。 ベストアンサーは No4 の Siegruneさんの回答を待ってから選出しますが、とりあえずお礼までを。 本当にありがとうございました!!
補足
No.6 SiegruneさんのTriggerバージョンを見て気が付きました。 Triggerのやり方でも追加失敗すると連番が一つ飛びになっているのですが、これは rollback が効いていたからだったんですね。。 調べたら書いてありました。 >列または列の集合に対するCHECK制約では、その表のすべての行について、指定した条件がTRUEまたはUNKNOWNであることが必要。 DML文の結果でCHECK制約の条件がFALSEに評価される場合、その文はロールバックされる。 追加質問は取り消させていただきます。ありがとうございました!