Kayıt durumları nasıl saklanır (beklemede, tamamlandı, taslak, iptal edildi…)


19

Oldukça fazla uygulama tablolarında kayıtların 'tamamlandı', 'taslak', 'iptal edildi' gibi bir duruma sahip olmasını gerektirir. Bu durumları depolamanın en iyi yolu nedir? Burada ne elde etmek göstermek için * çok kısa) bir örnektir.

Basit bir Blog uygulamam var ve her gönderinin bir durumu var: yayınlandı, taslak veya beklemede.

Ben bunu görmek veritabanında bu modellemek için 2 yolu vardır.

  1. Post tablosunda durum metnini içeren bir metin alanı vardır.
  2. Post tablosunda, PostStatus tablosundaki bir kaydın kimliğini içeren bir durum alanı vardır

Buradaki Blog örneği çok basit bir örnektir. Bir numaralandırma (destekleniyorsa) yeterli olabilir. Ancak, durumların listesinin herhangi bir zamanda değişebileceğini dikkate almak için soruya verilen yanıtları istiyorum, bu yüzden daha fazla eklenebilir veya kaldırılabilir.

Herkes her birinin avantajlarını / dezavantajlarını açıklayabilir mi?

Şerefe!

Bu benim ilk tercihim, başka bir tablo kullanmak ve durumu normalleştirme için daha iyi olarak aramak daha iyi ve her zaman normalleştirmenin veritabanları için iyi olduğu öğretildi



"Herhangi bir zamanda" ile ne demek istiyorsun? Bu, kullanıcı etkinliğinin bir parçası mı, yoksa yazılım yayın döngüsünün bir parçası mıdır?
kevin cline

Her ikisi de, hangi durumlarda burada en iyi kullanılan yaklaşımlardan herhangi biri. Kullanıcılar yeni durumlar ekleyebiliyorsa veya projenin sonraki bir noktasına yenileri eklenirse
veganista

Metnin veritabanında depolanması iyi bir denormalizasyon olabilir. Kesin ayrıntılara bağlı olabileceğini düşünüyorum, örneğin kuruluşunuz süreçlerini ne sıklıkla değiştiriyor (olası durum değişikliklerine yol açıyor)?
Jaydee

Kullanıcılar yeni durumlar ekleyebiliyorsa, bu tamamen başka bir şeydir. Muhtemelen durum ile yaratan kullanıcı vb. Kaydetmek isteyeceksiniz ve kesinlikle başka bir tabloya ihtiyacınız olacak.
kevin cline

Yanıtlar:


14

Durumun başka bir tabloya indeks olarak kaydedilmesi gereksiz bir komplikasyondur. Durumu doğrudan tabloda okunabilir bir şekilde saklayın. Uygulama kodunda sabitleri veya numaralandırma türünü kullanın. Bu, daha basit uygulama koduyla sonuçlanacak ve veri katmanında hata ayıklamayı kolaylaştıracaktır.

Bu verileri denormalize etmez, sadece gösterimi değiştirir. Veritabanı numaralandırmaları doğrudan destekliyorsa, bunu kullanın. Aksi takdirde sütun değerlerini kısıtlamak için bir kısıt kullanın. Her iki şekilde de bir kısıtlamanız olacaktır: sütun değerleri üzerinde doğrudan bir sınırlama veya bir yabancı anahtar kısıtlaması.

Evet, durumu farklı kullanıcılara farklı göstermeniz gerekebilir. Bu, kalıcılık katmanında değil, sunum katmanında çözülmesi gereken bir sunum problemidir.


1
+1, db'de durumların listesini tutmak için belirli bir ihtiyacı kısıtlamak , bu genellikle bunu yapmanın en basit, en az karmaşık yoludur.
GrandmasterB

2
Durum mimarisini değiştirmeye veya mutasyon tarihlerini saklamaya başlamadığınız sürece sorun yok
LastTribunal

10

Durum metnini saklamak IMO iyi bir fikir değildir, çünkü birisi bunun yerine "tamamlandı" olarak adlandırılması gerektiğine karar verebilir ve veritabanınızı güncellemeniz, birisi metni kodladıysa programa bakmanız gerekir.

