- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
计划:使用INSTEAD OF INSERT
触发器将失败的插入重定向到“待定”表。这些行保留在“待定”表中,直到在另一个表中插入一些附加信息;当此新信息可用时,待定行将移至其原始目的地。
背景:交易记录与控股有关。更新交易的服务可以包含尚未在数据库中的信息,例如尚未插入的控股交易(请不要关注系统那部分的“为什么”,我可以'不要改变它)。
问题:INSTEAD OF INSERT
触发器正常工作,但我在使用INSTEAD OF UPDATE
触发器时遇到问题。当应用 UPDATE
但要更新的行位于“待定”表中时,触发器中的 INSERTED
表为空,因此我无法更新“待定”表.这是(简化的)DDL:
CREATE TABLE [Holding] (
[HoldingID] INTEGER NOT NULL,
[InstrumentID] INTEGER,
CONSTRAINT [PK_Holding] PRIMARY KEY ([HoldingID])
)
GO
CREATE TABLE [Trade] (
[TradeID] INTEGER IDENTITY(1,1) NOT NULL,
[HoldingID] INTEGER NOT NULL,
[BuySell] CHAR(1) NOT NULL,
CONSTRAINT [PK_TradeSummary] PRIMARY KEY ([TradeID])
)
GO
ALTER TABLE [Trade] ADD CONSTRAINT [CC_Trade_BuySell]
CHECK (BuySell = 'B' or BuySell = 'S')
GO
ALTER TABLE [Trade] ADD CONSTRAINT [Holding_Trade]
FOREIGN KEY ([HoldingID]) REFERENCES [Holding] ([HoldingID])
GO
CREATE TABLE [TradePending] (
[TradeID] INTEGER IDENTITY(1,1) NOT NULL,
[HoldingID] INTEGER NOT NULL,
[BuySell] CHAR(1) NOT NULL,
CONSTRAINT [PK_TradePending] PRIMARY KEY ([TradeID])
)
GO
ALTER TABLE [TradePending] ADD CONSTRAINT [CC_TradePending_BuySell]
CHECK (BuySell = 'B' or BuySell = 'S')
GO
-- The INSERT trigger works, when the referenced holding does not exist the row is redirected to the TradePending table.
CREATE TRIGGER [Trg_Trade_Insert]
ON [Trade]
INSTEAD OF INSERT
AS
IF NOT EXISTS (SELECT 1
FROM inserted i INNER JOIN Holding h
ON i.HoldingID = h.HoldingID)
BEGIN
INSERT TradePending(HoldingID, BuySell) SELECT HoldingID, BuySell FROM inserted
END
ELSE
BEGIN
INSERT Trade(HoldingID, BuySell) SELECT HoldingID, BuySell FROM inserted
END
GO
执行 UPDATE
的触发器在 Trade
表中存在行时起作用,但在行不存在时不起作用,INSERTED
虚拟表是空的。我已将一些 PRINT
语句添加到触发器以尝试查看发生了什么。
CREATE TRIGGER [dbo].[Trg_Trade_Update]
ON [dbo].[Trade]
INSTEAD OF UPDATE
AS
DECLARE @s char(1)
DECLARE @h int
IF NOT EXISTS (SELECT 1
FROM inserted i INNER JOIN Trade t
ON i.HoldingID = t.HoldingID)
BEGIN
PRINT 'Update TradePending'
SET @h = COALESCE((SELECT i.HoldingID
FROM TradeSummaryPending t INNER JOIN inserted i
ON t.HoldingID = i.HoldingID), 0)
SET @a = COALESCE((SELECT i.BuySell
FROM TradeSummaryPending t INNER JOIN inserted i
ON t.HoldingID = i.HoldingID), 'N')
PRINT 'h=' + CAST(@h AS varchar(1)) + ' s=' + @s
UPDATE TradePending
SET BuySell = i.BuySell
FROM Trade t INNER JOIN inserted i
ON t.HoldingID = i.HoldingID
END
ELSE
BEGIN
PRINT 'Update Trade'
SET @h = (SELECT i.HoldingID
FROM Trade t INNER JOIN inserted i
ON t.HoldingID = i.HoldingID)
SET @s = (SELECT i.BuySell
FROM Trade t INNER JOIN inserted i
ON t.HoldingID = i.HoldingID)
PRINT 'h=' + CAST(@h AS varchar(1)) + ' s=' + @s
UPDATE Trade
SET BuySell = i.BuySell
FROM Trade t INNER JOIN inserted i
ON t.HoldingID = i.HoldingID
END
下面是一些用于测试的示例数据:
-- Create a Holding and a Trade, this will be inserted as normal.
INSERT Holding VALUES(1,100)
INSERT TradeSummary VALUES(1,'B')
-- Create a Trade where the Holding does not exists,
-- row redirected to TradePending table.
INSERT TradeSummary values(2,'S')
-- Update the first trade to be a Buy, updates the `Trade` table
UPDATE Trade SET BuySell = 'S' WHERE HoldingID = 1
执行更新的输出:
Update Trade
h=1 s=S
(1 row(s) affected)
(1 row(s) affected)
现在更新仅存在于 TradePending 表中的行:
UPDATE Trade SET BuySell = 'B' WHERE HoldingID = 2
结果如下:
Update TradePending
h=0 s=N
(0 row(s) affected)
(0 row(s) affected)
INSERTED
表似乎包含现在的行,即使这是一个 INSTEAD OF
触发器并且应该在 SQL 应用于表之前执行。
谁能解释为什么 INSERTED
表是空的?我确信解决方案会很简单,但我似乎无法让它发挥作用。
最佳答案
当然,当您更新表中不存在的行时,这些行不存在于 INSERTED 伪表中以开始:您在 Trade< 上发出 UPDATE 语句
用于 TradePending
中的行!
此外,您的 INSTEAD OF INSERT 触发器已损坏。它只适用于单行插入,即使对于那些在并发下也会失败的插入。使用基于集合的 MERGE。
最终,您将围绕与应用程序的功能脱节的数据模型设计黑客攻击。创建 INSTEAD OF 触发器以完全更改遗留代码使用的表的形状仅到目前为止有效,您遇到的这个问题只是 future 的众多问题之一。最终,您的客户端代码必须插入/更新/删除正确的表。
作为解决方法,您可以尝试将所有数据移动到一个表中,该表包含两者 Trade 和 TradePending 并使用状态列来区分这两者,将旧的 Trade 和 TradePending 表公开为 View 并使用触发器捕获 View 上的 DML,以将它们重定向到正确的表。虽然不确定是否可行,但我现在无法对其进行测试。
更新:
这是一个如何使用可更新 View 的示例:
CREATE TABLE [Holding] (
[HoldingID] INTEGER NOT NULL,
[InstrumentID] INTEGER,
CONSTRAINT [PK_Holding] PRIMARY KEY ([HoldingID])
)
GO
CREATE TABLE [TradeStorage] (
[TradeID] INTEGER IDENTITY(1,1) NOT NULL,
[HoldingID] INTEGER NOT NULL,
[BuySell] CHAR(1) NOT NULL,
CONSTRAINT [PK_TradeSummary] PRIMARY KEY ([TradeID])
, CONSTRAINT [CC_Trade_BuySell] CHECK (BuySell IN ('B','S'))
)
GO
create view Trade
with schemabinding
as
select TradeID, HoldingID, BuySell
from dbo.TradeStorage
where exists (
select HoldingID from dbo.Holding
where Holding.HoldingID = TradeStorage.HoldingID);
go
create view TradePending
with schemabinding
as
select TradeID, HoldingID, BuySell
from dbo.TradeStorage
where not exists (
select HoldingID from dbo.Holding
where HoldingID = TradeStorage.HoldingID);
go
-- Create a Holding and a Trade, this will be inserted as normal.
INSERT Holding VALUES(1,100)
INSERT Trade VALUES(1,'B')
-- Create a Trade where the Holding does not exists,
-- row redirected to TradePending table.
INSERT Trade values(2,'B')
go
select * from Trade;
select * from TradePending;
go
-- Update the first trade to be a Buy, updates the `Trade` table
UPDATE Trade SET BuySell = 'S' WHERE HoldingID = 1
go
-- Insert a holding with ID 2,
-- this will automatically move the pending trade to Trade
INSERT Holding VALUES(2,100)
select * from Trade;
select * from TradePending;
go
UPDATE Trade SET BuySell = 'S' WHERE HoldingID = 2
go
select * from Trade;
select * from TradePending;
go
请注意,仍然无法为 TradePending 中的记录更新 Trade。没有触发器、 View 或类似机制可以做到这一点。
关于sql - 为什么 INSTEAD OF UPDATE 触发器的 INSERTED 表是空的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4334647/
我正在开发一些用于计费的数据库项目(PHP/MySQL)。 每当创建新账单时,我想生成一个由年、周和增量编号组成的账单编号。我想用触发器来做到这一点。触发器将使用现有的账单编号来查找增量编号,或者从新
我有一个 MySQL 插入,我正在使用 RAND 生成随机 INT 值问题是它不会插入到数据库中,因为该列接受 TINYINT ,如何将输出转换为 TINYINT。代码示例如下: INSERT INT
如果我想从单个插入中保存主键 (mytable_id),我已完成以下操作: CREATE OR REPLACE FUNCTION myfunct(ownerid text) RETURNS void
为了简单起见,假设我有两个表 用户表(id,email) 用户日志表(id, date) 无论 id 被插入到 user 表中,相同的 id 也应该被插入到 user_log 表中,否则事务应该失败。
为了简单起见,假设我有两个表 用户表(id,email) 用户日志表(id, date) 无论 id 被插入到 user 表中,相同的 id 也应该被插入到 user_log 表中,否则事务应该失败。
我知道在触发器中 - 至少对于 SQL Server - 人们永远不应该假设插入的表只有一行,这意味着触发器中这样的 SQL 通常是不好的: select @UserID = ID from inse
我正在使用 bigquery 对象中的方法 tabledata().insertAll 更新行列表。执行后,返回显示没有错误。但是,我的表仍然继续,没有写入任何数据。 可能是权限问题。如果是这样,为什
这是一个扩展 F# Recursive Tree Validation 的问题,我昨天已经很好地回答了。 这个问题涉及在现有树中插入一个 child 。这是我想使用的更新类型: type Name
我有 2 个表:用户和照片(在 mysql 数据库中)。 在这里你可以看到两个表之间的关系 User Photos -------------
我试图同时在不同的表上插入两行。 子查询INSERT INTO的AUTO_INCRMENT或id的值(如果已经存在)应该写入主查询中。 目前我有这个(仅用 3 个值简化),但它不起作用。我想知道是否有
我有一个 900 万行的表,由于其庞大的规模,我正在努力处理所有这些数据。 我想做的是在不覆盖数据的情况下将 IMPORT 一个 CSV 添加到表中。 在我做这样的事情之前; INSERT if no
我正在写新闻并将其插入到我的数据库中,我在 3 年前构建了代码并且运行良好,但我不能再插入了,我不明白为什么: $insert=mysqli_query($co,"INSERT INTO articl
我正在尝试编写一个简单的 INSERT 语句来将新用户添加到数据库中,但它不起作用,这意味着,我尝试插入到表中的数据都没有被插入。几个小时以来,我一直在尝试解决此问题,但没有成功。我尝试编写插入语句的
所以我有这个表格: http://i.imgur.com/vZYssQy.png 现在 ID、First Name、Last Name、DOB、Address、Phone Number 和 Post
在控制台中运行查询(SELECT 语句)时,从数据库检索到的数据以表格格式显示在数据库控制台工具窗口的结果 Pane 中。 我已经搜索过 datagrip Help我只是想知道是否有任何方法可以用于为
每当使用触发器插入行时,我都试图将另一行插入表中,但收到以下错误消息: The target table 'EDDSDBO.Redaction' of the DML statement cannot
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 6 年前。 Improve
我有以下代码片段: $get_data = mysqli_query ($connect, "SELECT * FROM users WHERE username = '$username'");
情况:需要向 SQLite 数据库中插入大量数据。 问题:我们可以使用两个语句来插入数据 - data = [("111", "222", "333"), ("AAA", "BBB", "CCC"),
我的数据库中有一个表 Teacher: TABLE Teacher ( ID CHAR (7) NOT NULL , name
我是一名优秀的程序员,十分优秀!