Pole boolowskie w Oracle

145

Wczoraj chciałem dodać pole boolowskie do tabeli Oracle. Jednak w rzeczywistości nie ma logicznego typu danych w Oracle. Czy ktoś tutaj zna najlepszy sposób na symulację wartości logicznej? Wyszukiwanie tematu w Google pozwoliło odkryć kilka podejść

  1. Użyj liczby całkowitej i po prostu nie przejmuj się przypisywaniem do niej niczego innego niż 0 lub 1.

  2. Użyj pola znaku z „Y” lub „N” jako jedynymi dwiema wartościami.

  3. Użyj wyliczenia z ograniczeniem CHECK.

Czy doświadczeni programiści Oracle wiedzą, które podejście jest preferowane / kanoniczne?

Eli Courtwright
źródło
195
Żałuję, że Oracle nie ma walltypu danych, abym mógł rozbić sobie głowę, używając wartości logicznych.
Greg

Odpowiedzi:

82

Ten link okazał się przydatny.

Oto akapit przedstawiający niektóre zalety / wady każdego podejścia.

Najczęściej spotykanym projektem jest naśladowanie wielu flag podobnych do logicznych, których używają widoki słownika danych Oracle, wybierając „Y” dla prawdy i „N” dla fałszu. Jednak, aby poprawnie współdziałać ze środowiskami hosta, takimi jak JDBC, OCCI i innymi środowiskami programistycznymi, lepiej wybrać 0 dla fałszu i 1 dla prawdy, aby działał poprawnie z funkcjami getBoolean i setBoolean.

Zasadniczo opowiadają się za metodą numer 2, ze względu na wydajność, używając

  • wartości 0/1 (z powodu współdziałania z JDBC getBoolean()itp.) z ograniczeniem sprawdzającym
  • typu char (ponieważ używa mniej miejsca niż liczba).

Ich przykład:

