2012-08-13 66 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