SQL Server veritabanında Tek Sıralı yapılandırma tablosu kullanma. Kötü bir fikir?


145

Bir alışveriş sepeti uygulaması geliştirirken, yöneticinin tercihlerine ve gereksinimlerine göre ayarları ve yapılandırmaları kaydetmem gerektiğini buldum. Bu bilgiler şirket bilgileri, Gönderim hesabı kimlikleri, PayPal API anahtarları, bildirim tercihleri ​​vb.

İlişkisel bir veritabanı sisteminde tek bir satırı saklamak için bir tablo oluşturmak son derece uygun görünmemektedir.

Bu bilgileri depolamanın uygun yolu nedir?

Not: DBMS'im SQL Server 2008'dir ve programlama katmanı ASP.NET (C # ile) ile uygulanır.

Yanıtlar:


189

Geçmişte bu iki yolu yaptım - tek sıralı bir tablo ve bir anahtar / değer çifti tablosu - ve her yaklaşım için olumlu ve olumsuzlar var.

Tek Sıra

  • pozitif: değerler doğru tipte saklanır
  • pozitif: kodla uğraşmak daha kolaydır (yukarıdakiler nedeniyle)
  • pozitif: her ayara ayrı ayrı varsayılan değerler verilebilir
  • negatif: yeni bir ayar eklemek için şema değişikliği gerekiyor
  • negatif: Çok sayıda ayar varsa tablo çok geniş olabilir

Anahtar / Değer Çifti

  • pozitif: yeni ayarlar eklemek şema değişikliği gerektirmez
  • pozitif: tablo şeması dar, yeni ayarlar için fazladan satırlar kullanılıyor
  • negatif: her ayar aynı varsayılan değere sahiptir (boş / boş?)
  • negatif: her şey dize olarak saklanmalıdır (örn. nvarchar)
  • negatif: Koddaki ayarlarla uğraşırken, bir ayarın ne tür olduğunu bilmeniz ve yayınlamanız gerekir

Tek sıra seçeneği, çalışmak için en kolay seçenek. Bunun nedeni, her ayarı veritabanında doğru türde saklayabilmeniz ve ayar türlerinin yanı sıra arama anahtarlarını kodda saklamanız gerekmemesidir.

Bu yaklaşımı kullanmakla ilgilendiğim bir şey, "özel" tek sıra ayarları tablosunda birden çok satır olmasıydı. Ben (SQL Server'da) tarafından üstesinden geldi:

  • varsayılan değeri 0 olan yeni bir bit sütunu ekleme
  • bu sütunun 0 değerine sahip olduğundan emin olmak için bir kontrol kısıtlaması oluşturma
  • bit sütununda benzersiz bir kısıtlama oluşturma

Bu, bit sütununun 0 değerine sahip olması gerektiğinden tabloda yalnızca bir satır olabileceği anlamına gelir, ancak benzersiz kısıtlama nedeniyle bu değerle yalnızca bir satır olabilir.


5
LOB uygulamamızda tek satırlık şey yapıyoruz. Değerlerin hepsi doğru tiptedir, bu da onları uygulamada kullanmayı daha basit hale getirir. Şemamız uygulama ile birlikte sürümlendirilmiştir, bu nedenle yapılandırma kurulumundaki bir değişiklik tıpkı herhangi bir uygulama revizyonu gibi yönetilir.
DaveE

17
Tek satır pozitif: Bazı sütunlarda FK tanımlanmış olabilir!
wqw

8
Hangi sütunun değer türünde değere sahip olduğunu belirlemek için her zaman tür tanımlayıcılı bir anahtar / değer çifti yapabilirsiniz. Bu size her iki dünyanın en iyisini verir ve ihtiyaç duyduğunuzda değeri elde etmek için depolanmış bir proc kullanabilirsiniz.
Middletone

19
Gerçekten tek sıralı çözümünü uygulamadan sonra gününüzü berbat edebilir bir şey daha sonra görevli edildiğinde "adlı ayrıca her değeri değiştirildi ve kim .... değiştirdi son kez takip etme olanağı tanır" dır
Dave Mateer

6
Tek bir durumda bulduğum tek sıralı çözümün bir diğer avantajı: Bir istemci için, "ayarlar" için tek sıralı bir tablo ile oluşturulmuş bir uygulamam vardı. Daha sonra aynı uygulamayı kullanmak isteyen ancak farklı ayarlar isteyen iki istemcim daha vardı: tek yapmam gereken her istemci için ayrı bir ayar kümesi sağlamak için tabloya "client_id" PK eklemekti. (Bu, bu "ayarların" gerçekten henüz modellemediğiniz daha üst düzey bir varlığın özellikleri olduğunu anladığınızda.)
Jeffrey Kemp

10

Bilgi türü ve bilgi değeri (en azından) için sütun içeren bir tablo oluşturmalısınız. Bu şekilde, her yeni bilgi eklendiğinde yeni sütunlar oluşturmak zorunda kalmazsınız.


1
Basit ve temiz. Oradan anahtar değer çiftlerinin bir listesiyle çalışın. Varsayılan değerleri biraz düşünmek isteyebilirsiniz, kullanım bağlamına bağlıdır ...
Paul Kohler

4
Yeni sütunlar oluşturmak neden bir sorundur? SQL şemalarının güncellenmesi ile ilgili politik sorunlar nedeniyle geliştiricilerin bundan kaçınması gereken durumlar olduğunu biliyorum, ancak soruda bundan bahsedilmiyor.
finnw

6

Tek bir satır iyi çalışır; hatta güçlü türleri olacaktır:

show_borders    bit
admin_name      varchar(50)
max_users       int

Bir dezavantajı, alter tableyeni bir ayar eklemek için bir şema değişikliği ( ) gerektirmesidir . Alternatiflerden biri, aşağıdaki gibi bir tabloyla sonuçlandığınız normalleştirmektir:

pref_name       varchar(50) primary key
pref_value      varchar(50) 

Bu zayıf türlere sahiptir (her şey bir varchartır), ancak yeni bir ayar eklemek sadece bir satır eklemek, sadece veritabanı yazma erişimi ile yapabileceğiniz bir şey.


4

Şahsen, işe yarayan şeyse tek bir satırda saklayacağım. Bir SQL tablosunda saklamak için gereğinden fazla mı? muhtemelen, ama bunu yaparken gerçek bir zarar yoktur.


4

Tahmin ettiğiniz gibi ve en basit durumlar dışında, tüm yapılandırma parametrelerini tek bir satıra koymanın birçok dezavantajı vardır. Kötü bir fikir ...

Yapılandırma ve / veya kullanıcı tercihi türü bilgilerini saklamanın kolay bir yolu XML'dir . Birçok DBMS, XML veri türünü destekler. XML sözdizimi, bu yapılandırma geliştikçe yapılandırmayı açıklayan "dili" ve yapıyı harcamanıza olanak tanır. XML'in bir avantajı, hiyerarşik yapı için örtük desteğidir ve örneğin, bunları yapılandırılmış parametrelerin küçük bir listesini numaralandırılmış bir sonekle adlandırmak zorunda kalmadan depolamaya izin verir. XML formatının olası bir dezavantajı, bu verilerin aranması ve genellikle değiştirilmesinin diğer yaklaşımlar kadar basit olmamasıdır (karmaşık bir şey değildir, ancak basit / doğal değildir).

İlişkisel modele daha yakın kalmak istiyorsanız , Entity-Attribute-Value modeli muhtemelen ihtiyacınız olan şeydir, böylece bireysel değerler tipik olarak aşağıdaki gibi bir tabloda saklanır:

EntityId     (foreign key to the "owner" of this attribute)
AttributeId  (foreign key to the "metadata" table where the attribute is defined)
StringValue  (it is often convenient to have different columns of different types
IntValue      allowing to store the various attributes in a format that befits 
              them)

AttributeId, her olası Attribute (sizin durumunuzda "yapılandırma parametresi") tanımlanmış bir tablonun yabancı anahtarı olduğundan,

AttributeId  (Primary Key)
Name
AttributeType     (some code  S = string, I = Int etc.)
Required          (some boolean indicating that this is required)
Some_other_fields   (for example to define in which order these attributes get displayed etc...)

Son olarak EntityId, bu çeşitli niteliklere "sahip" bazı varlıkları tanımlamanıza izin verir. Sizin durumunuzda bir UserId olabilir, hatta yalnızca yönetilecek bir yapılandırmanız varsa örtük olabilir.

Uygulama geliştikçe olası yapılandırma parametrelerinin listesinin büyümesine izin vermenin yanı sıra, EAV modeli "meta verileri", yani Öznitelik ile ilgili verileri veri tablolarına yerleştirir, böylece yaygın olarak görülen sütun adlarının tüm kodlamasından kaçınır yapılandırma parametreleri tek bir satırda saklandığında.


3
Bir yapılandırma tablosunun çoğu kullanımı için aşırı doldurma gibi geliyor.
JerryOL

Bence bu yaklaşımın ardındaki genel fikir harika. Ama neden XML? Sadece JSON veya YAML gibi basit bir veri değişim formatı seçin ve diğer her iki varyasyondan da avantajlara sahip olabilirsiniz.
schlamar

1
EAV ilişkiseldir ancak normalize edilmemiştir. Bunun için kesinlikle kullanım örnekleri vardır (örneğin ORM sistemleri onları sevmektedir), ancak meta verilerin EAV için veritabanında olduğu iddiası, bunu kullanmak için ikna edici bir neden değildir. Tüm RDBMS, yine de bulabileceğiniz sistem tablolarında meta veriler içerir, bu nedenle tek satır tablolar da veritabanında meta verilere sahiptir. Sabit kodlanmış sütun adları da sorun değildir. Varlıklar ve öznitelikler için anahtarlar kullanırsanız, bunları tanımlayan başka bir yerde sabit kodlu bir arama tablonuz olur (veya sunum katmanınızda daha kötüdür).
Davos

3

Normalleştirilmiş yaklaşımda yeni bir yapılandırma parametresi eklerken şemanızı kesinlikle değiştirmeniz gerekmez, ancak yine de muhtemelen yeni değeri işlemek için kodunuzu değiştiriyorsunuzdur.

Dağıtımınıza bir "değiştirme tablosu" eklemek, tek sıralı yaklaşımın basitliği ve tür güvenliği için bir büyüklük gibi görünmüyor.


2

Bir Anahtar ve Değer çifti, yapılandırma ayarlarını saklayabilen bir .Net App.Config dosyasına benzer.

Yani değeri almak istediğinizde şunları yapabilirsiniz:

SELECT value FROM configurationTable
WHERE ApplicationGroup = 'myappgroup'
AND keyDescription = 'myKey';

1

Bunu yapmanın yaygın bir yolu, bir özellikler dosyasına simüle olan bir "özellikler" tablosuna sahip olmaktır. Burada tüm uygulama sabitlerinizi saklayabilir veya yalnızca sahip olmanız gereken sabit şeyleri saklayamazsınız.

Daha sonra bilgileri gerektiği gibi bu tablodan alabilirsiniz. Benzer şekilde, kaydetmek için başka bir ayarınız olduğunu fark ettiğinizde, ekleyebilirsiniz. İşte bir örnek:

property_entry_table

[id, scope, refId, propertyName, propertyValue, propertyType] 
1, 0, 1, "COMPANY_INFO", "Acme Tools", "ADMIN"  
2, 0, 1, "SHIPPING_ID", "12333484", "ADMIN"  
3, 0, 1, "PAYPAL_KEY", "2143123412341", "ADMIN"   
4, 0, 1, "PAYPAL_KEY", "123412341234123", "ADMIN"  
5, 0, 1, "NOTIF_PREF", "ON", "ADMIN"  
6, 0, 2, "NOTIF_PREF", "OFF", "ADMIN"   

Bu şekilde sahip olduğunuz verileri ve gelecek yıl sahip olacağınız ve henüz bilmediğiniz verileri saklayabilirsiniz :).

Bu örnekte, kapsamınız ve refD'niz arka uçta istediğiniz herhangi bir şey için kullanılabilir. Yani propertyType "ADMIN" kapsam 0 refId 2 içeriyorsa, bunun ne tercih olduğunu bilirsiniz.

Mülk türü, bir gün yönetici olmayan bilgileri burada da saklamanız gerektiğinde elinize geçer.

Alışveriş sepeti verilerini bu şekilde depolamamanız gerektiğini veya bu konuyla ilgili aramalar yapmayacağınızı unutmayın. Ancak veriler Sisteme özgü ise, bu yöntemi kesinlikle kullanabilirsiniz.

Örneğin: DATABASE_VERSION ürününüzü saklamak istiyorsanız , böyle bir tablo kullanırsınız. Bu şekilde, uygulamayı yükseltmeniz gerektiğinde, istemcinizin yazılımınızın hangi sürümüne sahip olduğunu görmek için özellikler tablosunu kontrol edebilirsiniz.

Mesele şu ki, bunu sepete ait şeyler için kullanmak istemiyorsunuz. İş mantığınızı iyi tanımlanmış ilişkisel tablolarda tutun. Özellikler tablosu yalnızca sistem bilgisi içindir.


@finnw Bu yöntemin aramalar için, özellikle de birçok farklı arama türü olduğunda kullanılmaması gerektiğine tamamen katılıyorum. Belki de soruyu yanlış anladım. Sabitler ve sistem özellikleri için bir masaya ihtiyacı vardı. Bu durumda neden 10 farklı masa var?
Stephano

not: "Ayarları ve konfigürasyonları kaydet" dedi, "İlişkisel alışveriş sepeti verilerini kaydetmem gerekiyor" dedi
Stephano

Buna itirazım, yeni özellikler eklediğinizde SQL şemasını güncellemekten kaçınmak için SQL'in yazımını ve diğer kısıtlama mekanizmalarını atlamanızdır. Dediğiniz gibi "gelecek yıl sahip olacağınız ve henüz bilmediğiniz veriler." Evet, gelecek yıl yeni verileriniz olacak, ancak eklendiği sırada yeni (yazılan) SQL sütunları, CHECK ve muhtemelen FOREIGN KEY kısıtlamaları oluşturmanızı engelleyecek ne var?
finnw

İlk içgüdüm bu verileri düz bir dosyaya eklemektir. Ve haklısınız, bunun yerine bir tablo kullanma işlemi aslında DBMS'nin kısıtlama mekanizmalarını atlatacaktır. Ancak, uygun veritabanı tekniklerini takip etmek çok zor denerseniz, noktayı eksik olduğunu söyleyebilirim. İlk cevaba göz atın; en çok SO'ya oy verdi: stackoverflow.com/questions/406760/…
Stephano

2
Anahtar değer çiftine giderdim, her şeyi başlangıçta bir sözlük içine döktüm ve sıraladınız.
Paul Creasey

0

Tek bir satırın yapılandırma için en iyi uygulama olduğundan emin değilim. Yapılandırma başına iki sütuna (configName, configValue) sahip bir satır bulundurmak daha iyi olabilir, ancak bu, tüm değerlerinizin dizelere ve arkaya dökülmesini gerektirecektir.

Ne olursa olsun, global yapılandırma için tek bir satır kullanmanın bir zararı yoktur. DB (global değişkenler) içinde saklamak için diğer seçenekler daha kötüdür. İlk yapılandırma satırınızı ekleyerek, ardından birden çok satırı önlemek için tablodaki eklemeleri devre dışı bırakarak kontrol edebilirsiniz.


0

Her bir ana tür için bir sütun ve verilerin hangi sütunda olduğunu bildiren bir sütun ekleyerek Anahtar / Değer Çifti'ni dönüşüm olmadan yapabilirsiniz.

Yani tablonuz şöyle görünecektir:

id, column_num, property_name, intValue, floatValue, charValue, dateValue
1, 1, weeks, 51, , ,
2, 2, pi, , 3.14159, , 
3, 4, FiscYearEnd, , , , 1/31/2015
4, 3, CompanyName, , , ACME, 

Biraz daha fazla alan kullanıyor ancak en fazla birkaç düzine özellik kullanıyorsunuz. Doğru alanı çekmek / birleştirmek için column_num değerinin dışında bir case deyimi kullanabilirsiniz.


0

Üzgünüm, geldim, yıllar sonra. Ama her neyse, yaptığım basit ve etkili. Ben sadece üç () sütun içeren bir tablo oluşturun:

Kimlik - int (11)

adı - varchar (64)

değer - metin

Yeni bir yapılandırma sütunu oluşturmadan, güncellemeden veya okumadan önce ne yaptığım "değer" serileştirmektir! Bu şekilde tür eminim (Peki, php :))

