2007年11月9日金曜日

SQL Serverって主キーをupdate出来るんですね。

SQL Server2005Expressで確認しました。
で、Inside SQL Server2005ストレージ編には、updateがdeleteとinsertに分解され、主キーの順でソートされるそう。
でもそれだと以下の③はうまくいかない気がする。
deleteを先にやろうとすると外部キー制約に引っ掛かるはずなのに引っかからない。なんか特別な処理をしているのかな?
USE [pubs]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tbl](
[pk1] [int] NOT NULL,
[ux1] [int] NOT NULL,
CONSTRAINT [PK_tbl] PRIMARY KEY CLUSTERED
(
[pk1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [IX_tbl] UNIQUE NONCLUSTERED
(
[ux1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tbl2](
[num] [int] NOT NULL,
[rel1] [int] NULL,
CONSTRAINT [PK_tbl2] PRIMARY KEY CLUSTERED
(
[num] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[tbl2] WITH CHECK ADD CONSTRAINT [FK_tbl2_tbl] FOREIGN KEY([rel1])
REFERENCES [dbo].[tbl] ([pk1])
GO
ALTER TABLE [dbo].[tbl2] CHECK CONSTRAINT [FK_tbl2_tbl]
GO

insert tbl(pk1,ux1) values(1,10);
insert tbl(pk1,ux1) values(2,20);
insert tbl2(num,rel1) values(100,2);

select * from tbl2
--以下は一意性エラー
update tbl set pk1=2 where pk1=1;

--以下は正常
begin tran;
update tbl set pk1=3-pk1
select * from tbl
rollback;

--以下は一意性エラー
update tbl set ux1=20 where ux1=10;

--以下はok
begin tran;
update tbl set ux1=30-ux1;
select * from tbl
rollback;

--③以下もok
begin tran;
update tbl set pk1=3-pk1, ux1=30-ux1;
select * from tbl
rollback;


それはそうと、主キーが変えられるとなると昔作ったトリガの設計が破綻することになるのか。はぁ。
昔作ったトリガは効率化のために、insertedとdeletedのテーブルを主キーで連結し前後の変化列を調べて変化に見合う処理を行っていたのだけれど、主キーが変えられると変化を追跡できない。
効率を無視して、deletedテーブルでdeleteに見合う処理を行って、insertedテーブルでinsertに見合うを行うというようにdeleteとinsertの処理を別々に処理しなければならなかったのかな。(こちらの方が条件式のバリエーションが減るし。)

0 件のコメント: