Varchar değerinin eşit karşılaştırmada otomatik karşılaştırılması ancak karşılaştırma gibi değil


13

Bugün birisinin açıklayabileceğini umduğum SQL Server'da (2005 ve 2012'de gözlemlenen) bazı ilginç davranışlarla karşılaştım.

Bir =NVARCHAR alanını kullanarak karşılaştırma yapan bir sorgu , dizedeki arka boşluğu yok saydı (veya karşılaştırma öncesi değeri otomatik olarak kırptı), ancak likeişleci kullanan aynı sorgu alanı yok saymadı. Kullanılan harmanlama 2012 yılında Latin1_General_CI_AS şeklindedir.

Bu SQL Fiddle'ı düşünün: http://sqlfiddle.com/#!6/72262/4

likeİşlecin, sondaki boşluk dizesi için bir sonuç döndürmediğini, ancak =işleci döndürdüğünü unutmayın . Bu neden?

Bonus puanları: Bunu bir VARCHAR alanında kopyalayamıyorum, her iki veri türünde de bir alanın aynı şekilde ele alınacağını düşünürdüm - bu doğru mu?


Bir dize kesilmiş bir kontrol kısıtlaması yazmak için bakıyordu. Bu blogdaMyString+'x' = ltrim(rtrim(MyString))+'x' önerildiği gibi kontrol etmek için bir geçici çözüm buldum
default.kramer

Yanıtlar:


15

İlk cevabım, OFF olarak ayarlanmış ANSI_PADDING bayrağının davranıştaki farktan dolayı sorumlu olabileceğini ileri sürdü. Ancak, bu yanlış; bu bayrağın depolama üzerinde etkisi vardır, ancak eşitlik karşılaştırması yoktur.

Aradaki fark Microsoft'un SQL standardını uygulamasından kaynaklanıyor . Standart, eşitliği kontrol ederken , eşitlik operatörünün sol ve sağ tarafındaki her iki dizginin de aynı uzunlukta olması için doldurulması gerektiğini belirtir . Bu aşağıdaki sonuçları açıklar:

insert into test_padding (varchar_clmn, nvarchar_clmn) values ('space ', 'nspace ')
go
-- equality for varchar column
select count(*) from test_padding where varchar_clmn = 'space' -- returns 1
select count(*) from test_padding where varchar_clmn = 'space ' -- returns 1
select count(*) from test_padding where varchar_clmn = 'space    ' --returns 1
-- equality for nvarchar column
select count(*) from test_padding where nvarchar_clmn = 'nspace' -- returns 1
select count(*) from test_padding where nvarchar_clmn = 'nspace ' -- returns 1
select count(*) from test_padding where nvarchar_clmn = 'nspace    ' --returns 1

LIKE operatörü işlenenlerini doldurmaz. Ayrıca sütun türleri VARCHARve NVARCHARsütun türleri için farklı davranır :

-- likeness for varchar column
select count(*) from test_padding where varchar_clmn like 'space' -- returns 1
select count(*) from test_padding where varchar_clmn like 'space ' -- returns 1
select count(*) from test_padding where varchar_clmn like 'space    ' -- returns 0
-- likeness for nvarchar column
select count(*) from test_padding where nvarchar_clmn like 'nspace' -- returns 0
select count(*) from test_padding where nvarchar_clmn like 'nspace ' -- returns 1
select count(*) from test_padding where nvarchar_clmn like 'nspace    ' -- returns 0

ASCII türü için LIKE işlecinin davranışı SQL Server'a özgüdür; Unicode tipi için ANSI uyumludur.


4

Çoğu veri işleme dili her alan / değişken için sabit uzunluklar kullandığında SQL bir çağda doğmuştur. Fazla alan içeren metin alanlarının otomatik olarak doldurulması da bu resmin bir parçasıydı. Bu davranışla aynı hizaya gelmek için, orijinal SQL CHAR türü, '=' operatörü için arka boşlukları yoksaymak üzere açıkça tanımlanmıştır. (Bu garip bulursanız, bana bir metne eklenen boşlukların gerçek iş anlamının olduğu çekici bir durum gösterin .)

SQL CHAR türleri o zamandan beri her türlü yönde gelişmiştir, ancak bazı daha modern veri türlerinin hala bazı karakterleri tarihsel öncüllerinden miras almış olduğu düşünülemez.


"bir metne eklenen boşlukların gerçek iş anlamının olduğu cazip bir durum göster" - belirli ham konsol çıktısı ve güvenli olmayan XML parçaları gibi boşluk açısından önemli verileri depolamak.
Dai

1

LIKE (Transact-SQL) belgelerinde Microsoft şöyle yazmaktadır (benimkini vurgulayın):

LIKE Kullanarak Kalıp Eşleştirme

LIKE, ASCII kalıp eşleşmesini ve Unicode kalıp eşleşmesini destekler. Tüm argümanlar ... ASCII karakter veri tipleri olduğunda, ASCII desen eşleştirme gerçekleştirilir. Bağımsız değişkenlerden herhangi biri Unicode veri türündeyse, tüm bağımsız değişkenler Unicode'a dönüştürülür ve Unicode kalıp eşleşmesi gerçekleştirilir. Unicode verilerini LIKE ile kullandığınızda, sondaki boşluklar önemlidir; ancak, Unicode olmayan veriler için, sondaki boşluklar önemli değildir. Unicode LIKE, ISO standardıyla uyumludur. ASCII LIKE, SQL Server'ın önceki sürümleriyle uyumludur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.