“Boş veya boş değer” kontrol etmenin en iyi yolu


176

Postgres sql ifadelerinde değerin null veya boş dize olup olmadığını kontrol etmenin en iyi yolu nedir?

Değer uzun ifade olabilir, bu nedenle kontrolde yalnızca bir kez yazılması tercih edilir.

Şu anda kullanıyorum:

coalesce( trim(stringexpression),'')=''

Ama biraz çirkin gözüküyor.

stringexpressionchar(n)sütun veya char(n)sondaki boşluklu sütunlar içeren ifade olabilir .

En iyi yol nedir?


3
charDolgu (ve sonuçta alan israfı) nedeniyle kullanmak neredeyse her zaman yanlış seçimdir. Ama bunun dışında: Daha iyi bir çözüm olduğunu sanmıyorum.
a_horse_with_no_name

Neden çirkin? Mantıksal ve okunaklı.
klin

1
@a_horse_with_no_name: Bence var.
Erwin Brandstetter

Yanıtlar:


283

İfade şu sonuçları stringexpression = ''verir:

TRUE   .. için ''(veya yalnızca veri türüne sahip boşluklardan oluşan herhangi bir dize   için char(n))
NULL.. için NULL
FALSE .. başka bir şey için

Bu yüzden kontrol etmek için: " stringexpressionboş veya boş" :

(stringexpression = '') IS NOT FALSE

Veya tersine yaklaşım (okunması daha kolay olabilir):

(stringexpression <> '') IS NOT TRUE

Dahil herhangi bir karakter türü için çalışır char(n). Karşılaştırma operatörleri kılavuzu.

Veya orijinal ifadenizi kullanmayın trim(), bu maliyet char(n)düşüktür (aşağıya bakın) veya diğer karakter türleri için yanlıştır: yalnızca boşluklardan oluşan dizeler boş dize olarak geçer.

coalesce(stringexpression, '') = ''

Ancak üstteki ifadeler daha hızlıdır.

Aksini iddia etmek daha da basittir: " stringexpressionne NULL ne de boş" :

stringexpression <> ''

hakkında char(n)