Birçok programda gördüklerim ya sayısal bir kod (1 = yeni, 2 = taslak, 3 = doğrulamada, 4 = tamamlandı, 99 = iptal edildi) ya da kısa bir alfasayısal kod ("YENİ", "DRA", "INV "," COM "," CAN "). Daha sonra kodu (programda veya veritabanında) daha insan tarafından okunabilir hale getirir, bu genellikle iyi bir şeydir. Diğer yandan, sayısal kodlar "büyüktür" veya "küçüktür" karşılaştırmaları yapmayı kolaylaştırır, örneğin

select * from myrecords where status < Status.Complete;

Bazı salak da kimliği zorlayabilir.
Morons

Kimliklerin bir diğer avantajı da yerelleştirme sağlamanızdır. Kaynak dizesini ve görüntüyü aramak için kimliğinizi kullanabilirsiniz. Sabit kodlu dizelerle bu mümkün değildir
12'de armitage

3
Gösterdiğiniz gibi "büyüktür" veya "küçüktür" karşılaştırmaları kullanarak durumları yapmak iyi bir fikir olduğunu düşünmüyorum. Bu örnek gibi daha basit uygulamalar için işe yarayabilir, ancak daha karmaşık uygulamalar için iyi değildir (bunun farkında olduğunuzdan eminim)
veganista

1
@armitage: dizeleri kullanarak arama yapmak mükemmel bir şekilde mümkündür. Kaynak adları dizeler:status.draft=Draught
kevin cline

veganista: Tabii, karşılaştırmalardan daha büyük / daha küçük zorluklarla karşılaşabilirsiniz, ancak bunu yapan ve yaşayan büyük, karmaşık sistemler gördüm.
user281377

4

İlişkisel veritabanlarının üç kuralı:

  1. Normale
  2. Normale
  3. Normale

Yani sorunuz kendi kendine cevap veriyor. Durumu kendi tablosunun içinde tutun ve kimliğiniz olarak GUID / UUID'leri kullanın . Endeksli GUIDS çok hızlıdır ve artan sayılara özgü problemleri çözer. Bir kimlik ile kimliği kullanarak tüm tamamlanmış gönderiler için DB isteyin gibi serin şeyler yapabilirsiniz ve ilişkisel db paradigması içinde çalıştığınız için, çok hızlı. Sadece bir alanınız varsa, DB her satırda döngü yapmalı ve bir metin karşılaştırması yapmalıdır, belki de munging ile ve bu çok yavaştır.

Gönderi durumu adları değişebilir, gönderi durumu hakkında daha fazla bilgi tabloya girebilir, normalleşirseniz her şey çalışır .

Örneğin, ek cephane olarak karşılaştırma cephanesi bahsine izin veren durum seviyeleri ekleyebilirsiniz. Ancak, konumlandırma anahtarına bağlı değildir ve DB bütünlüğüne zarar vermeden durum seviyesinin yeniden düzenlenmesine izin verir. Ayrıca otomatik düzeylendirme anahtarıyla ilişkili düzeyiniz varsa, ek düzeyler de ekleyebilirsiniz.


Burada belirttiğiniz nedenler tam olarak stajlarımı saklamak için başka bir tablo kullanmamın nedenleridir. Neden bu soruyu sordum ana nedeni bazen daha basit bir metin alanı kullanmak iyi olup olmadığını görmek için.
veganista

@Liam Yalnızca bir metin alanına normalleşirse. Diğer bir deyişle, metin alanınız yalnızca birincil anahtara bağlıysa ve metin alanına eşlik eden şeyleri birincil anahtara göre ararsanız . İlişkisel DB ilişkilerle ilgilidir, burada bir tane var, bu yüzden tanımlanması gerekiyor. Birkaç istisnadan biri, dış verileri kirli verilerle işliyor ve tamamen modellemek için zamanınız yoksa. Mümkünse bundan kaçının.
Spencer Rathbun

asla geri dönmeyecek GUID'leri yas tutan gözleri gizler
sq33G 15:12

"Üç ilişkisel veritabanı kuramı " yazmış olmalısınız . Teori her zaman pratik değildir. Durum kodunu doğrudan ilişkili olduğu kayıtta saklamak genellikle daha etkilidir. Kullanmak için aramanıza gerek yoksa, birleştirmeyi başka bir tabloya kaldırmak çok boşa harcanan bir işlemden tasarruf etmenizi sağlar.
Suncat2000

Tam tablo taramaları ve sütun türleri hakkında yanlış bilgi nedeniyle indirildi.
igorrs

3

Evet, PostStatus tablosuna sahip olan 2. seçeneğe gitmelisiniz.

Diğer cevaplarda belirtilen tüm avantajların dışında.

