Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

penggabungan nvarchar / indeks / nvarchar (maks) perilaku yang tidak dapat dijelaskan

TLDR; Ini bukan pendekatan yang didokumentasikan/didukung untuk menggabungkan string melintasi baris. Terkadang berhasil tetapi terkadang juga gagal karena tergantung pada rencana eksekusi yang Anda dapatkan.

Sebagai gantinya, gunakan salah satu dari pendekatan yang dijamin berikut

SQL Server 2017+

SELECT @a = STRING_AGG([msg], '') WITHIN GROUP (ORDER BY [priority] ASC)
FROM bla
where   autofix = 0

SQL Server 2005+

SELECT @a = (SELECT [msg] + ''
             FROM   bla
             WHERE  autofix = 0
             ORDER  BY [priority] ASC
             FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)') 

Latar Belakang

Artikel KB yang sudah ditautkan oleh VanDerNorth memang menyertakan baris

Perilaku yang benar untuk kueri penggabungan agregat tidak ditentukan.

tetapi kemudian melanjutkan sedikit memperkeruh keadaan dengan memberikan solusi yang tampaknya menunjukkan perilaku deterministik mungkin terjadi.

Untuk mencapai hasil yang diharapkan dari kueri penggabungan agregat, terapkan fungsi atau ekspresi Transact-SQL apa pun ke kolom dalam daftar SELECT daripada di klausa ORDER BY.

Kueri bermasalah Anda tidak menerapkan ekspresi apa pun ke kolom di ORDER BY klausa.

Artikel 2005 Memesan jaminan di SQL Server... menyatakan

Untuk alasan kompatibilitas mundur, SQL Server menyediakan dukungan untuk penetapan tipe SELECT @p =@p + 1 ... ORDER BY di paling atas.

Dalam rencana di mana penggabungan bekerja seperti yang Anda harapkan, skalar komputasi dengan ekspresi [Expr1003] = Scalar Operator([@x]+[Expr1004]) muncul di atas pengurutan.

Dalam rencana yang gagal berfungsi, skalar komputasi muncul di bawah pengurutan. Seperti yang dijelaskan dalam item penghubung ini dari tahun 2006 ketika ekspresi @x = @x + [msg] muncul di bawah jenis yang dievaluasi untuk setiap baris tetapi semua evaluasi berakhir dengan menggunakan nilai pra penetapan @x . Dalam Connect Item serupa lainnya dari tahun 2006 tanggapan dari Microsoft berbicara tentang "memperbaiki" masalah.

Tanggapan Microsoft pada semua item Connect yang lebih baru tentang masalah ini (dan ada banyak) menyatakan bahwa ini sama sekali tidak dijamin

Contoh 1

kami tidak menjamin kebenaran kueri rangkaian (seperti menggunakan penetapan variabel dengan pengambilan data dalam urutan tertentu). Keluaran kueri dapat berubah di SQL Server 2008bergantung pada pilihan paket, data dalam tabel, dll. Anda tidak boleh mengandalkan ini untuk bekerja secara konsisten meskipun sintaks memungkinkan Anda untuk menulis pernyataan SELECT yang menggabungkan pengambilan baris terurut dengan penetapan variabel.

Contoh 2

Perilaku yang Anda lihat adalah berdasarkan desain. Menggunakan operasi penugasan (penggabungan dalam contoh ini) dalam kueri dengan klausa ORDER BY memiliki perilaku yang tidak ditentukan. Ini dapat berubah dari rilis ke rilis atau bahkan dalam versi server tertentu karena perubahan dalam rencana kueri. Anda tidak dapat mengandalkan perilaku ini meskipun ada solusi. Lihat artikel KB di bawah ini untuk detail selengkapnya:
http://support.microsoft.com/kb/287515 HANYA mekanisme yang dijamin adalah sebagai berikut:

  1. Gunakan kursor untuk mengulang baris dalam urutan tertentu dan menggabungkan nilai
  2. Gunakan untuk kueri xml dengan ORDER BY untuk menghasilkan nilai gabungan
  3. Gunakan agregat CLR (ini tidak akan bekerja dengan klausa ORDER BY)

Contoh 3

Perilaku yang Anda lihat sebenarnya dirancang. Ini ada hubungannya dengan SQL menjadi bahasa manipulasi set. Semua ekspresi dalam SELECTlist (dan ini juga termasuk tugas) tidak dijamin akan dieksekusi tepat satu kali untuk setiap baris keluaran. Faktanya, SQL queryoptimizer berusaha keras untuk mengeksekusinya sesedikit mungkin. Ini akan memberikan hasil yang diharapkan ketika Anda menghitung nilai variabel berdasarkan beberapa data dalam tabel, tetapi ketika nilai yang Anda tetapkan bergantung pada nilai sebelumnya dari variabel yang sama, hasilnya mungkin sangat tidak terduga. Jika pengoptimal kueri memindahkan ekspresi ke tempat yang berbeda di pohon kueri, itu mungkin akan dievaluasi lebih sedikit (atau hanya sekali, seperti dalam salah satu contoh Anda). Inilah mengapa kami tidak menyarankan penggunaan penetapan jenis "iterasi" untuk menghitung nilai agregat. Kami menemukan bahwa solusi berbasis XML ... biasanya bekerja dengan baik untuk pelanggan

Contoh 4

Bahkan tanpa ORDER BY, kami tidak menjamin bahwa @var =@var +akan menghasilkan nilai gabungan untuk pernyataan apa pun yang memengaruhi banyak baris. Sisi kanan ekspresi dapat dievaluasi sekali atau beberapa kali selama eksekusi kueri dan perilaku seperti yang saya katakan bergantung pada rencana.

Contoh 5

Penetapan variabel dengan pernyataan SELECT adalah sintaks berpemilik (hanya T-SQL) di mana perilaku tidak ditentukan atau bergantung pada rencana jika beberapa baris diproduksi. Jika Anda perlu melakukan penggabungan string, gunakan agregat SQLCLR atau FOR XML query based concatenation atau metode relasional lainnya.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Perbedaan antara database dan skema

  2. T-SQL trim   (dan karakter non-alfanumerik lainnya)

  3. Mengubah kolom:null menjadi bukan null

  4. Cara terhubung ke database server SQL dari aplikasi Windows 10 UWP

  5. nvarchar(maks) vs NText