Aplikasi kita perlu bekerja sama baiknya dengan database Oracle atau database Microsoft SQL Server. Untuk memfasilitasi ini, kami membuat beberapa UDF untuk menyeragamkan sintaksis kueri kami. Sebagai contoh, SQL Server memiliki GETDATE () dan Oracle memiliki SYSDATE. Mereka melakukan fungsi yang sama tetapi kata-kata mereka berbeda. Kami menulis pembungkus UDF yang disebut SEKARANG () untuk kedua platform yang membungkus sintaksis platform spesifik yang relevan dengan nama fungsi umum. Kami memiliki fungsi lain seperti itu, beberapa di antaranya pada dasarnya tidak ada tetapi hanya ada demi homogenisasi. Sayangnya, ini memiliki biaya untuk SQL Server. UDF skalar sebaris mendatangkan malapetaka pada kinerja dan sepenuhnya menonaktifkan paralelisme. Sebagai alternatif, kami menulis fungsi perakitan CLR untuk mencapai tujuan yang sama. Ketika kami menyebarkan ini ke klien, mereka mulai sering mengalami kebuntuan. Klien khusus ini menggunakan replikasi dan teknik ketersediaan tinggi dan saya bertanya-tanya apakah ada semacam interaksi yang terjadi di sini. Saya hanya tidak mengerti bagaimana memperkenalkan fungsi CLR akan menyebabkan masalah seperti ini. Sebagai referensi, saya telah memasukkan definisi skalar UDF asli serta definisi CLR pengganti di C # dan deklarasi SQL untuk itu. Saya juga memiliki kebuntuan XML yang bisa saya berikan jika itu membantu.
UDF asli
CREATE FUNCTION [fn].[APAD]
(
@Value VARCHAR(4000)
, @tablename VARCHAR(4000) = NULL
, @columnname VARCHAR(4000) = NULL
)
RETURNS VARCHAR(4000)
WITH SCHEMABINDING
AS
BEGIN
RETURN LTRIM(RTRIM(@Value))
END
GO
Fungsi Perakitan CLR
[SqlFunction(IsDeterministic = true)]
public static string APAD(string value, string tableName, string columnName)
{
return value?.Trim();
}
Deklarasi SQL Server untuk Fungsi CLR
CREATE FUNCTION [fn].[APAD]
(
@Value NVARCHAR(4000),
@TableName NVARCHAR(4000),
@ColumnName NVARCHAR(4000)
) RETURNS NVARCHAR(4000)
AS
EXTERNAL NAME ASI.fn.APAD
GO
sumber
Jawaban:
Versi SQL Server apa yang Anda gunakan?
Saya ingat melihat sedikit perubahan perilaku di SQL Server 2017 belum lama ini. Saya harus kembali dan melihat apakah saya dapat menemukan di mana saya membuat catatan itu, tapi saya pikir itu ada hubungannya dengan kunci skema yang dimulai ketika objek SQLCLR sedang diakses.
Sementara saya mencari itu, saya akan mengatakan hal berikut mengenai pendekatan Anda:
Sql*
tipe untuk parameter input, tipe kembali. Anda harus menggunakanSqlString
bukanstring
.SqlString
sangat mirip dengan string nullable (Andavalue?
, tetapi memiliki fungsi lain yang dibangun di dalamnya adalah SQL Server-spesifik. SemuaSql*
jenis memilikiValue
properti yang mengembalikan tipe .NET yang diharapkan (misalnyaSqlString.Value
pengembalianstring
,SqlInt32
pengembalianint
,SqlDateTime
pengembalianDateTime
, dll).Saya akan merekomendasikan terhadap seluruh pendekatan ini untuk memulai, apakah kebuntuan terkait atau tidak. Saya mengatakan ini karena:
VARCHAR
. Apakah Anda setuju dengan secara implisit mengubah segalanya menjadiNVARCHAR
dan kemudian kembali keVARCHAR
untuk operasi sederhana?NVARCHAR(4000)
danNVARCHAR(MAX)
:MAX
tipe (bahkan memiliki satu pun dari mereka dalam tanda tangan) membuat panggilan SQLCLR memakan waktu dua kali selama tidak memilikiMAX
jenis tanda tangan (saya percaya ini berlaku berlaku untukVARBINARY(MAX)
vsVARBINARY(4000)
juga). Jadi, Anda perlu memutuskan antara:NVARCHAR(MAX)
untuk memiliki API yang disederhanakan, tetapi ambil hit kinerja ketika Anda menggunakan 8000 byte atau kurang dari data string, atauMAX
tipe, dan satu tanpa (untuk saat Anda dijamin tidak akan pernah melewati 8000 byte data string masuk atau keluar). Ini adalah pendekatan yang saya pilih untuk mengambil sebagian besar fungsi dalam pustaka SQL # saya : adaTrim()
fungsi yang kemungkinan memiliki satu atau lebihMAX
tipe, danTrim4k()
versi yang tidak pernah memilikiMAX
tipe di mana pun dalam skema set tanda tangan atau hasil. Versi "4k" benar-benar lebih efisien.Anda tidak berhati-hati untuk meniru fungsionalitas yang diberikan contoh dalam pertanyaan.
LTRIM
danRTRIM
hanya memangkas ruang, sementara .NETString.Trim()
memangkas ruang putih (setidaknya ruang, tab, dan baris baru). Sebagai contoh:sumber