帮助SQL Server触发器在插入之前截断坏数据

时间:2011-05-23 19:56:30

标签: sql sql-server triggers

我们使用一个决定从255改变字段最大长度的Web服务。我们的末端有一个旧的供应商表,仍然限制在255.我们希望暂时使用触发器来解决这个问题,直到我们可以在下一次迭代中实现更加商业友好的解决方案。

以下是我的开始:

CREATE TRIGGER [mySchema].[TruncDescription] 
ON  [mySchema].[myTable] 
INSTEAD OF INSERT
AS 
BEGIN
SET NOCOUNT ON;

INSERT INTO [mySchema].[myTable]
SELECT SubType, type, substring(description, 1, 255)
FROM inserted
END

但是,当我尝试在myTable上插入时,我收到错误:

  

字符串或二进制数据   截断。声明一直如此   终止。

我尝试使用SET ANSI_WARNINGS OFF进行试验,这样可以使查询正常工作,但之后只是没有在说明列中插入任何数据。

有没有办法使用触发器来截断太长的数据,还是有其他替代方法我可以使用,直到可以设计出更有说服力的解决方案?我们在表修改方面相当有限(即我们不能),因为它是供应商表,我们不控制我们正在使用的Web服务,所以我们也不能要求他们修复它。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

通过此设置,一切正常。 不要说明显而易见但是你确定在测试时说明字段中有数据吗?他们有可能更改你插入的其他字段之一,也许其中一个是抛出错误?

CREATE TABLE [dbo].[DataPlay](
    [Data] [nvarchar](255) NULL
) ON [PRIMARY]
GO

和像这样的触发器

Create TRIGGER updT ON  DataPlay 
Instead of Insert 
AS 
BEGIN
    SET NOCOUNT ON;     
INSERT INTO [tempdb].[dbo].[DataPlay]
           ([Data])
           (Select substring(Data, 1, 255) from inserted)
END
GO

然后插入

Declare @d as nvarchar(max)
Select @d = REPLICATE('a', 500)
SET ANSI_WARNINGS OFF
INSERT INTO [tempdb].[dbo].[DataPlay]
           ([Data])
     VALUES
           (@d)
GO

答案 1 :(得分:2)

无法避免错误,因为填充插入的表时会发生错误。

从文档中: http://msdn.microsoft.com/en-us/library/ms191300.aspx

“inserted和deleted表的格式与定义INSTEAD OF触发器的表的格式相同。inserted和deleted表中的每一列都直接映射到基表中的一列。”< / p>

我能想到的唯一真正“聪明”的想法是利用模式和登录使用的默认模式。如果您可以获取Web服务用于引用另一个表的登录名,则可以增加该表上的列大小,并使用INSTEAD OF INSERT触发器对供应商表执行INSERT。其中一个变体是在不同的数据库中创建表,并为Web服务登录设置默认数据库。

CREATE TRIGGER [myDB].[mySchema].[TruncDescription] 
ON  [myDB].[mySchema].[myTable] 
INSTEAD OF INSERT
AS 
BEGIN
SET NOCOUNT ON;

INSERT INTO [VendorDB].[VendorSchema].[VendorTable]
SELECT SubType, type, substring(description, 1, 255)
FROM inserted
END

答案 2 :(得分:1)

我无法使用以下方法在SQL 2008 R2上重现此问题:

Declare @table table ( fielda varchar(10) )

Insert  Into @table ( fielda )
Values  ( Substring('12345678901234567890', 1, 10) )

请确保您的字段确实定义为varchar(255)。

我还强烈建议您使用带有显式字段列表的Insert语句。虽然您的Insert在语法上是正确的,但您确实应该使用显式字段列表(就像在我的示例中一样)。问题是当您没有指定字段列表时,您将受SQL的限制和字段顺序的表定义。当您执行使用字段列表时,您可以更改表中字段的顺序(或在中间添加新字段),而不关心插入语句。