Zwykle projektuję swoje bazy danych według następujących zasad:
- Nikt inny niż db_owner i sysadmin nie ma dostępu do tabel bazy danych.
- Role użytkowników są kontrolowane na poziomie aplikacji. Zwykle używam jednej roli db, aby przyznać dostęp do widoków, procedur przechowywanych i funkcji, ale w niektórych przypadkach dodam drugą regułę, aby chronić niektóre procedury przechowywane.
- Używam TRIGGERS do początkowej weryfikacji ważnych informacji.
CREATE TRIGGER <TriggerName>
ON <MyTable>
[BEFORE | AFTER] INSERT
AS
IF EXISTS (SELECT 1
FROM inserted
WHERE Field1 <> <some_initial_value>
OR Field2 <> <other_initial_value>)
BEGIN
UPDATE MyTable
SET Field1 = <some_initial_value>,
Field2 = <other_initial_value>
...
END
- DML jest wykonywany przy użyciu procedur przechowywanych:
sp_MyTable_Insert(@Field1, @Field2, @Field3, ...);
sp_MyTable_Delete(@Key1, @Key2, ...);
sp_MyTable_Update(@Key1, @Key2, @Field3, ...);
Czy uważasz, że w tym scenariuszu warto użyć DOMYŚLNYCH OGRANICZEŃ, czy dodam dodatkową i niepotrzebną pracę do serwera DB?
Aktualizacja
Rozumiem, że używając ograniczenia DOMYŚLNEGO podaję więcej informacji komuś innemu, kto musi zarządzać bazą danych. Ale najbardziej interesuje mnie wydajność.
Zakładam, że baza danych sprawdza zawsze wartości domyślne, nawet jeśli podam prawidłową wartość, dlatego wykonuję to samo zadanie dwukrotnie.
Na przykład Czy istnieje sposób na uniknięcie ograniczenia DOMYŚLNEGO w ramach wykonania wyzwalacza?
sql-server
itsql
ponieważ kod w twoim pytaniu jest bardzo specyficzny dla tego DBMSOdpowiedzi:
Dlaczego miałbyś to założyć? ;-). Biorąc pod uwagę, że Domyślne istnieją, aby zapewnić wartość, gdy kolumna, do której są dołączone, nie jest obecna w
INSERT
instrukcji, zakładam, że jest dokładnie odwrotnie: są one całkowicie ignorowane, jeśli powiązana kolumna jest obecna wINSERT
instrukcji.Na szczęście żadne z nas nie musi niczego zakładać z powodu tego stwierdzenia w pytaniu:
Pytania dotyczące wydajności prawie zawsze można przetestować. Musimy więc wymyślić test, który pozwoli SQL Serverowi (tutaj prawdziwemu autorytetowi) odpowiedzieć na to pytanie.
USTAWIAĆ
Uruchom raz:
Testy 1A i 1B należy wykonywać osobno, a nie razem, ponieważ zniekształca to taktowanie. Uruchom każdy z nich kilka razy, aby poznać średnie czasy dla każdego z nich.
Test 1A
Test 1B
Testy 2A i 2B należy wykonywać osobno, a nie razem, ponieważ zmienia to czas. Uruchom każdy z nich kilka razy, aby poznać średnie czasy dla każdego z nich.
Test 2A
Test 2B
Powinieneś zobaczyć, że nie ma prawdziwej różnicy w czasie między testami 1A i 1B, ani między testami 2A i 2B. Więc nie, nie ma ograniczenia wydajności, które ma
DEFAULT
określone, ale nie jest używane.Poza dokumentowaniem zamierzonego zachowania należy również pamiętać, że to w głównej mierze zależy Ci na tym, aby instrukcje DML były całkowicie zawarte w procedurach przechowywanych. Ludzie wsparcia nie dbają. Przyszli programiści mogą nie zdawać sobie sprawy z twojego pragnienia, aby wszystkie DML były zawarte w tych procedurach przechowywanych, lub dbać o to, nawet jeśli wiedzą. A ktokolwiek utrzymuje tę bazę danych po twojej nieobecności (inny projekt lub zadanie), może się tym nie przejmować lub może nie być w stanie zapobiec użyciu ORM bez względu na to, ile protestuje. Tak więc, Defaults, może pomóc w tym, że dają ludziom „out” podczas robienia
INSERT
, zwłaszcza ad-hocINSERT
wykonywany przez przedstawiciela wsparcia, ponieważ jest to jedna kolumna, której nie trzeba uwzględniać (dlatego zawsze używam wartości domyślnych podczas audytu kolumny dat).I właśnie przyszło mi do głowy, że można raczej obiektywnie pokazać, czy a
DEFAULT
jest sprawdzane, gdy powiązana kolumna jest obecna wINSERT
instrukcji: po prostu podaj niepoprawną wartość. Poniższy test właśnie to robi:Jak widać, gdy
DEFAULT
podana jest kolumna (i wartość, a nie słowo kluczowe ), wartość domyślna jest w 100% ignorowana. Wiemy to, ponieważ się toINSERT
udaje. Ale jeśli zostanie użyta wartość domyślna, wystąpi błąd, ponieważ jest ona w końcu wykonywana.Chociaż potrzeba uniknięcia domyślnych ograniczeń (przynajmniej w tym kontekście) jest całkowicie niepotrzebna, dla zachowania kompletności można zauważyć, że możliwe byłoby „uniknięcie” domyślnego ograniczenia w ramach
INSTEAD OF
wyzwalacza, ale nie w obrębieAFTER
wyzwalacza. Zgodnie z dokumentacją CREATE TRIGGER :Oczywiście użycie
INSTEAD OF
wyzwalacza wymagałoby:AFTER
wyzwalacza, który włącza ograniczenieJednak nie poleciłbym tego robić.
źródło
CURRENT_TIMESTAMP
dla kolumn datetime. Tak więc „łatwy” test użycia niepoprawnego wyrażenia nie będzie tam działał (a nie można użyć niepoprawnej wartości,CREATE TABLE
ponieważ jest on sprawdzony) i nie mam czasu na wykonanie testu wydajności. Podejrzewam jednak, że większość RDBMS potraktowałaby je w ten sam sposób.Nie widzę żadnej istotnej szkody z powodu domyślnych ograniczeń. W rzeczywistości widzę jedną szczególną zaletę - zdefiniowałeś domyślną wartość na tym samym poziomie logiki, co sama definicja tabeli. Jeśli masz wartość domyślną podaną w procedurze przechowywanej, ktoś musi tam pójść, aby dowiedzieć się, jaka jest wartość domyślna; i nie jest to coś oczywistego dla kogoś nowego w systemie, koniecznie (jeśli, na przykład, jutro odziedziczysz miliard dolarów, kupisz własną tropikalną wyspę, zrezygnujesz i się tam przeprowadzisz, pozostawiając innego biednego sokowirówkę do wymyślenia różnych rzeczy) na własną rękę).
źródło