Saya memiliki prosedur tersimpan yang menjalankan beberapa perintah. Saya tidak ingin perintah ini dibungkus dengan transaksi dari prosedur tersimpan. Jika perintah ke-4 gagal, saya ingin yang ke-1, ke-2 dan ke-3 tetap dan tidak kembalikan.
Apakah mungkin untuk menulis prosedur tersimpan sedemikian rupa sehingga tidak semua dijalankan sebagai satu transaksi besar?
Semua transaksi tidak akan dieksekusi dalam satu transaksi. Lihatlah contoh ini:
use TestDB;
go
ifexists(select1from sys.tables where object_id = object_id('dbo.TestTranTable1'))droptable dbo.TestTranTable1;createtable dbo.TestTranTable1
(
id int identity(1,1)notnull,
some_int int notnulldefault1);
go
insertinto dbo.TestTranTable1
defaultvalues;
go 4select*from dbo.TestTranTable1;ifexists(select1from sys.sql_modules where object_id = object_id('dbo.ChangeValues'))begindropproc dbo.ChangeValues;end
go
createproc dbo.ChangeValues
asupdate dbo.TestTranTable1
set some_int =11where id =1;update dbo.TestTranTable1
set some_int =12where id =2;update dbo.TestTranTable1
set some_int =13where id =3;-- this will error out (arithmetic overflow)update dbo.TestTranTable1
set some_int =2147483648where id =4;
go
exec dbo.ChangeValues;select*from dbo.TestTranTable1;
Berikut hasilnya:
Dengan membuat sesi Extended Events untuk memantau sql_transactionacara, berikut adalah output dari pelaksanaan dbo.ChangeValues:
Seperti yang dapat Anda lihat pada tangkapan layar di atas, ada transaksi terpisah untuk masing-masing dari empat pernyataan. 3 komit pertama, dan yang terakhir memutar kembali karena kesalahan.
Saya pikir mungkin ada beberapa kebingungan di sini tentang batch vs transaksi .
Sebuah transaksi adalah pernyataan atau set pernyataan yang baik akan berhasil atau gagal sebagai satu unit. Semua pernyataan DDL dalam transaksi itu sendiri (yaitu jika Anda memperbarui 100 baris tetapi baris 98 menimbulkan kesalahan, tidak ada baris yang diperbarui). Anda dapat membungkus serangkaian pernyataan dalam suatu transaksi juga menggunakan BEGIN TRANSACTIONdan kemudian salah satu COMMITatau ROLLBACK.
Sebuah batch yang merupakan serangkaian pernyataan yang dijalankan bersama-sama. Prosedur tersimpan adalah contoh batch. Dalam prosedur tersimpan, jika satu pernyataan gagal dan ada perangkap kesalahan (biasanya TRY/CATCHblok) maka pernyataan berikutnya tidak akan dijalankan.
Saya menduga masalah Anda adalah batch dibatalkan ketika terjadi kesalahan karena proc yang disimpan itu sendiri atau lingkup luar (seperti aplikasi atau proc yang disimpan yang menyebut prosedur ini) memiliki kesalahan dalam menjebaknya. Jika itu masalahnya, ini lebih sulit untuk diselesaikan karena Anda perlu menyesuaikan cara Anda menangani kesalahan pada ruang lingkup apa pun yang menjebaknya.
Saya tidak menemukan artikel yang mengatakan, "Prosedur penyimpanan adalah contoh kumpulan". Saya percaya Stored Procedure sangat mirip dengan batch tetapi ini bukan batch. Perbedaan utama adalah: SP dijamin akan dikompilasi terlebih dahulu dan siap untuk dieksekusi beberapa kali tidak seperti Batch. Kesamaannya adalah: - Mereka berdua menjalankan setiap perintah pada suatu waktu. - Jika satu perintah gagal maka semua perintah sebelumnya dilakukan (kecuali jika sedang berjalan dalam transaksi) - jika satu perintah gagal maka semua perintah selanjutnya tidak dijalankan.
Ashi
6
Segala sesuatu di server sql terkandung dalam transaksi.
Ketika Anda secara eksplisit menentukan begin transactiondan end transactionkemudian disebut Transaksi Eksplisit . Ketika Anda tidak, maka itu adalah transaksi implisit .
Untuk mengganti mode yang Anda gunakan, gunakan
set implicit_transactions on
atau
set implicit_transactions offselect@@OPTIONS &2
jika di atas mengembalikan 2, Anda berada dalam mode transaksi implisit. Jika mengembalikan 0, Anda berada dalam autocommit.
Transaksi adalah SEMUA atau tidak sama sekali untuk menjaga basis data dalam keadaan konsisten .. ingat properti ACID.
Ini adalah cara kerja prosedur tersimpan secara default. Prosedur tersimpan tidak dibungkus dalam suatu transaksi secara otomatis.
Jika Anda ingin prosedur tersimpan berhenti ketika hits kesalahan pertama Anda ingin menaruh beberapa TRY / CATCH login di sana untuk kembali jika terjadi masalah dengan perintah 2 misalnya.
Saya ingin memastikan bahwa setiap transaksi merupakan perilaku default untuk prosedur tersimpan, karena semua pernyataan terbungkus dalam transaksi implisit; Namun, tidak seorang pun harus mengandalkan transaksi implisit untuk mengendalikan nasib kode mereka. Ini adalah praktik yang jauh lebih baik untuk secara eksplisit mengontrol cara transaksi ditangani dalam kode produksi.
pisahkan setiap bagian dengan BEGIN TRAN dan untuk memeriksa apakah transaksi berhasil. jika itu melakukan itu, kalau tidak lakukan rollback, karena mereka semua mengeksekusi dari tingkat yang sama Anda akan dapat melakukan setiap bagian secara terpisah tanpa harus mengembalikan semua jika salah satu gagal.
Apakah itu akan membuat sub transaksi dalam Prosedur Tersimpan saya? Idealnya saya ingin menghindari itu jika memungkinkan
Matthew Steeples
1
Jika SP dipanggil dari dalam suatu transaksi, maka transaksi yang disimpan di atas adalah jawabannya. Jika sp tidak dipanggil dengan, maka @rdenny sudah benar. Sql server tidak mendukung transaksi bersarang.
Agar lebih jelas (dan bagi pemalas yang tidak ingin mengklik tautan), Anda sebenarnya tidak memulai transaksi lain. Aka judul pada posting Paul: "Mitos: Transaksi Bertumpuk adalah nyata." Itu bukan transaksi nyata. KOMIT dalam transaksi bersarang tidak melakukan apa pun kecuali penurunan @@ TRANCOUNT. Memang benar bahwa Anda tidak mendapatkan kesalahan jika Anda bersarang BEGIN TRAN / COMMIT, tetapi itu berbeda dari memiliki transksi bersarang nyata.
Segala sesuatu di server sql terkandung dalam transaksi.
Ketika Anda secara eksplisit menentukan
begin transaction
danend transaction
kemudian disebut Transaksi Eksplisit . Ketika Anda tidak, maka itu adalah transaksi implisit .Untuk mengganti mode yang Anda gunakan, gunakan
atau
jika di atas mengembalikan 2, Anda berada dalam mode transaksi implisit. Jika mengembalikan 0, Anda berada dalam autocommit.
Transaksi adalah SEMUA atau tidak sama sekali untuk menjaga basis data dalam keadaan konsisten .. ingat properti ACID.
- buat SP sekarang - perhatikan bahwa 3 pertama akan berhasil dan 4 akan gagal karena pemotongan string ...
Lihat: Apakah praktik yang buruk untuk selalu membuat transaksi?
sumber
Ini adalah cara kerja prosedur tersimpan secara default. Prosedur tersimpan tidak dibungkus dalam suatu transaksi secara otomatis.
Jika Anda ingin prosedur tersimpan berhenti ketika hits kesalahan pertama Anda ingin menaruh beberapa TRY / CATCH login di sana untuk kembali jika terjadi masalah dengan perintah 2 misalnya.
sumber
Anda akan membutuhkan transaksi individual untuk setiap perintah. Anda juga dapat melakukan ini dengan transaksi tersimpan:
Lihat
SAVE TRANSACTION (Transact-SQL)
di dokumentasi produk.Saya ingin memastikan bahwa setiap transaksi merupakan perilaku default untuk prosedur tersimpan, karena semua pernyataan terbungkus dalam transaksi implisit; Namun, tidak seorang pun harus mengandalkan transaksi implisit untuk mengendalikan nasib kode mereka. Ini adalah praktik yang jauh lebih baik untuk secara eksplisit mengontrol cara transaksi ditangani dalam kode produksi.
sumber
pisahkan setiap bagian dengan BEGIN TRAN dan untuk memeriksa apakah transaksi berhasil. jika itu melakukan itu, kalau tidak lakukan rollback, karena mereka semua mengeksekusi dari tingkat yang sama Anda akan dapat melakukan setiap bagian secara terpisah tanpa harus mengembalikan semua jika salah satu gagal.
Untuk info lebih lanjut Anda dapat melihat di: http://msdn.microsoft.com/en-us/library/ms188929.aspx
sumber