Saya perlu menulis prosedur tersimpan T-SQL yang memperbarui baris dalam sebuah tabel. Jika baris tidak ada, masukkan. Semua langkah ini dibungkus oleh suatu transaksi.
Ini untuk sistem pemesanan, jadi harus atomik dan andal . Ini harus mengembalikan true jika transaksi dilakukan dan penerbangan dipesan.
Saya baru mengenal T-SQL , dan tidak yakin bagaimana cara menggunakannya @@rowcount
. Ini yang saya tulis sampai sekarang. Apakah saya di jalan yang benar? Saya yakin ini adalah masalah yang mudah bagi Anda.
-- BEGIN TRANSACTION (HOW TO DO?)
UPDATE Bookings
SET TicketsBooked = TicketsBooked + @TicketsToBook
WHERE FlightId = @Id AND TicketsMax < (TicketsBooked + @TicketsToBook)
-- Here I need to insert only if the row doesn't exists.
-- If the row exists but the condition TicketsMax is violated, I must not insert
-- the row and return FALSE
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO Bookings ... (omitted)
END
-- END TRANSACTION (HOW TO DO?)
-- Return TRUE (How to do?)
sql
sql-server
sql-server-2008
tsql
Whymarrh
sumber
sumber
Jawaban:
Lihatlah perintah MERGE . Anda dapat melakukannya
UPDATE
,INSERT
&DELETE
dalam satu pernyataan.Berikut ini adalah implementasi bekerja pada penggunaan
MERGE
- Ini memeriksa apakah penerbangan penuh sebelum melakukan pembaruan, selain itu memasukkan.
Lalu ...
sumber
Saya menganggap satu baris untuk setiap penerbangan? Jika begitu:
Saya berasumsi apa yang saya katakan, karena cara Anda melakukan hal-hal dapat memesan tiket lebih dari penerbangan, karena akan memasukkan baris baru ketika ada 10 tiket maks dan Anda memesan 20.
sumber
BEGIN TRAN ... COMMIT
bawah tingkat isolasi standar tidak akan menyelesaikan masalah. OP menetapkan bahwa atomik dan andal adalah persyaratan. Jawaban Anda gagal mengatasinya dalam bentuk atau bentuk apa pun.IF EXISTS (SELECT * FROM Bookings (UPDLOCK, HOLDLOCK) WHERE FLightID = @Id)
?Lewati updlock, rowlock, petunjuk holdlock saat menguji keberadaan baris.
Petunjuk updlock memaksa kueri untuk mengambil kunci pembaruan di baris jika sudah ada, mencegah transaksi lain dari memodifikasinya sampai Anda melakukan atau memutar kembali.
Petunjuk penahanan memaksa kueri untuk mengambil kunci rentang, mencegah transaksi lain dari menambahkan baris yang cocok dengan kriteria filter Anda sampai Anda komit atau memutar kembali.
Petunjuk baris kunci memaksa granularity kunci ke tingkat baris alih-alih tingkat halaman default, sehingga transaksi Anda tidak akan memblokir transaksi lain yang mencoba memperbarui baris yang tidak terkait di halaman yang sama (tetapi berhati-hatilah dengan trade-off antara pertikaian yang berkurang dan peningkatan mengunci overhead - Anda harus menghindari mengambil sejumlah besar kunci tingkat baris dalam satu transaksi).
Lihat http://msdn.microsoft.com/en-us/library/ms187373.aspx untuk informasi lebih lanjut.
Perhatikan bahwa kunci diambil sebagai pernyataan yang membawanya dieksekusi - memohon mulai tran tidak memberi Anda kekebalan terhadap transaksi lain menjepit kunci pada sesuatu sebelum Anda sampai ke sana. Anda harus mencoba dan faktor SQL Anda untuk menahan kunci untuk waktu sesingkat mungkin dengan melakukan transaksi sesegera mungkin (memperoleh terlambat, lepaskan lebih awal).
Perhatikan bahwa kunci tingkat baris mungkin kurang efektif jika PK Anda merupakan masalah besar, karena hashing internal pada SQL Server mengalami degenerasi untuk nilai 64-bit (nilai kunci yang berbeda mungkin hash ke id kunci yang sama).
sumber
exists
pemeriksaan ekstra preventif tanpa penguncian petunjuk.saya sedang menulis solusi saya. metode saya tidak tahan 'jika' atau 'bergabung'. metode saya mudah.
Sebagai contoh:
Penjelasan:
(1) PILIH col1, col2 DARI TableName WHERE col1 = @ par1 DAN col2 = @ par2 Ia memilih dari nilai yang dicari TableName
(2) SELECT @ par1, @ par2 WHERE NOT EXISTS Dibutuhkan jika tidak ada dari (1) subquery
(3) Menyisipkan nilai langkah TableName (2)
sumber
Saya akhirnya bisa menyisipkan baris, dengan syarat belum ada, menggunakan model berikut:
yang saya temukan di:
http://www.postgresql.org/message-id/[email protected]
sumber
Ini adalah sesuatu yang baru-baru ini harus saya lakukan:
sumber
Anda dapat menggunakan Fungsi Gabung untuk mencapai. Kalau tidak, Anda dapat melakukan:
sumber
Solusi lengkapnya ada di bawah (termasuk struktur kursor). Terima kasih banyak kepada Cassius Porcus untuk
begin trans ... commit
kode dari posting di atas.sumber
sumber
sumber
Pendekatan terbaik untuk masalah ini adalah pertama-tama membuat kolom basis data UNIK
ALTER TABLE table_name ADD UNIQUE KEY
THEN INSERT IGNORE INTO table_name
, nilai tidak akan dimasukkan jika menghasilkan kunci duplikat / sudah ada dalam tabel.sumber