Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Kunci Komposit Unik SQL Server dari Dua Bidang Dengan Peningkatan Otomatis Bidang Kedua

Sejak seseorang memposting pertanyaan serupa, saya telah merenungkan ini. Masalah pertama adalah bahwa DB tidak menyediakan urutan "yang dapat dipartisi" (yang akan dimulai ulang/diingat berdasarkan kunci yang berbeda). Yang kedua adalah SEQUENCE objek yang adalah yang disediakan ditujukan untuk akses cepat, dan tidak dapat dibatalkan (yaitu, Anda akan mendapatkan celah). Ini pada dasarnya mengesampingkan penggunaan utilitas bawaan... artinya kita harus menjalankannya sendiri.

Hal pertama yang kita perlukan adalah tabel untuk menyimpan nomor urut kita. Ini bisa sangat sederhana:

CREATE TABLE Invoice_Sequence (base CHAR(1) PRIMARY KEY CLUSTERED,
                               invoiceNumber INTEGER);

Pada kenyataannya base kolom harus menjadi referensi kunci asing ke tabel/id apa pun yang mendefinisikan bisnis/entitas tempat Anda menerbitkan faktur. Dalam tabel ini, Anda ingin entri menjadi unik per entitas yang diterbitkan.

Selanjutnya, Anda menginginkan proc tersimpan yang akan mengambil kunci (base ) dan keluarkan nomor berikutnya dalam urutan (invoiceNumber ). Kumpulan kunci yang diperlukan akan bervariasi (yaitu, beberapa nomor faktur harus berisi tahun atau tanggal lengkap penerbitan), tetapi bentuk dasar untuk situasi ini adalah sebagai berikut:

CREATE PROCEDURE Next_Invoice_Number @baseKey CHAR(1), 
                                     @invoiceNumber INTEGER OUTPUT 
AS MERGE INTO Invoice_Sequence Stored
              USING (VALUES (@baseKey)) Incoming(base)
                 ON Incoming.base = Stored.base
   WHEN MATCHED THEN UPDATE SET Stored.invoiceNumber = Stored.invoiceNumber + 1
   WHEN NOT MATCHED BY TARGET THEN INSERT (base) VALUES(@baseKey)
   OUTPUT INSERTED.invoiceNumber ;;

Perhatikan bahwa:

  1. Anda harus jalankan ini dalam transaksi berseri
  2. Transaksi harus sama dengan yang dimasukkan ke tabel tujuan (faktur).

Itu benar, Anda masih akan mendapatkan pemblokiran per bisnis saat mengeluarkan nomor faktur. Anda tidak bisa hindari ini jika nomor faktur harus berurutan, tanpa celah - sampai baris benar-benar dikomit, mungkin akan dibatalkan, artinya nomor faktur tidak akan diterbitkan.

Sekarang, karena Anda tidak ingin mengingat untuk memanggil prosedur entri, bungkus dalam pemicu:

CREATE TRIGGER Populate_Invoice_Number ON Invoice INSTEAD OF INSERT
AS 
  DECLARE @invoiceNumber INTEGER
  BEGIN
    EXEC Next_Invoice_Number Inserted.base, @invoiceNumber OUTPUT
    INSERT INTO Invoice (base, invoiceNumber) 
                VALUES (Inserted.base, @invoiceNumber)
  END

(jelas, Anda memiliki lebih banyak kolom, termasuk kolom lain yang harus diisi secara otomatis - Anda harus mengisinya)
...yang kemudian dapat Anda gunakan hanya dengan mengatakan:

INSERT INTO Invoice (base) VALUES('A');

Jadi apa yang telah kita lakukan? Sebagian besar, semua pekerjaan ini adalah tentang menyusutkan jumlah baris yang dikunci oleh suatu transaksi. Sampai INSERT di-commit, hanya ada dua baris yang terkunci:

  • Baris di Invoice_Sequence mempertahankan nomor urut
  • Baris di Invoice untuk faktur baru.

Semua baris lain untuk base tertentu gratis - mereka dapat diperbarui atau ditanyakan sesuka hati (menghapus informasi dari sistem semacam ini cenderung membuat akuntan gugup). Anda mungkin perlu memutuskan apa yang akan terjadi ketika kueri biasanya menyertakan faktur yang menunggu keputusan...



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Menghubungkan aplikasi inti ASP.NET Anda ke instance lokal SQLServer

  2. 2 Cara Mengembalikan Daftar Pemicu di Database SQL Server menggunakan T-SQL

  3. Kembalikan Daftar Peristiwa Pemicu Server di SQL Server

  4. Terhubung ke Database MSSQL menggunakan Flask-SQLAlchemy

  5. Bagaimana cara memilih semua catatan dari satu tabel yang tidak ada di tabel lain?