怎样对一个通过left join拼起来的表进行更新的操作?

licheng31 2003-05-14 08:50:24
我的表是这样得到的:select t1.TraceNO, t1.userno, t1.gasfee, t2.gas, t2.LateDate from
((select TraceNO, UserNo, GasFee, PayID from Tcopy) t1
left join
(select gas, LateDate, PayID from Tpay) t2 on t1.PayID = t2.PayID
并且方在一个recordset里面.我现在想对其中的TraceNO字段进行更新操作.
但是发现会报错,说"缺少更新或刷新的键列信息".那位大虾知道如何解决这样的问题?
我实际的表比上面写的更加复杂,我只是把其中一个内容抽象出来.主要是想问问,有没有人知道解决办法?
...全文
127 点赞 收藏 11
写回复
11 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
pengdali 2003-05-14
inserted 是系统临时表用来放新的值 如:insert,update 里的被插入的值

deleted 也是系统临时表用来放旧的值 如:delete,update 里的被删除值
回复
pengdali 2003-05-14
举例:(你到查询分析器里执行一下,看看结果!就全明白了)

create table 表 (a int)
go
insert 表 values (1)
go

CREATE TRIGGER 名 ON 表
FOR UPDATE
AS
select a 更新前被删除的数据 from deleted
select a 更新后被插入的数据 from inserted
go

------------测试:
update 表 set a=3
回复
licheng31 2003-05-14
非常感谢 pengdali(大力) 的细心指导.我还是有一点不明白.触发器本身是没有参数传入的,那么我在使用 INSTEAD OF Insert触发器的时候,用什么值去插入新表呢?
以你给出的最后一段代码为例:
INSERT INTO BaseTable
SELECT PrimaryKey, ColumnB,
-- Perform logical inverse of function in view.
SQRT(SquareC)
FROM inserted
是不是以为着我每次更新的时候都必须更新3个字段:PrimaryKey, ColumnB,ColumnC.如果我只想更新其中两个字段,PrimaryKey,ColumC,怎么办?
insert into SquareView(Primarykey, ColumC) values (11,12)
这样写可以吗
回复
pengdali 2003-05-14
INSTEAD OF 触发器中的表达式和计算列
视图的选择列表可以包含除简单表达式(仅由一个列名构成)以外的其它表达式。这些视图上的 INSTEAD OF 触发器必须具有相应的逻辑,能够正确地确定 INSERT 和 UPDATE 触发器上指定的值中哪些值必须设置到基表中的列。此类表达式的示例包括:

不映射到任何表中任何列的视图表达式,如常数或某些类型的函数。


映射到多列的视图表达式,如由两个或更多列的串联字符串组成的复杂表达式。


转换单个基表列的值的视图表达式,如引用函数中的列。
这些情况还适合作为简单表达式的视图列,这些视图列引用基表中的计算列。定义计算列的表达式可与视图选择列表中的更复杂表达式具有相同的形式。

视图可在其不映射到任何基表列的选择列表中包含表达式,例如:

CREATE VIEW ExpressionView
AS
SELECT *, GETDATE() AS TodaysDate
FROM Northwind.dbo.Employees

虽然 TodaysDate 列并不映射到任何表列,但是 Microsoft® SQL Server™ 2000 必须在将其传递到在 ExpressionView 上定义的 INSTEAD OF 触发器的 inserted 表中生成 TodaysDate 列。然而 inserted.TodaysDate 列可为空,所以引用 ExpressionView 的 INSERT 不必为该列提供值。因为表达式不映射到表中的列,所以触发器会忽略 INSERT 在该列中提供的任何值。

相同的方法应该应用于简单视图表达式,这些表达式引用基表中的计算列,而基表也生成不依赖于其它列的结果,例如:

CREATE TABLE ComputedExample
(
PrimaryKey int PRIMARY KEY,
ComputedCol AS SUSER_NAME()
)

一些复杂表达式映射到多列:

CREATE TABLE SampleTable
(
PriKey int,
FirstName nvarchar(20),
LastName nvarchar(30)
)
GO
CREATE VIEW ConcatView
AS
SELECT PriKey, FirstName + ' ' + LastName AS CombinedName
FROM SampleTable

ConcatView 中的表达式 CombinedName 包含由 FirstName 和 LastName 值串联起来的值。如果在 ConcatView 上定义 INSTEAD OF INSERT 触发器,则对 INSERT 语句如何提供 CombinedName 列值必须有相应的规则,让触发器确定字符串的哪部分应放在 FirstName 列中,哪部分应放在 LastName 列中。如果选择的规则是让 INSERT 语句使用 'first_name;last_name' 规则指定 CombinedName 的值,则该触发器可成功地处理 INSERT:

CREATE TRIGGER InsteadSample on ConcatView
INSTEAD OF INSERT
AS
BEGIN

INSERT INTO SampleTable
SELECT PriKey,
-- Pull out the first name string.
SUBSTRING(
CombinedName,
1,
(CHARINDEX(';', CombinedName) - 1)
),
-- Pull out the last name string.
SUBSTRING(
CombinedName,
(CHARINDEX(';', CombinedName) + 1),
DATALENGTH(CombinedName)
)
FROM inserted
END

需要类似的逻辑来处理本身是简单表达式,但引用的计算列中包含复杂表达式的视图列。

一些视图表达式可转换基表列的值,例如通过执行数学运算或使用列作为函数的参数。在这种情况下,INSTEAD OF INSERT 触发器中的逻辑可采用两种方法:

规则可以是:所有 INSERT 语句提供要放在基表中的原始值,而触发器逻辑将该值从 inserted 表移到基表。


规则可以是:所有 INSERT 语句提供预期得到的由视图上的 SELECT 返回的值,在这种情况下触发器中的逻辑必须反转此操作。例如:
CREATE TABLE BaseTable
(
PrimaryKey int PRIMARY KEY,
ColumnB int,
ColumnC decimal(19,3)
)

CREATE VIEW SquareView AS
SELECT PrimaryKey, ColumnB,
-- Square the value of ColumnC
SQUARE(ColumnC) AS SquareC
FROM BaseTable

CREATE TRIGGER SquareTrigger ON SquareView
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO BaseTable
SELECT PrimaryKey, ColumnB,
-- Perform logical inverse of function in view.
SQRT(SquareC)
FROM inserted
END

对于某些表达式(如使用加法和减法等数学运算的复杂表达式),用户也许不可能提供特定的值供触发器明确地生成目的基表列的值。例如,如果视图选择列表包含表达式 IntColA + IntColB AS AddedColumns,那么 inserted.AddedColumns 中的值 10 表示什么?10 是3 + 7、2 + 8 还是 5 + 5 的结果?仅从 inserted.AddedColumns 值没有办法得知什么值应放置在 IntColA 和 IntColB 中。

在这些情况下,可对触发器进行编码以使用备用信息源确定基表列中要设置的值。对于具有 INSTEAD OF 触发器的视图,视图选择列表必须包含足够的信息,以生成由触发器修改的基表中所有非空列的值。并不是所有的数据都必须直接来自 inserted 表。在一些情况下,inserted 表中的值可以是触发器用于检索其它基表中相关数据的键值。

回复
licheng31 2003-05-14
如果把上面的结果集方在一个视图里面,能通过recordset进行更新操作吗?
回复
pengdali 2003-05-14
晕~~连手工都构造不出来程序怎么能够造得出来如:

select a,b,a+b c from 表

你去更新c列 ,那你说你更新的值是给a还是给b ?
人都不能理解你的意思,你的程序能吗?
你的join一样的道理,不是能不能做,是你要写程序告诉它怎么做!
回复
licheng31 2003-05-14
主要是我需要更新的值,是通过前台生成的.不是在数据库里面值的运算结果,所以单纯的insert或者update不行,有没有更好的办法?
回复
pengdali 2003-05-14
1、没有办法,不管是在delphi,bcb,vb,c#里的都是这样,应为它们都不能 将你得出的结果自动生成insert update delete语句,去更新表
就像你不能更新计算字段一样

2、你只能通过Query 或 存储过程 自己人工构造insert ..语句来更新表

3、你可以把你的查询作成视图,再对视图做 替代操作触发器,例:
CREATE TRIGGER 名 on 视图
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO 表1 SELECT name1,name2 FROM inserted
INSERT INTO 表2 SELECT name3,name4 FROM inserted
END
回复
pengdali 2003-05-14
1、没有办法,不管是在delphi,bcb,vb,c#里的都是这样,应为它们都不能 将你得出的结果自动生成insert update delete语句,去更新表
就像你不能更新计算字段一样

2、你只能通过Query 或 存储过程 自己人工构造insert ..语句来更新表

3、你可以把你的查询作成视图,再对视图做 替代操作触发器,例:
CREATE TRIGGER 名 on 视图
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO 表1 SELECT name1,name2 FROM inserted
INSERT INTO 表2 SELECT name3,name4 FROM inserted
END
回复
hooboo 2003-05-14
楼下的,如果你没有不同的见解就不要和我抢分了
回复
hooboo 2003-05-14
这是个结果集,不能用来更新的。所以断了这个念头,老老实实地用UPDATE来更新
回复
相关推荐
发帖
MS-SQL Server
创建于2007-09-28

3.3w+

社区成员

MS-SQL Server相关内容讨论专区
申请成为版主
帖子事件
创建了帖子
2003-05-14 08:50
社区公告
暂无公告