以下 C# 代碼正確地與 MySQL 服務器一起作業,以從表中獲取列的 MAX 值,同時此查詢將 1 添加到該值,如下所示:
SqlDataReader dr = new SqlCommand("SELECT (MAX(Consec) 1) AS NextSampleID FROM Samples", Connection).ExecuteReader();
while (dr.Read())
{ //in case of Maximum value of Consec = 555, the expected result: A556
txtSampleID.Text = "A" dr["NextSampleID"].ToString();
}
然而這段代碼在將資料庫從 MySQL 遷移到 SQL Server 后不再起作用,如果 MAX(Consec) = 555 結果是一樣的,運行查詢后的結果是 A555,它不像以前使用 MySQL 服務器時那樣加 1。
問題:獲取Consec 的MAX 值的正確查詢是什么,如何在同一個查詢中將MAX 的結果加“1”?
uj5u.com熱心網友回復:
MySQL 查詢是錯誤的,除了在微不足道的應用程式中不起作用,只有一個用戶,沒有洗掉和關系:
- 并發呼叫將產生相同的 MAX 值,因此導致相同的、重復的下一個值
- 洗掉記錄將減少 MAX 值,導致以前的 ID 值被分配給新行。如果在另一個表中使用該 ID 值,則新記錄最終將與它沒有實際關系的行相關聯。這可能非常糟糕。想象一下,一名患者的測驗樣本與另一名患者的測驗樣本混合在一起。
- 計算 MAX 需要鎖定整個表或索引,從而阻塞或被其他人阻塞。考慮到 MySQL 的 MVCC 隔離,這不會阻止重復,因為并發
SELECT MAX查詢不會相互阻塞。
MAX 1在只有一個終端生成發票編號的 POS 應用程式中是可行的,但是一旦您添加了兩個 POS 終端,您就有生成重復發票的風險。
另一方面,在電子商務應用程式中,幾乎可以保證即使每月只下兩個訂單,它們也會在完全相同的時刻發生,從而導致重復。
正確的 MySQL 解決方案和等價物
MySQL 中的正確解決方案是使用AUTO_INCREMENT屬性:
CREATE TABLE Samples (
Consec INT NOT NULL AUTO_INCREMENT,
...
);
如果您希望發票編號包含其他資料,請使用計算列來組合遞增編號和其他資料。
SQL Server 中的等效項是IDENTITY 屬性:
CREATE TABLE Samples (
Consec INT NOT NULL IDENTITY,
...
);
序列
SQL Server 和其他資料庫中可用的另一個選項是SEQUENCE物件。SEQUENCE 可用于生成與表無關的遞增數字。它也可以重置,非常適合在特定時期(例如每年)后重置發票編號的會計應用程式。
由于 aSEQUENCE是一個獨立物件,因此您可以在使用NEXT VALUE FOR將任何資料插入資料庫之前增加并接收新值,例如:
SELECT NEXT VALUE FOR seq_InvoiceNumber;
NEXT VALUE FOR可以以相同的方式用作表列的默認約束IDENTITY或AUTO_INCREMENT使用:
Create MyTable (
...
Consec INT NOT NULL DEFAULT (NEXT VALUE FOR seq_ThatSequence)
)
多表序列
The same sequence can be used in multiple tables. One case where that's useful is assigning a Document ID to data imported from multiple sources, stored in different tables, eg payments.
Payment providers (credit cards, banks etc) send statements using different formats. Obviously you can't lose any information there so you need to use different tables per provider, but still be able to handle payments the same way no matter where they came from.
If you used an IDENTITY on each table you'd end up with conflicting IDs for payments coming from different providers. On eg the OrderPayments table you'd have to record both the provider name and ID. Generating a single view of payments would end up with ID values that can't be used by themselves.
By using a single SEQUENCE though, each record would get its own ID, no matter the table.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/328798.html
標籤:C# sql sql-server 选择
