Sizce “empty string”, NULL’a eşit mi?
Bu sorunun cevabı, hangi veri tabanıyla çalıştığınıza bağlıdır. Peki, veri tabanı bağımsız bir uygulama geliştiriyorsanız sizi nelerin beklediğini biliyor musunuz?
Architecht’te global bir şirkete veri tabanı bağımsız bir bankacılık uygulaması geliştiriyoruz. Uçtan uca bir bankanın alt yapısını sağlayacak olan uygulamanın, geliştirme sürecinde hemen hemen her şeyin önceden düşünülmesi ve bu minvalde tasarlanması zaruridir.
Tahmin ettiğiniz üzere veri tabanı bağımsız bir uygulama geliştirirken birçok zorluklarla karşılaştık. Bunlardan bir tanesiyse empty string kullanımıydı.
Bu sorunu daha önce yaşamamış ve konuyu merak edenler için sorunun detaylarını ve olası çözümleri sizlerle paylaşacağım.
Empty string {”} SQL veri tabanında sorunsuz bir şekilde çalışmaktadır. Oracle veri tabanı ise empty string değerini NULL olarak kullanmaktadır. Eğer bu farklı davranış yönetilmezse, Oracle veri tabanını ve SQL veri tabanını aynı anda destekleyen uygulamalarda empty string veri tutarsızlığı sorununa neden olacaktır.
Bu yazımda, empty string kullandığımız kolonun veri tipinin (varchar, nvarchar gibi) string veri tipi olduğunu varsayıyorum. Diğer veri tipleri kapsam dışındadır. Ayrıca Oracle veri tabanı, kolonun NULLABLE olup olmamasına bağlı olarak farklı davranışlar sergilemektedir. Bu davranışı gelin detaylıca birlikte inceleyelim.
Oracle veri tabanında;
- Eğer, NOT NULL veri tipine sahip bir sütuna empty string eklenmek istenirse, Oracle “OracleException: ORA-01400: Cannot NULL into (“DB”.”TABLE”.”COLUMN”) hatası fırlatacaktır. Diğer bir değişle NOT NULL bir kolona empty string ekleyemiyoruz.
- Eğer string empty, NULLABLE bir kolona eklenir / güncellenirse, empty string değeri NULL’a çevrilerek eklenir / güncellenir.
Buradan, Oracle veri tabanında empty string konseptinin olmadığını ve empty string’e NULL gibi davranıldığını anlayabiliyoruz.
SQL server veri tabanında ise empty string sorunsuz bir şekilde eklenebiliyor, kullanılabiliyor ve sorgulanabiliyor. SQL server farklı konularda olduğu gibi bu konuda da daha esnek bir tutum sergiliyor.
Birinde Var Diğerinde Yok
Uygulamamızın her iki veri tabanıyla da çalışması lazım.
Ne yapacağız? Evet, veri tabanı bağımsız bir uygulama geliştiriyorsak empty string için özel önlemler almamız gerekecek.
O vakit, veri tabanları arasındaki farkı daha iyi anlamamız ve uygulamada kullandığımız ORM’in çalışma şeklini detaylıca incelememiz gerekiyor. Bu durumda ufak bir test çalışmasıyla konuyu detaylandırabiliriz.
Bildiğiniz üzere uygulamalarda ORM kullanımı yaygınlaştı. Çoklu veri tabanını desteklemek için de ORM kullanmak ideal bir çözüm. Geliştirmemizi NET Core üzerinde yaptığımızdan, biz de doğal olarak ORM için EF Core kullanmayı tercih ettik. Uyumlu ve anlaşılır olması için testleri de EF Core ile yaptım.
Test amaçlı PRODUCT isminde bir tablo oluşturdum. Tabloda, string değeri tutan biri NOT NULL ve biri NULLABLE olan iki ayrı kolon ekledim. Amacım, NULLABLE veya NOT NULL olma durumunda veri tabanlarının davranışlarını daha iyi gözlemlemek.
PRODUCT tablosunun şeması aşağıdaki gibi:
CREATE TABLE PRODUCT(
ID int IDENTITY(1,1) NOT NULL,
NAME VARCHAR(500) NOT NULL,
DETAIL NVARCHAR(1000) NULL,
CONSTRAINT PK_PRODUCT PRIMARY KEY CLUSTERED
(
ID ASC
) ON PRIMARY
) ON PRIMARY
Test amaçlı tabloya eklediğim kayıtlar konsol ekranında gözüktüğü gibi. Ekranın anlaşılabilir olması için ekran çıktısını EF Core’dan dönen Empty, NULL ve White Space değerlerine müdahale ederek oluşturdum. Normalde Console.WriteLine metodu bu değerlerin hepsini aynı şekilde, boşluk olarak gösteriyor.
Resimdeki kayıtlar, hem SQL server hem de Oracle veri tabanında mevcut.
Senaryo 1: NULLABLE bir kolona boş string ekleme ve okuma işleminin senaryosu.
Oracle veri tabanı empty string değerlerini NULL’a çevirip yazmakta ve empty string NULL gibi değerlendirilmektedir. Dolayısıyla okuma işlemi sırasında empty string ile birlikte NULL değerleri de getirilmektedir.
SQL server veri tabanı ise empty string ile White space karakterlerini eşit değerlendirmekte ve sorgu sonucunda her iki kaydı da getirmektedir.
Sadece empty string sorgulandığı durumlarda veri tabanları arasında bariz farklar oluşmaktadır.
Senaryo 2: NOT NULL kolonlara empty string yerine White space ekleme senaryosu.
Empty string yerine White space ekleyerek oluşturulan kayıtları IsNullOrWhiteSpace ile sorgulayalım.
Bu durumda veri tabanları aynı sonucu vermektedir. Ancak dikkat edilmesi gereken nokta şudur: Bu kayıtları ayrı ayrı elde etmek istersek yine sorun yaşarız.
Senaryo 3: NOT NULL sütununa White space ekleme ve sorgulama.
Sorgu her iki veri tabanında da doğru çalışıyor gözüküyor. Oracle tarafında eklenemeyen, hata alan ancak SQL veri tabanında eklenebilen empty string değeri SQL server tarafında sorguya dahil edileceğinden yine farklar oluşacaktır.
Senaryo 4: NULLABLE kolona emty string ekleme ve sorgulama.
SQL server veri tabanı White space’leri de empty string gibi değerlendireceğinden yine farklar oluşacaktır.
Bu aşamaya kadar sorunu tanımaya çalıştık. EF Core ile veri tabanlarına sorgular yaparak dönüş değerlerini inceledik. Empty string kullanımının bir sorun olduğu aşikâr. Şimdi, bu sorununun çözüm yollarını listeler halinde yazacağım. Her problemde olduğu gibi, benim fark etmediğim bir çözümü olabilir. Çözüm önerilerinizi iletirseniz yazımız daha da zenginleşecektir.
Çözümler
1- Uygulama seviyesinde empty string’leri NULL’a dönüştürmek ve eklemek.
EF Core üzerinde DbContext sınıfında, Empty string içeren veriler, ekleme / güncellemeden önce NULL olarak güncellenebilir. Bu durumda tüm sütunlar NULLABLE olmalıdır.
2- Uygulama seviyesinde empty string’leri, White space karakterlerine dönüştürmek.
NULL veriye çevirmek gibi ama veriyi işlerken daha zahmetli ve yeni kullanım alışkanlıkları gerektiriyor.
3- Tüm string verilere bir önek, özel bir karakter ekleme yöntemi.
Tüm string’lere önek eklenmesi durumunda empty string yalnızca ekten oluşacaktır, empty string için önek kontrol edilerek tespit edilebilir.
4- Empty string verisinin içerdiği kolonlara ek olarak verinin empty string olup olmadığını belirten bir kolon ekleme yöntemi.
Bu yöntemi buraya eklerken tepki alabilir miyim diye çok düşündüm ama farkındalık yaratmak için ekledim. Bana göre bu yöntem çözümler arasında en zahmetlisi gibi gözüküyor.
Biz nasıl mı çözdük? Şirket sırrı detaylarını paylaşamıyorum. 😊
Selametle.
Kaynak:
https://blog.joda.org/2014/09/oracle-rdbms-empty-string-null.html