Saya menyiapkan tugas untuk mengulang daftar server yang ditautkan dan menjalankan kueri tertentu terhadap masing-masing server. Saya mencoba untuk mengeksekusi query di dalam blok TRY-CATCH jadi jika ada masalah dengan satu server tertentu saya bisa login tetapi kemudian melanjutkan dengan server lain.
Kueri yang saya jalankan di dalam loop terlihat seperti ini:
BEGIN TRY
SELECT *
FROM OPENQUERY([server1], 'SELECT 1 AS c;');
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER(), ERROR_MESSAGE();
END CATCH;
PRINT 'We got past the Catch block!';
Jika ada masalah saat menyambung ke server, kode itu langsung gagal dan tidak dapat ditransfer ke CATCH
blok. Jika server terhubung tetapi ada kesalahan dalam kueri yang sebenarnya, mis. Bagi dengan nol, maka ini ditangkap seperti yang diharapkan oleh CATCH
blok.
Misalnya, saya membuat server tertaut ke nama yang saya tahu tidak ada. Saat menjalankan hal di atas saya baru saja mendapatkan:
OLE DB provider "SQLNCLI" for linked server "nonserver" returned message
"Login timeout expired".
OLE DB provider "SQLNCLI" for linked server "nonserver" returned message
"An error has occurred while establishing a connection to the server.
When connecting to SQL Server 2005, this failure may be caused by the
fact that under the default settings SQL Server does not allow remote
connections.".
Msg 53, Level 16, State 1, Line 0
Named Pipes Provider: Could not open a connection to SQL Server [53].
Saya telah membaca BOL TRY-CATCH
dan tahu bahwa itu tidak akan menangkap kesalahan level 20+ yang memutuskan koneksi tetapi ini tampaknya tidak menjadi masalah (ini hanya level 16).
Adakah yang tahu mengapa kesalahan ini tidak ditangkap dengan benar?
sumber
PRINT 'Start';
di bagian paling atas skrip, ini akan dicetak dalam output, meskipun koneksi kemudian gagal dan skrip keluar dengan kesalahan. Jadi ini akan menunjukkan kesalahan runtime bukan? Kecuali saya salah paham?PRINT
saya masih memilikisp_testlinkedserver
panggilan dalam skrip. Sebenarnya, itu tidak bisa dicetak menggunakan skrip asli saya (gagal). Jadi sepertinya ini sebenarnya adalah kesalahan kompilasi-waktu , yang mengapa tidak ketahuan.sp_testlinkedserver
panggilan keluar , tetapi meninggalkanSELECT
SQL dinamis. TidakPRINT
terjadi jika Anda merujuk nama server secara langsung, jadi seperti yang saya sarankan sebelumnya,BEGIN TRY
tidak pernah dimasukkan karena kesalahan dinaikkan terlebih dahulu.Setelah penyelidikan sepertinya kesalahan ini tidak ditangkap karena ini adalah kesalahan waktu kompilasi daripada kesalahan runtime. Untuk menunjukkan ini, coba yang berikut ini:
PRINT
Pernyataan awal tidak mendapatkan output, juga tidak membagi kesalahan dengan nol dieksekusi / ditangkap. Server yang tidak ada menyebabkan skrip segera gagal.sumber
Saya baru-baru ini memiliki masalah yang sama di mana saya memanggil prosedur jarak jauh dari dalam TRY-CATCH dan prosedur gagal karena upaya untuk memasukkan kunci duplikat (kesalahan run time level 16). Blok CATCH tidak dipanggil. Saya menemukan alasannya dalam artikel ini: https://technet.microsoft.com/en-us/library/ms191515(v=sql.105).aspx
Solusinya adalah SET XACT_ABORT AKTIF dalam prosedur panggilan sebelum memanggil prosedur jarak jauh. Ketika XACT_ABORT berada di blok CATCH dipanggil seperti yang diharapkan. Anda perlu mengetahui bahwa pengaturan XACT_ABORT disebarkan ke prosedur jarak jauh, dan itu mungkin mempengaruhi perilakunya.
sumber
sumber