Bu, veri türüyle ilgilidir char(n): kısaltması character(n). ( char/ characterİçin kısa char(1)/ ' character(1).) Kullanımı edilir Postgres cesaretini :

Çoğu durumda textveya character varyingbunun yerine kullanılmalıdır.

Karıştırmayın char(n)diğer yararlı, karakter tipleri varchar(n), varchar, textveya"char" (çift tırnak).

Gelen char(n)bir boş bir dizge , boşluklar oluşan her hangi bir başka dizisinden farklı değildir. Bunların tümü , tip tanımına göre n boşluğa katlanır char(n). Yukarıdaki ifadelerin char(n)de aynı şekilde (diğer karakter türleri için işe yaramayacak kadar) işe yaradığı mantıklı bir şekilde sonuçlanır:

coalesce(stringexpression, '  ') = '  '
coalesce(stringexpression, '') = '       '

gösteri

Boş dize, şuraya verildiğinde boşluk dizesine eşittir char(n):

SELECT ''::char(5) = ''::char(5)     AS eq1
     , ''::char(5) = '  '::char(5)   AS eq2
     , ''::char(5) = '    '::char(5) AS eq3;

Sonuç:

 eq1 | eq2 | eq3
 ----+-----+----
 t   | t   | t

Şununla "boş veya boş dize" için test yapın char(n):

SELECT stringexpression 
     , stringexpression = ''                   AS base_test
     , (stringexpression = '')  IS NOT FALSE   AS test1
     , (stringexpression <> '') IS NOT TRUE    AS test2
     , coalesce(stringexpression, '') = ''     AS coalesce1
     , coalesce(stringexpression, '  ') = '  ' AS coalesce2
     , coalesce(stringexpression, '') = '  '   AS coalesce3
FROM  (
   VALUES
     ('foo'::char(5))
   , ('')
   , ('   ')                -- not different from '' in char(n)
   , (NULL)
   ) sub(stringexpression);

Sonuç:

stringexpression | base_test | test1 | test2 | birleşme1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 foo | f | f | f | f | f | f
                  | t | t | t | t | t | t
                  | t | t | t | t | t | t
 null              | null       | t | t | t | t | t

Şununla "boş veya boş dize" için test yapın text:

SELECT stringexpression 
     , stringexpression = ''                   AS base_test
     , (stringexpression = '')  IS NOT FALSE   AS test1
     , (stringexpression <> '') IS NOT TRUE    AS test2
     , coalesce(stringexpression, '') = ''     AS coalesce1
     , coalesce(stringexpression, '  ') = '  ' AS coalesce2
     , coalesce(stringexpression, '') = '  '   AS coalesce3
FROM  (
   VALUES
     ('foo'::text)
   , ('')
   , ('   ')                -- different from '' in a sane character types
   , (NULL)
   ) sub(stringexpression);

Sonuç:

stringexpression | base_test | test1 | test2 | birleşme1 | coalesce2 | coalesce3
------------------ + ----------- + ------- + ------- + --- -------- + ----------- + -----------
 foo | f | f | f | f | f | f
                  | t | t | t | t | f | f
                  | f | f | f | f | f | f
 null              | null       | t | t | t | t | f

db <> keman burada
Eski sqlfiddle

İlişkili:


2
@a_horse_with_no_name: OP ister best way to check if value is null or empty string. trim()Ve sadece gerekli değildir - çağrı (nispeten) pahalıdır. Hakkında daha fazla şey ekledim char(n)ve "boş dize".
Erwin Brandstetter

1
Yalnızca boşluk içeren herhangi bir dize ifadesinin eşit olduğunu yazdınız ''. Döşemeyi çıkarabilir ve coalesce(stringexpression,'')=''kontrol etmek için kullanabilir miyim . Bu, cevabınıza göre bana daha okunabilir görünüyor.
Andrus

1
@Andrus: Evet, yapabilirsin. Cevaba bunu ve biraz daha fazlasını ekledim.
Erwin Brandstetter

3
select coalesce(' ', '') = '' yanlış döndürür. TRIM () gereklidir
Andrus

1
Ama coalesce(' '::char(5), '') = ''değil. Her halükarda en iyi iki ifadeden birini kullanırım, bu da herhangi bir karakter türü için çalışır ve en hızlı ve en temizdir.
Erwin Brandstetter

46

Boş ve boş olup olmadığını kontrol etmek için:

coalesce(string, '') = ''

Boş, boş ve boşluk olup olmadığını kontrol etmek için (ipi kırpın)

coalesce(TRIM(string), '') = ''

3
Bu cevabın basitliğini / netliğini seviyorum.
stwr667

12

Dizenin uzunluğunu kontrol etmek de çalışır ve kompakttır:

where length(stringexpression) > 0;

Bunu NULL vakası için kontrol ettin mi?
Flinsch

1
Evet yaptım. Boş veya boş dize alanları döndürmez.
yglodt

Sadece boş değerleri kontrol etmeniz gerekiyorsa, bunu deneyin -> where length(stringexpression) = 0;. Bu benim için çalışıyor.
Kushan Gunasekera

2

Boş arka boşluklar varsa, muhtemelen daha iyi bir çözüm yoktur. COALESCEsadece sizinki gibi problemler içindir.


1

İnsanların kullandığını gördüğüm bir şey stringexpression > '' . Bu en hızlı olmayabilir, ancak en kısa olanlardan biri olur.

MS SQL ve PostgreSQL üzerinde denedim.



0

Null alanlarını karşılaştırmak için tercih ettiğim yol: NULLIF (nulllablefield,: ParameterValue) IS NULL AND NULLIF (: ParameterValue, nullablefield) IS NULL. Bu hantal ama evrensel kullanımdayken, Coalesce bazı durumlarda imkansız.

NULLIF'in ikinci ve ters kullanımı, ilk parametre null olduğunda "NULLIF (boş alan,: ParameterValue) IS NULL" her zaman "true" döndürür.


0

Çok sayıda kayda sahip veritabanı null checkdaha fazla zaman alabilirse, null kontrolü aşağıdaki gibi farklı şekillerde kullanabilirsiniz: 1) where columnname is null 2) where not exists() 3)WHERE (case when columnname is null then true end)


0

Bir çok yanıt en kısa yoldur, sütunun çok sayıda boş değeri olması gerekiyorsa mutlaka en iyi yol değildir. Kontrolleri kaldırmak, optimize edicinin diğer şartlarda çalışması gerekmediğinden kontrolü daha hızlı değerlendirmesini sağlar.

(stringexpression IS NOT NULL AND trim(stringexpression) != '')

İlk koşul yanlış olduğundan dize karşılaştırmasının değerlendirilmesi gerekmez.

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.