【发布时间】:2018-04-04 04:05:45
【问题描述】:
场景:对不同的表使用“Instead of Insert”触发器(覆盖当前表的插入)会引发截断错误。
- 尝试将数据插入 TableA 中
- Instead Of Trigger 设置为在 TableA 上运行
- 此触发器改为插入到 TableB 中
- TableA 未写入
问题:
TableA 有一个nvarchar(10) desc 列,TableB 有一个nvarchar(200) desc 列。在 TableA 上设置了插入触发器,其中 desc 列的数据长度为 50 个字符。
使用
SET ANSI_WARNINGS ON (默认值),TableA 会导致截断错误。对于
SET ANSI_WARNINGS OFF(危险),TableB 上的截断被忽略。因此,如果 desc 以 400 个字符输入,它将被截断为 200 个字符而没有错误。
设置
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[results]
(
[id] [int] IDENTITY(1,1) NOT NULL,
[causefailure] [nvarchar](5) NULL,
[type] [nvarchar](50) NOT NULL,
[description] [nvarchar](200) NULL,
[rundate] [datetime] NOT NULL DEFAULT (getdate())
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[test_table]
(
[id] [int] IDENTITY(1,1) NOT NULL,
[description] [nvarchar](10) NULL,
[rundate] [datetime] NOT NULL DEFAULT (getdate())
) ON [PRIMARY]
GO
CREATE TRIGGER [dbo].[InsteadTrigger]
ON [dbo].[test_table]
INSTEAD OF INSERT
AS
SET NOCOUNT ON
SET ANSI_WARNINGS ON
BEGIN
INSERT INTO results([type], [description])
SELECT
(CASE SUBSTRING([description], 1, 1)
WHEN 'a'
THEN 'causes failure or truncation'
ELSE ''
END AS [causefailure],
'Instead Of Trigger' AS [type],
[description]
FROM inserted
END;
GO
ALTER TABLE [dbo].[test_table] ENABLE TRIGGER [InsteadTrigger]
GO
第一次尝试:
SET ANSI_WARNINGS OFF
INSERT INTO [dbo].[test_table]([description])
SELECT 'atest12345678910' AS [description]
第二次尝试:
SET ANSI_WARNINGS ON
INSERT INTO [dbo].[test_table]([description])
SELECT 'btest12345678910' AS [description]
INSERT INTO [dbo].[test_table]([description])
SELECT 'atest12345678910' AS [description]
但是当我运行第一个代码 sn-p 时,causefailure 被截断。但是没有错误。运行第二个 sn-p 在 [results] 中插入一条记录。但它会在第二次引发异常。
有没有办法忽略:约束、转换问题等,初始写入 [test_table] 的异常?但是在触发器中完成的任何工作是否有例外(例如插入 [results] 甚至可能是 [test_tables] 的实际工作)?
编辑:我不想更改
nvarchar(10) desc的列大小 在表 A 上。最终目标可能是“代替触发器” 无法在 TableA 上插入,它保存到 TableB。或者它甚至可能改变desc的大小在触发器内部动态失败并重试 插入。
希望对您有所帮助!
【问题讨论】:
-
我也很感兴趣,是否有可以用 CLR C# 编写的“代替插入”触发器之类的东西。但我需要先解决上述问题。
-
目标是在插入失败时更改 test_table 的模式并再次尝试插入。就像在尝试/捕获中一样。我会在问题中包含这个。
-
使用存储过程来处理这个问题,而不是使用不透明的触发器来重定向您的 INSERT。触发器中的错误无论如何都会使批处理失败,除非您使用 TRY/CATCH
-
trigger 对截断没有任何作用。当触发器触发时,截断已经发生。
-
然后让 EF 正确设计表格。您要求的解决方案很糟糕。
标签: sql sql-server triggers