Durumların eklenmesi veya kaldırılması gerektiğini göz önünde bulundurarak, PostStatus tablosunda "etkin" bir sütununuz olabilir, bu nedenle durum kaldırılırsa "etkin" sütunu "N" olarak işaretleyin, böylece durum ekleme veya kaldırma ve ayrıca mevcut kayıtlar sorunsuz kalır.


1

Tam normalleştirme için, bir varlığın durumundaki bir değişikliğin aslında ayrı bir varlıkta, örneğin 'statusChange' olarak modellenmiş olduğu anlayışlı cevaplara eklemek istiyorum.

StatusChange varlığıyla ekstra bir birleşim yapmanız gerekir, ancak değişikliği yapan aktör, değişikliğin neden oluştuğuna dair olası yorumlar ve statusChange'in gerçekleştirildiği tarih ve hatta muhtemelen etkili olur.


0

Kayıt tablosunda durum için metin kullanmak muhtemelen iyi bir fikir olmayabilir, çünkü bu değişebilir ve ekleme / güncelleme üzerinde herhangi bir veri bütünlüğü kontrolü yapmak zor olacaktır. Numaralandırma veri türüne sahip bir DBMS kullanıyorsanız, bunun yerine bunu kullanabilirsiniz (muhtemelen performanstan ödün verilmeyecektir ... bağlı olarak).

Durumunuzda herhangi bir meta veri gerekiyorsa (açıklama, tarafından oluşturulmuş açıklama, kolay ad, ...) durumları ayrı bir tabloda depolamanız ve kayıt tablonuzda bir durum anahtarına sahip olmanız gerekir (yabancı anahtar kullandığınızdan emin olun). Kimlik mutlaka bir sayı olmak zorunda değildir, yalnızca durum tablosunun PK'sidir. Ayrıca, durumlar kendi tablolarındaysa bunları varsa kayıt türleriyle (tablolar) paylaşabilirsiniz. Durum tablosuna bir JOIN ile performans sorunları hakkında endişe olmaz.

Ne yaparsanız yapın, sihirli durumlardan kaçının (aktif için 1, silinmiş için 2, ...). Bu, her zaman yeterince geniş bir zaman çizelgesinde kaybolma eğilimi gösteren dokümantasyon ve geleneğe dayanır. Nümerik kimlikleri kullanıyorsanız, db'nizin herhangi bir yerinde bir metin ilişkilendirmesi olduğundan emin olun.


Performans konusunda endişelenmiyorsanız, ölçeklenebilirlikten ödün veriyorsunuz. Bilgisayarların sihirli durumlardan kaçınması imkansızdır: 0 ve 1 kendiliğinden büyülüdür.
Suncat2000

0

Veritabanı tasarımının amacına bağlıdır.

Veritabanını uygulamayı destekleyecek şekilde tasarlarsanız (yani nesneler (kod) her şeyin efendisiyse) bir numaralandırma (veya desteklemeyen sınıflar için bir psuedo numaralandırma) kullanarak ve numaralandırma adını saklamak bir iyi bir fikir, çünkü hala numaralandırma aracılığıyla izin verilen değerleri kontrol ve ayrıca ham verileri görüntülemek zorunda kaldığınızda tabloyu okumak için biraz daha kolay hale getirir (kod gerçekten tüm kurallar bu sık sık değil). Ancak numaralandırma işaretlenirse. Sonra genellikle enum değerini (tamsayı) saklarım.


-1

Durum çok önemlidir, posta bilgisini her aldığınızda durumunu almanız gerekir veya yayınları duruma göre filtrelemek istersiniz. Başka bir tabloda durumunuz varsa, bu bilgiyi almak için birleştirme yapmanız gerekir ve böylece performans tehlikeye girer. Kesinlikle aynı tabloda durumunuz olmalıdır. Ve üzerine bir indeks koy! Hala tamsayı durum veya belki numaralandırma alanı olarak kullanabilirsiniz.


-2

Doğru çözüm, CQRS ile bir Etkinlik Deposu / Kaynağı veya bir blok zinciri kullanmaktır. RDB'deki olayları yakalamadaki sorun, RDB'nin tek bir olayın anlık görüntüsünü zamanında depolaması ve "Durumlar / Durumlar" gibi şeylerin zamanla gelişen mutasyonlar dizisidir.


Eğer görevimi oylayacaksanız, bir dava açın.
Yoksa
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.