Saat mengeluarkan perintah cadangan dalam prosedur tersimpan yang menggunakan try catch dan sql dinamis, pesan kesalahan sangat umum jika dibandingkan dengan menjalankan perintah cadangan secara langsung.
Coba / Tangkap dalam SP:
begin try
execute sp_executesql @sql; -- a backup command
end try
begin catch
print ERROR_MESSAGE(); -- save to log, etc.
end catch
Hasil dalam
50000: usp_Backup: 117: BATUP DATABASE berakhir secara tidak normal.
ketika mengeluarkan perintah mentah:
backup DATABASE someDb to disk...
Hasil dalam detail yang lebih baik:
Kesalahan Pencarian - Kesalahan Database SQL Server: Terjadi kesalahan I / O yang tidak dapat dipulihkan pada file "H: \ FolderName \ Filename.bak:" 112 (Tidak ada cukup ruang pada disk.).
Apakah ada cara untuk menangkap rincian ini ke dalam variabel dalam prosedur tersimpan (untuk log, kembali ke pemanggil, untuk coba lagi logika)? Sepertinya detailnya datang melalui saluran pesan tapi saya ingin mereka tersedia dalam SP.
sumber
Jawaban:
Ketika
BACKUP DATABASE
menghasilkan kesalahan, itu sebenarnya menghasilkan dua. SayangnyaTRY/CATCH
tidak mampu menangkap kesalahan pertama; hanya menangkap kesalahan kedua.Saya menduga taruhan terbaik Anda untuk menangkap alasan sebenarnya di balik cadangan yang gagal adalah untuk mengotomatiskan cadangan Anda melalui SQLCMD (dengan
-o
mengirim hasil ke file), SSIS, C #, PowerShell dll. Semua yang akan memberi Anda kontrol lebih besar untuk menangkap semua dari kesalahan.Jawaban SO dalam komentar menyarankan menggunakan
DBCC OUTPUTBUFFER
- selagi mungkin, ini sepertinya bukan permainan anak-anak sama sekali. Merasa bebas untuk bersenang-senang dengan prosedur ini dari situs Erland Sommarskog , tetapi ini masih tidak berfungsi dengan baik jika dikombinasikanTRY/CATCH
.Satu-satunya cara saya tampaknya dapat menangkap pesan kesalahan
spGET_LastErrorMessage
adalah jika kesalahan yang sebenarnya terjadi. Jika Anda membungkusnya dalamTRY/CATCH
kesalahan tertelan dan prosedur yang tersimpan tidak melakukan apa-apa:Di SQL Server <2012 Anda tidak bisa menaikkan kembali kesalahan sendiri, tetapi Anda bisa di SQL Server 2012 dan yang lebih baru. Jadi dua variasi ini berfungsi:
Atau pada 2012 dan di atas, ini berfungsi, tetapi sebagian besar mengalahkan tujuan
TRY/CATCH
, karena kesalahan asli masih dilemparkan:Dalam kedua kasus ini, kesalahan masih terjadi pada klien, tentu saja. Jadi jika Anda menggunakan
TRY/CATCH
untuk menghindari itu, kecuali ada beberapa celah yang tidak saya pikirkan, saya khawatir Anda harus membuat pilihan ... baik memberikan kesalahan kepada pengguna dan dapat menangkap detail tentang itu, atau menekan kesalahan dan alasan sebenarnya.sumber
Yah saya tahu ini adalah utas lama, dan saya tahu apa yang akan saya usulkan adalah peretasan yang berbelit-belit, tetapi untuk berjaga-jaga kalau itu bisa membantu siapa saja, begini: Karena kesalahan cadangan ini dicatat, Anda dapat menggunakan xp_readerrorlog di tangkapan layar blokir untuk mengikis log untuk pesan terkait (kesalahan atau info). Anda dapat mencari Google untuk xp_readerrorlog params tetapi singkatnya Anda dapat menentukan string pencarian dan filter waktu mulai yang berguna dalam kasus ini. Tidak yakin apakah ini akan membantu Anda coba lagi logika, tetapi untuk menangkap info atau kesalahan untuk login, saya datang dengan sesuatu seperti ini ...
HTH
sumber
Anda bisa mencatat rincian kesalahan ke tabel. Anda juga bisa membuat file log, tetapi itu mungkin memerlukan CLR atau xp_cmdshell untuk melakukannya. Anda juga dapat mengirim email basis data, tetapi itu dapat menyebabkan masalah spam dan bukan log yang tepat.
Tabelnya paling sederhana.
Lihat contoh Jeremy Kadlec yang disediakan di tautan di bawah ini:
http://www.mssqltips.com/sqlservertip/1152/standardized-sql-server-error-handling-and-centralized-logging/
sumber
CATCH
. Ini karena hanya pesan kesalahan terakhir yang dikembalikan dalamERROR_MESSAGE()
...