Örneğin:

b: 0; için B OOLEAN ( sahte )

b: 1 'dir; için B OOLEAN ( gerçek )

i: 1988; içindir I NT

s: 5: "Kader"; Bir için S 5 karakter uzunluğunda TRING

Umarım bu yardımcı olur :)


1
Neden yalnızca tür için yeni bir sütun oluşturmuyorsunuz? i:1988iki bilgiyi tek bir sütuna daraltmaya çalışıyorsunuz.
maksymiuk

Derhal bir kez serileştirilmediğinde (sonra veya anahtar) sonra bir döngü kullanmak yerine tam tip olsun ... vb
Kader Bouyakoub

herhangi bir döngüye veya anahtarlara veya herhangi bir şeye ihtiyaç duymazsanız, aslında her satırdaki bilgileri ayrıştırma adımını kaldıracaktır, oysa, tür için fazladan bir sütununuz varsa, bilgileri çeken bileşen için tür bilgisi zaten mevcuttur sadece ilk sorgudan başka adım yapmak zorunda kalmadan
maksymiuk

echo (int) $varBir tamsayı gibi bir şey ve diğer türler için diğerleri yaparak ne demek istiyorsun ?
Kader Bouyakoub

0

Varchar olarak bir anahtar sütun ve JSON olarak bir değer sütun var. 1sayısal, oysa "1"bir dizedir. trueve falseikisi de boolean. Nesneleriniz de olabilir.

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.