0

最近我继承了一个新的 ASP Web 应用程序,它只允许客户在线支付他们的未结发票。该应用程序设计不佳,并且没有付款历史记录表。将支付记录传输到记录会计系统的 Web 服务删除了整个支付表。

我刚刚在 Payments 表上创建了一个简单的触发器,它只是将 Payments 表中的数据复制到 Payment_Log 表中。最初,触发器只是做了一个 select * on insert 来复制数据。但是,我刚刚修改了触发器以将付款日期插入到 Payment_Log 表中,因为我们的一位客户遇到了一些我需要调试的问题。新的触发器如下。我的问题是我注意到使用这个新版本的触发器,行被插入到表的中间(即不是在末尾)。有人可以解释为什么会这样吗?

ALTER trigger [dbo].[PaymentHistory] on [dbo].[Payments]
for insert as

Declare @InvoiceNo nvarchar(255),
    @CustomerName nvarchar(255),
    @PaymentAmount float,
    @PaymentRefNumber nvarchar(255),
    @BulkPaid bit,
    @PaymentType nvarchar(255),
    @PaymentDate datetime

Select @InvoiceNo = InvoiceNo,
   @CustomerName = CustomerName,
   @PaymentAmount = PaymentAmount,
   @PaymentRefNumber = PaymentRefNumber,
   @BulkPaid = BulkPaid,
   @PaymentType = PaymentType
from inserted

Set @PaymentDate = GETDATE()

Insert into Payment_Log 
values (@InvoiceNo, @CustomerName, @PaymentAmount, @PaymentRefNumber, @BulkPaid, @PaymentType, @PaymentDate)

下面是 SQL Server Management Studio 的屏幕截图,显示了插入到表数据中间的行。在此先感谢您的帮助。

在此处输入图像描述

4

2 回答 2

5

数据集没有顺序。这意味着每次都SELECT * FROM x 可以以不同的顺序返回结果。

唯一保证数据以相同顺序返回的情况是在您指定ORDER BY子句时。


也就是说,在某些情况下,数据通常会按特定顺序返回。最明显的是聚集索引。

这让我想知道这两个表是否有主键。检查每个表上的所有索引,并至少强制执行主键。


顺便说一句,SQL Server 中的触发器不是针对每行触发,而是针对每批触发。这可能意味着该inserted表可以包含不止一行。 (例如,批量插入测试数据,或重新加载大批量事务时。)

因此,将数据复制到变量中不是标准做法。相反,您可以执行以下操作...

ALTER trigger [dbo].[PaymentHistory] on [dbo].[Payments]
for insert as

INSERT INTO
  Payment_Log
SELECT
  InvoiceNo, CustomerName, PaymentAmount, PaymentRefNumber,
  BulkPaid,  PaymentType,  GetDate()
FROM
  inserted
于 2012-08-13T14:51:53.990 回答
-1

好的 这个问题的答案与我在 SQL 查询中不使用 order by 子句时为什么行以不同的顺序返回的答案相同。如果您要求 SQL 以任何方式处理行,它将以最快的方式处理它们,首先兑现行,接下来是最接近硬盘驱动器上读取头的行,最后是其余行。

换一种说法:如果查询的行顺序比先到先得的方式要长 10 倍,您会很恼火。SQL 尽可能快地完成您所要求的工作

希望这可以帮助

于 2012-08-13T14:47:26.023 回答