create table tbool (bool char check (bool in (0,1));
insert into tbool values(0);
insert into tbool values(1);`
ColinYounger
źródło
31
Odradzam używanie „N” i „Y”, ponieważ jest to zależne od języka. Anglofony czasami zapominają, że większość świata nie reprezentuje pojęcia prawdy za pomocą litery Y. Z kolei znaczenie 0 i 1 jest stałe ponad barierami językowymi.
Andrew Spencer,
7
0 i 1 jako wartości logiczne nie są spójne w informatyce - języki skryptowe powłoki zwykle mają 0 jako sukces, a wartość niezerową jako porażkę, podczas gdy języki typu C mają zwykle 0 jako niepowodzenie i niezerowe jako sukces.
Phil
41
Jako wartości logiczne są one jednoznaczne. Kody powrotu procesu nie są wartościami logicznymi.
Andrew Spencer
13
Dlaczego cały akapit z podanego linku został zignorowany w tej odpowiedzi? „Najczęściej spotykanym projektem jest naśladowanie wielu flag podobnych do wartości logicznych, których używają widoki słownika danych Oracle, wybierając„ Y ”dla prawdy i„ N ”dla fałszu. Jednak aby poprawnie współdziałać ze środowiskami hosta, takimi jak JDBC, OCCI, i innych środowisk programistycznych, lepiej wybrać 0 dla fałszu i 1 dla prawdy, aby działało poprawnie z funkcjami getBoolean i setBoolean. " Twierdzą, że chociaż „T / N” jest powszechne, zalecane jest użycie „0/1” w celu zwiększenia zgodności ze środowiskami hostów.
justin.hughey
28

Sama Oracle używa Y / N dla wartości logicznych. Dla kompletności należy zauważyć, że pl / sql ma typ boolowski, tylko tabele go nie mają.

Jeśli używasz tego pola do wskazania, czy rekord ma zostać przetworzony, czy nie, możesz rozważyć użycie Y i NULL jako wartości. To sprawia, że ​​indeks jest bardzo mały (szybki), który zajmuje bardzo mało miejsca.

Leigh Riffel
źródło
7
+1 Dobra uwaga na temat wewnętrznych widoków i tabel Oracle przy użyciu T / N. Jeśli Oracle robi to w ten sposób, to musi mieć rację! :)
Jeffrey Kemp
Czy możesz wyjaśnić, jak Y i NULL tworzą mały indeks w porównaniu z Y i N?
styfle
6
Wartości NULL nie są indeksowane w Oracle, więc jeśli indeks zawiera kilka Y znaków, ale głównie wartości NULL, będziesz mieć bardzo mały indeks.
Leigh Riffel
25

Aby wykorzystać jak najmniej miejsca, należy użyć pola CHAR ograniczonego do „Y” lub „N”. Oracle nie obsługuje typów danych BOOLEAN, BIT ani TINYINT, więc jeden bajt CHAR jest tak mały, jak to tylko możliwe.

Bill the Lizard
źródło
19

Najlepszą opcją jest 0 i 1 (jako liczby - inna odpowiedź sugeruje 0 i 1 jako CHAR dla wydajności przestrzennej, ale jest to dla mnie trochę zbyt pokręcone), używając NOT NULL i ograniczenia sprawdzającego, aby ograniczyć zawartość do tych wartości. (Jeśli chcesz, aby kolumna miała wartość null, to nie jest to wartość logiczna, z którą masz do czynienia, ale wyliczenie z trzema wartościami ...)

Zalety 0/1:

  • Niezależny od języka. „Y” i „N” byłyby w porządku, gdyby wszyscy go używali. Ale tak nie jest. We Francji używają „O” i „N” (widziałem to na własne oczy). Nie zaprogramowałem w Finlandii, aby sprawdzić, czy używają tam „E” i „K” - bez wątpienia są mądrzejsi, ale nie możesz być pewien.
  • Zgodny z praktyką w szeroko stosowanych językach programowania (C, C ++, Perl, Javascript)
  • Działa lepiej z warstwą aplikacji np. Hibernate
  • Prowadzi do bardziej zwięzłego języka SQL, na przykład, aby dowiedzieć się, ile bananów jest gotowych do spożycia select sum(is_ripe) from bananaszamiast select count(*) from bananas where is_ripe = 'Y'lub nawet (fuj)select sum(case is_ripe when 'Y' then 1 else 0) from bananas

Zalety „Y” / „N”:

  • Zajmuje mniej miejsca niż 0/1
  • To właśnie sugeruje Oracle, więc może być to, do czego niektórzy ludzie są bardziej przyzwyczajeni

Inny plakat sugerował „Y” / null w celu zwiększenia wydajności. Jeśli udowodnisz , że potrzebujesz wydajności, to wystarczy, ale w przeciwnym razie unikaj, ponieważ sprawia, że ​​zapytania są mniej naturalne ( some_column is nullzamiast some_column = 0), a w złączeniu po lewej stronie połączysz fałsz z nieistniejącymi rekordami.

Andrew Spencer
źródło
3
Okazuje się, że obecnie wiele wartości logicznych jest trójstanowych, tj. Prawdziwe, fałszywe i nieznane. co doskonale pasuje do idei bazy danych o zerowej wartości. po prostu dlatego, że wiele razy świadomość braku odpowiedzi jest niezwykle ważna
MikeT,
1
Tak, prawda-fałsz-nieznane może być wymagane, chociaż gdybym był wybredny (którym jestem), powiedziałbym, że tak naprawdę nie powinien być opisywany jako wartość logiczna, ponieważ tak nie jest.
Andrew Spencer
2
jeśli chcesz być tak wybredny, możesz zastosować ten sam argument dla każdego typu danych. tak jak w ścisłej definicji liczba całkowita, double (chyba powinienem powiedzieć zmiennoprzecinkowe uzupełnienie dwójek o podwójnej długości), Binary, string, itd. wszystkie zakładają, że podano wartość, ale implementacje baz danych zawsze dodają opcję wartości null Boolean nie różni się
niczym
1
prawda, na plus dla twojej metody, jeśli poprawnie skonfigurujesz swój numer, może być również przechowywany w tym samym pojedynczym bajcie co pole char, co unieważnia argument size przeciwko użyciu 0/1, nie mogę obecnie znaleźć linku, ale przechowywanie liczby waha się od 1 do 22 bajtów w zależności od konfiguracji
MikeT
4
Podejrzewam, że głosy przeciwne wynikają ze starszego punktu widzenia wyboru implementacji najbardziej wydajnej pod względem pamięci. Dzisiejsza efektywność pamięci w czasach współczesnych jest znacznie mniej priorytetowa i powinna być brana pod uwagę po użyteczności i kompatybilności. Każdemu, kto może odpowiedzieć na ten komentarz, polecam poczytać o przedwczesnej optymalizacji. Dokładnie tak się dzieje, wybierając opcję „T / N” wyłącznie na podstawie wydajności pamięci. Z powodu tej decyzji tracisz natywną zgodność z zestawem powszechnie używanych platform.
justin.hughey
5

1/0 lub T / N z ograniczeniem sprawdzającym. sposób eteru jest w porządku. Osobiście wolę 1/0, ponieważ wykonuję dużo pracy w perlu i bardzo ułatwia to wykonywanie operacji logicznych w perlu na polach bazy danych.

Jeśli chcesz naprawdę dogłębnie omówić tę kwestię z jednym z szefów Oracles, sprawdź, co ma do powiedzenia na ten temat Tom Kyte Tutaj

Matthew Watson
źródło
Mówi się, że 1/0 jest „mniej wydajne pod względem pamięci”, ale ... ja też lubię go bardziej (a hibernacja najwyraźniej wymaga 1/0 dla wartości logicznej)
rogerdpack
1/0 to domyślne ustawienie Hibernate'a dla wartości logicznej, ale możesz zdefiniować dowolne niestandardowe mapowanie.
Andrew Spencer,
@rogerdpack, ponieważ pole char ma 1 bajt lub 2 bajty dla nchar, gdzie w zależności od tego, jak jest zdefiniowane, liczba może mieć od 1 do 22 bajtów
MikeT
4

Baza danych, na której wykonywałem większość swojej pracy, używała „Y” / „N” jako wartości logicznych. Dzięki tej implementacji możesz wykonać kilka sztuczek, takich jak:

  1. Policz wiersze, które są prawdziwe:
    SELECT SUM (CASE WHEN BOOLEAN_FLAG = 'Y' THEN 1 ELSE 0) FROM X

  2. Podczas grupowania wierszy
    wymuś logikę „Jeśli jeden wiersz jest prawdziwy, wszystkie są prawdziwe”: SELECT MAX (BOOLEAN_FLAG) FROM Y
    I odwrotnie, użyj MIN, aby wymusić grupowanie fałszywe, jeśli jeden wiersz jest fałszywy.

Erick B.
źródło
4
w rzeczywistości przedstawione przykłady są również przydatne w podejściu 0/1 - i IMHO, szybciej.
igorsantos 07
2

Roboczy przykład implementacji zaakceptowanej odpowiedzi poprzez dodanie kolumny „Boolean” do istniejącej tabeli w bazie danych Oracle (przy użyciu numbertypu):

ALTER TABLE my_table_name ADD (
my_new_boolean_column number(1) DEFAULT 0 NOT NULL
CONSTRAINT my_new_boolean_column CHECK (my_new_boolean_column in (1,0))
);

To tworzy nową kolumnę my_table_nameo nazwie my_new_boolean_columnz domyślnych wartości 0. kolumna nie będzie akceptować NULLwartości i ogranicza wartości zgodził się albo 0albo 1.

Ben.12
źródło
1

W naszych bazach danych używamy wyliczenia, które zapewnia, że ​​przekażemy je TRUE lub FALSE. Jeśli zrobisz to na jeden z dwóch pierwszych sposobów, zbyt łatwo jest zacząć dodawać nowe znaczenie do liczby całkowitej bez przechodzenia przez odpowiedni projekt lub skończyć z tym polem znaku mającym Y, y, N, n, T, t, Wartości F, f i konieczność zapamiętania, która sekcja kodu używa której tabeli i której wersji true używa.

Ryan Ahearn
źródło