【发布时间】:2010-11-02 20:52:35
【问题描述】:
我正在运行带有 .NET 2.0 的 MS SQL Server 2005。我当前的应用程序是用 C# 编写的。
在 MSSQL 中,我创建了 2 个测试表来说明我的问题:
表1设置为:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[T1](
[n] [bigint] NOT NULL,
[t] [varchar](10) NOT NULL,
CONSTRAINT [PK_T1] PRIMARY KEY CLUSTERED
(
[n] 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_PADDING OFF
表2设置为:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[T2](
[n] [bigint] NULL,
[Test] [varchar](4) NOT NULL,
[Num] [bigint] NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[T2] WITH CHECK ADD CONSTRAINT [FK_T2_T1] FOREIGN KEY([n])
REFERENCES [dbo].[T1] ([n])
ON UPDATE CASCADE
GO
ALTER TABLE [dbo].[T2] CHECK CONSTRAINT [FK_T2_T1]
我已经用多行填充了每个。
简而言之,表 1 (T1) 有一个 bigint 主键字段“n”,它映射到子表 T2 的 n 字段。设置了级联更新,因此当 T1.n 被修改时,T2.n 也会被更新。如果我做一个简单的查询并在其中一行中设置 T1.n 的值,我可以看到级联发生在执行计划中。如果我设置了 T1.t 的值,级联不会按预期出现在执行计划中。
在 ADO.NET 中,我在表单中添加了一个 DataAdapter 并让它自动生成 4 个存储过程,T1 的更新显示如下:(我添加了一些间距以帮助提高可读性)
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[T1_Update]
(
@n bigint,
@t varchar(10),
@Original_n bigint,
@Original_t varchar(10)
)
AS
SET NOCOUNT OFF;
UPDATE [T1]
SET
[n] = @n,
[t] = @t
WHERE (
([n] = @Original_n) AND
([t] = @Original_t));
SELECT n, t FROM T1 WHERE (n = @n)
我可以执行这个存储过程:
DECLARE @RC int
DECLARE @n bigint
DECLARE @t varchar(10)
DECLARE @Original_n bigint
DECLARE @Original_t varchar(10)
EXECUTE @RC = [T1_Update]
5, '5', 5, '4' -- n, t, Original_n, Original_t
在这种情况下,n 的值不变,t 的值发生变化。我希望看到与我刚刚执行“UPDATE T1 SET t='4' where n=5 and t='5'”时相同的行为/执行计划。运行此查询,执行计划非常简单,其中包括 CI 搜索、计算标量、CI 更新、更新。
但是,运行上面的执行,执行计划显示它扫描表 T2 并在所述表上执行更新,即使值没有更改。
我认为这是由于以下几行:
UPDATE [T1]
SET
[n] = @n,
从 T1_Update 存储过程中注释掉 [n] = @n,即使值没有改变,也会停止触发级联更新。
所以假设我想保留级联更新,有没有办法重写/修改自动生成的 T1_Update 存储过程,以便级联更新仅在“n”的值更改时激活,而不是在值时激活没变?
编辑:我删除了 T1 上的一个外键关系,该关系引用了我在设置此测试时意外添加的自身。
【问题讨论】:
标签: sql sql-server ado.net