2012-08-13 99 views
0

最近,我继承了一个新的ASP Web应用程序,它仅允许客户在线支付其未付发票。该应用程序设计不佳,没有付款记录表。整个支付表已由将服务记录传输到记录会计系统的Web服务删除。为什么SQL触发器不按顺序插入行?

我刚刚在Payments表上创建了一个简单的触发器,它将Payments表中的数据复制到Payment_Log表中。最初,触发器只是做了select * on插入来复制数据。不过,我只是修改了触发器,将付款日期插入到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中的截图,显示被插入到表中数据的中间行。预先感谢帮助家伙。

enter image description here

+7

1)表不*有*的命令,2)你的触发打破了多行插入,3)为什么要“命令”是无论如何一个问题? – 2012-08-13 14:43:56

+2

您在这里遗漏的最重要的概念是'inserted'是一个**表**而不是**行**。 – Yuck 2012-08-13 14:45:34

回答

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 
+1

+1很好的答案,非常完整。 – Yuck 2012-08-13 14:53:08

+0

在主键和聚簇索引之间进行区分很重要。一个默认创建另一个的事实是一个小细节。并且强调大约7次以上,即使存在聚集索引,也不保证没有'ORDER BY'的情况下返回结果的顺序。 – 2012-08-13 18:34:44

-1

好这个问题有相同的答案,为什么行回来在不同的订单时,我不会在我的SQL查询由子句中使用的命令。如果您要求SQL以任何方式处理行,它将以最快的方式处理它们,首先兑现行,然后是最靠近硬盘驱动器上读取头的那些行,然后是最后一行。

换句话说:如果查询花费的时间比按照先到先得的顺序多10倍,那么您会很烦恼。 SQL做你问什么尽可能快,因为它可以

希望这有助于

+1

这不是SQL Server的准确信息。一般来说,这可能并不准确。 – Yuck 2012-08-13 14:48:44

+0

那么它的答案与标记正确的答案相同 - 稍微短一些,但他们都说同样的事情。实际上,聚集索引并不能确保退货秩序,所以在这方面,你所称赞的独自答案完全符合达米恩指出的要求。 – 2012-08-14 15:27:16