Konversi gagal saat mengonversi nilai nvarchar '01HP011' ke tipe data int

Saya mendapatkan kesalahan konversi di satu server tetapi tidak di server lain, keduanya memiliki database yang sama, yang satu adalah pengujian dan yang lainnya aktif, pengujian sebenarnya adalah salinan dari yang aktif tetapi agak lama. Server langsung telah mengaktifkan AlwaysOn. ketika saya menjalankan Print @@version di kedua server, saya mendapatkan yang berikut

Microsoft SQL Server 2016 (SP1-CU1) (KB3208177) - 13.0.4411.0 (X64) 
    Jan  6 2017 14:24:37 
    Copyright (c) Microsoft Corporation
    Standard Edition (64-bit) on Windows Server 2016 Standard 6.3 <X64> (Build 14393: ) (Hypervisor)

Ini adalah kueri sql yang saya jalankan


exec sp_executesql N'select * From DataTable
WHERE DT1 = @P1 AND DT2 = @P2
order by
cp1',N'@P1 smallint,@P2 smallint',0,0

kolom DT2 memiliki nilai campuran 1 dan 1BAC dan NULL tetapi saya tidak mengerti mengapa ini berfungsi di satu server tetapi tidak di server lain.


person Declan Junior    schedule 28.09.2020    source sumber
comment
Tipe Anda benar-benar harus cocok, karena berbagai alasan. Jika DT2 bukan smallint, mengapa Anda menggunakan smallint di klausa WHERE Anda? Itu baru saja rusak.   -  person pmbAustin    schedule 28.09.2020
comment
Terima kasih, kode ditulis di aplikasi dan mengirimkan permintaan seperti itu tetapi gagal dijalankan saat live tetapi berfungsi pada pengujian dan satu-satunya perbedaan adalah pengujian sedikit lebih lama dari Live dan berada di server yang berbeda, 90% data di tabel itu cocok, jadi mengapa ini berhasil saat pengujian?   -  person Declan Junior    schedule 28.09.2020
comment
Untuk membuat pernyataan yang jelas, tetapi kesalahan adalah memberi tahu Anda masalahnya di sini, '01HP011' bukan nilai int yang valid. ints tidak memiliki huruf di dalamnya.   -  person Larnu    schedule 28.09.2020
comment
Terima kasih Larun, saya sudah menebak kesalahan apa yang dikatakannya tetapi pertanyaan saya tetap sama, mengapa ini berhasil pada satu hal tetapi tidak pada yang lain...   -  person Declan Junior    schedule 28.09.2020
comment
Mengapa ini berhasil di satu dan tidak di yang lain. Pertama kita harus berasumsi bahwa apa yang Anda klaim adalah benar - bahwa struktur databasenya identik. Kami tahu bahwa keduanya tidak memiliki konten yang sama, dan itulah salah satu faktornya. Tetapi bahkan dengan asumsi mereka melakukannya, KEBERUNTUNGAN adalah alasan mengapa hal itu berhasil pada satu hal dan tidak pada yang lain. Kode Anda bergantung pada konversi implisit yang tidak aman. Jika beruntung, rencana eksekusi menghindari baris yang tidak dapat dikonversi. Mengapa ia melakukan hal itu? Bandingkan paket dan bandingkan baris yang diakses.   -  person SMor    schedule 29.09.2020
comment
Dan bahkan jika Anda tahu alasannya, lalu bagaimana? Kode aplikasi Anda perlu diperbaiki - menghindari bug bukanlah strategi kemenangan.   -  person SMor    schedule 29.09.2020
comment
Menurut aturan untuk prioritas tipe data saat Anda menggabungkan tipe data SmallInt dan string dalam sebuah ekspresi, mis. DT2 = @P2, string akan diubah menjadi SmallInt. Anda dapat menggunakan Cast untuk memaksakan konversi dengan cara lain, mis. DT2 = Cast( @P2 as VarChar(10) ).   -  person HABO    schedule 29.09.2020
comment
Terima kasih teman-teman, ketika saya mengetahui bahwa ini berfungsi pada database yang memiliki struktur yang sama tetapi lebih sedikit data maka saya pikir itu mungkin semacam pengaturan tingkat database/server yang mungkin menyebabkan masalah ini, itu sebabnya saya beralih ke kalian... Terima kasih lagi   -  person Declan Junior    schedule 29.09.2020
comment
Tip: Anda dapat menggunakan Try_Convert untuk mengidentifikasi nilai-nilai buruk.   -  person HABO    schedule 29.09.2020


Jawaban (1)


Sepertinya dt2 didefinisikan sebagai string, bukan sebagai angka. Anda harus menyelaraskan tipe data parameter Anda ke tipe data yang benar - jika tidak, SQL Server akan mencoba memaksakan string ke angka, yang akan gagal pada nilai seperti '1ABC':

Mempertimbangkan:

exec sp_executesql 
    N'select * From DataTable WHERE DT1 = @P1 AND DT2 = @P2 order by cp1',
    N'@P1 smallint, @P2 nvarchar(10)', 0, '0'

Anda mungkin ingin meninjau ukuran string parameter, dan memastikan bahwa parameter lainnya tidak memiliki masalah yang sama.


Mengapa kode Anda gagal di satu server tetapi tidak di server lain kemungkinan besar terkait dengan data Anda: semua nilai di dt2 dapat dikonversi menjadi angka, atau mungkin predikat where lainnya menghilangkan nilai yang salah sebelum server mencoba mengonversinya.

Berikut adalah demo yang menunjukkan hal ini.

Contoh data:

dt1 | dt2  |  cp1
--: | :--- | ---:
  0 | 1    | null
  0 | 1ABC | null
  0 | null | null

Ini gagal karena kesalahan konversi:

exec sp_executesql 
    N'select * From DataTable WHERE DT1 = @P1 AND DT2 = @P2 order by cp1',
    N'@P1 int, @P2 int', 0, 10

Ini berfungsi (dan mengembalikan hasil kosong):

exec sp_executesql 
    N'select * From DataTable WHERE DT1 = @P1 AND DT2 = @P2 order by cp1',
    N'@P1 int, @P2 int', 1, 10
person GMB    schedule 28.09.2020
comment
Tes berumur satu bulan dan juga mendapat data campuran (angka, string), apakah ada pengaturan tingkat database/server yang mungkin memaksa server sql berperilaku berbeda? Sebagai tambahan, kondisi Where sama di kedua server. tidak yakin mengapa kode aplikasi ditulis seperti ini tetapi yang saya coba temukan adalah mengapa itu berhasil. juga Dimana kondisinya selalu sama dengan nilai yang sama, 0 , 0 dan 1000 baris teratas pada tabel tersebut adalah sama. begitulah cara kode ditulis, selalu menghasilkan 0 baris - person Declan Junior; 28.09.2020