Rozpoczynam nowy projekt i chciałbym uzyskać od samego początku nazwy moich tabel i kolumn. Na przykład zawsze używałem liczby mnogiej w nazwach tabel, ale ostatnio dowiedziałem się, że liczba pojedyncza jest poprawna.
Tak więc, jeśli mam tabelę „user”, a następnie otrzymam produkty, które będzie miał tylko użytkownik, czy tabela powinna mieć nazwę „user_product” czy po prostu „product”? To jest relacja jeden do wielu.
I dalej, gdybym miał (z jakiegoś powodu) kilka opisów produktów dla każdego produktu, czy byłoby to „user_product_description”, „product_description” czy po prostu „description”? Oczywiście z ustawionymi odpowiednimi kluczami obcymi. Nadanie mu nazwy tylko opis byłoby problematyczne, ponieważ mógłbym mieć również opis użytkownika lub opis konta lub cokolwiek innego.
A co jeśli chcę mieć czystą tabelę relacyjną (wiele do wielu) z tylko dwiema kolumnami, jak by to wyglądało? „user_stuff” czy może coś w rodzaju „rel_user_stuff”? A jeśli pierwszy, co by to odróżniało od np. „User_product”?
Każda pomoc jest bardzo ceniona, a jeśli istnieje jakiś standard konwencji nazewnictwa, który polecacie, nie krępuj się, aby go połączyć.
Dzięki
primarily opinion-based
jest ewidentnie fałszywa.Odpowiedzi:
Nazwa tabeli
Tak. Strzeżcie się pogan. Liczba mnoga w nazwach tabel to pewny znak kogoś, kto nie przeczytał żadnego ze standardowych materiałów i nie ma wiedzy o teorii baz danych.
Oto niektóre ze wspaniałych cech Standardów:
Standardowa nazwa tabeli odnosi się do każdego wiersza w tabeli, która jest używana we wszystkich słowach, a nie do całej zawartości tabeli (wiemy, że
Customer
tabela zawiera wszystkich Klientów).Związek, zwrot czasownika
W prawdziwych relacyjnych bazach danych, które zostały zamodelowane (w przeciwieństwie do systemów archiwizacji rekordów sprzed lat 70. XX wieku [charakteryzujących się
Record IDs
tym, że dla wygody zaimplementowano je w kontenerze bazy danych SQL):Diagram_A
Oczywiście relacja jest zaimplementowana w języku SQL jako a
CONSTRAINT FOREIGN KEY
w tabeli potomnej (więcej, później). Oto fraza czasownika (w modelu), predykat, który reprezentuje (do odczytania z modelu) i nazwa ograniczenia FK :Tabela • Język
Jednak podczas opisywania tabeli, szczególnie w języku technicznym, takim jak predykaty lub inna dokumentacja, używaj liczby pojedynczej i mnogiej, ponieważ naturalnie w języku angielskim. Mając na uwadze, że nazwa tabeli pochodzi od pojedynczego wiersza (relacji), a język odnosi się do każdego wiersza pochodnego (relacja pochodna):
nie
(To nie jest kwestia nazewnictwa; to jest kwestia projektowania db.) Nie ma znaczenia, czy
user::product
jest to 1 :: n. Liczy się to, czyproduct
jest to odrębny byt i czy jest to Niezależna Tabela , tj. może istnieć samodzielnie. Dlategoproduct
nieuser_product
.A jeśli
product
istnieje tylko w kontekścieuser
, tj. jest to zatem tabela zależnauser_product
.Diagram_B
Zgadza się. Każdy
user_product_description
xorproduct_description
będzie poprawny, na podstawie powyższego. Nie ma go odróżniać od innychxxxx_descriptions
, ale ma nadać nazwie poczucie, gdzie należy, a przedrostkiem jest tabela nadrzędna.Miejmy nadzieję, że wszystkie tabele w relacyjnej bazie danych są czysto relacyjnymi, znormalizowanymi tabelami. Nie ma potrzeby identyfikowania tego w nazwie (w przeciwnym razie wszystkie tabele będą
rel_something
).Jeśli zawiera tylko PK dwóch rodziców (co rozwiązuje logiczną relację n :: n, która nie istnieje jako jednostka na poziomie logicznym, do fizycznej tabeli), jest to tabela asocjacyjna . Tak, zazwyczaj nazwa jest połączeniem dwóch nazw tabel nadrzędnych.
Zauważ, że w takich przypadkach fraza czasownika ma zastosowanie i jest odczytywana jako, od rodzica do rodzica, ignorując tabelę podrzędną, ponieważ jej jedynym celem w życiu jest powiązanie dwojga rodziców.
Diagram_C
Jeśli to nie tabeli asocjacyjne (tj. W uzupełnieniu do dwóch PK, zawiera dane), a następnie na to odpowiednie, i zwroty Verb odnoszą się do niego, a nie z rodziców na końcu związku.
Diagram_D
Jeśli otrzymasz dwie
user_product
tabele, oznacza to bardzo głośny sygnał, że dane nie zostały znormalizowane. Cofnij się więc o kilka kroków i zrób to, a następnie nazwij tabele dokładnie i konsekwentnie. Nazwy same się rozwiążą.Konwencja nazewnictwa
To, co robisz, jest bardzo ważne i wpłynie na łatwość użytkowania i zrozumienie na każdym poziomie. Dlatego dobrze jest na początku uzyskać jak najwięcej zrozumienia. Znaczenie większości z nich nie będzie jasne, dopóki nie zaczniesz kodować w języku SQL.
Sprawa to pierwsza rzecz, którą należy się zająć. Wszystkie czapki są niedopuszczalne. Wielkość liter jest normalna, zwłaszcza jeśli użytkownicy mają bezpośredni dostęp do tabel. Zapoznaj się z moimi modelami danych. Zauważ, że kiedy osoba poszukująca używa obłąkanego NonSQL, który ma tylko małe litery, daję to, w takim przypadku dołączam podkreślenia (jak na twoich przykładach).
Skup się na danych , a nie na aplikacji lub użyciu. W końcu 2011 roku mamy otwartą architekturę od 1984 roku, a bazy danych mają być niezależne od aplikacji, które z nich korzystają.
W ten sposób, gdy rosną i więcej niż jedna aplikacja ich używa, nazewnictwo pozostanie znaczące i nie będzie wymagało korekty. (Bazy danych, które są całkowicie osadzone w jednej aplikacji, nie są bazami danych). Nazwij elementy danych tylko jako dane.
Bądź bardzo rozważny i bardzo dokładnie nazywaj tabele i kolumny . Nie używaj,
UpdatedDate
jeśli jest toDATETIME
typ danych, użyjUpdatedDtm
. Nie używać,_description
jeśli zawiera dawkę.Ważne jest, aby zachować spójność w całej bazie danych. Nie używaj
NumProduct
w jednym miejscu do wskazania liczby ProduktówItemNo
aniItemNum
w innym miejscu do wskazania liczby Produktów. Używaj konsekwentnieNumSomething
do numerów-of iSomethingNo
lubSomethingId
do identyfikatorów.Nie poprzedzaj nazwy kolumny nazwą tabeli ani krótkim kodem, takim jak
user_first_name
. SQL już podaje nazwę tabeli jako kwalifikator:Wyjątki:
Pierwszy wyjątek dotyczy PK, wymagają one specjalnej obsługi, ponieważ cały czas kodujesz je w złączeniach i chcesz, aby klucze wyróżniały się z kolumn danych. Zawsze używaj
user_id
, nigdyid
.user_id
jest kolumna, która identyfikuje użytkownika, a nieid
nauser
stole.user_product
tabela będzie miałauser_id
jako składnik swojej PK(user_id, product_no)
.id
na wielu tabelach, łatwo jest pomylić kodowanie SQL. Po drugie, każdy inny, kto pierwszy programista nie ma pojęcia, co próbował zrobić. Oba są łatwe do uniknięcia, jeśli kolumny kluczowe są traktowane jak powyżej.Drugim wyjątkiem jest sytuacja, gdy istnieje więcej niż jeden FK odwołujący się do tej samej tabeli tabeli nadrzędnej, przenoszonej przez element podrzędny. Zgodnie z modelem relacyjnym , użyj nazw ról, aby rozróżnić znaczenie lub użycie, np.
AssemblyCode
iComponentCode
dla dwojgaPartCodes
. W takim przypadku nie używaj niezróżnicowanegoPartCode
dla jednego z nich. Bądź precyzyjny.Diagram_E
Prefiks
Jeśli masz więcej niż 100 tabel, poprzedź nazwy tabel obszarem tematu:
REF_
dla tabel referencyjnychOE_
dla klastra wprowadzania zamówień itp.Tylko na poziomie fizycznym, a nie logicznym (zaśmieca model).
Sufiks
Nigdy nie używaj sufiksów w tabelach i zawsze używaj sufiksów do wszystkiego innego. Oznacza to, że przy logicznym, normalnym korzystaniu z bazy danych nie ma podkreślenia; ale po stronie administracyjnej podkreślenia są używane jako separator:
_V
Widok (TableName
oczywiście z głównym z przodu)_fk
Klucz obcy (nazwa ograniczenia, a nie nazwa kolumny) Transakcja segmentu_cac
pamięci podręcznej (przechowywana procedura lub funkcja) Funkcja (nietransakcyjna) itp._seg
_tr
_fn
Format to nazwa tabeli lub FK, podkreślenie i nazwa akcji, podkreślenie i na końcu sufiks.
Jest to naprawdę ważne, ponieważ gdy serwer wyświetla komunikat o błędzie:
____
blah blah blah error on object_name
wiesz dokładnie, jaki obiekt został naruszony i co próbował zrobić:
____
blah blah blah error on Customer_Add_tr
Klucze obce (ograniczenie, a nie kolumna). Najlepszym nazewnictwem FK jest użycie wyrażenia czasownika (bez „każdego” i liczności).
Customer_Initiates_SalesOrder_fk
Part_Comprises_Component_fk
Part_IsConsumedIn_Assembly_fk
Użyj
Parent_Child_fk
sekwencji, a nieChild_Parent_fk
jest, ponieważ (a) pojawia się ona we właściwej kolejności, kiedy ich szukasz, i (b) zawsze wiemy, jakie dziecko jest zaangażowane, co zgadujemy, który rodzic. Komunikat o błędzie jest wtedy zachwycający:____
Foreign key violation on Vendor_Offers_PartVendor_fk
.To działa dobrze dla osób, które zadają sobie trud modelowania swoich danych, w których zidentyfikowano wyrażenia czasownikowe. W pozostałej części użyj zbiorów akt itp
Parent_Child_fk
.Indeksy są specjalne, więc mają własną konwencję nazewnictwa, na którą składają się kolejno pozycje każdego znaku od 1 do 3:
U
Unikalny lub_
nieunikatowy SeparatorC
klastrowy lub_
nieklastrowy_
Dla przypomnienia:
Jeśli klucz to jedna kolumna lub kilka kolumn:
____
ColumnNames
Jeśli klucz ma więcej niż kilka kolumn:
____
PK
Klucz podstawowy (zgodnie z modelem)____
AK[*n*]
Klucz alternatywny (termin IDEF1X)Zwróć uwagę, że nazwa tabeli nie jest wymagana w nazwie indeksu, ponieważ zawsze jest wyświetlana jako
table_name.index_name.
Więc kiedy
Customer.UC_CustomerId
lubProduct.U__AK
pojawia się w komunikacie o błędzie, mówi ci coś znaczącego. Gdy spojrzysz na indeksy na stole, możesz je łatwo rozróżnić.Znajdź kogoś wykwalifikowanego i profesjonalnego i podążaj za nimi. Przyjrzyj się ich projektom i dokładnie przestudiuj konwencje nazewnictwa, których używają. Zadawaj im konkretne pytania dotyczące wszystkiego, czego nie rozumiesz. I na odwrót, uciekaj jak diabli od każdego, kto wykazuje niewielki szacunek dla konwencji lub standardów nazewnictwa. Oto kilka na początek:
Zamówienia i zapasy z adresami zgodnymi z normami
Prosty system biuletynów biurowych dla PHP / MyNonSQL
Monitorowanie czujnika z pełną funkcją Temporal
Odpowiedzi na pytania
Na to nie można rozsądnie odpowiedzieć w polu komentarza.
W Twoim komentarzu są dwa główne problemy:
Oświadczasz, że twój przykład jest „najbardziej trywialny”, jednak jest to wszystko inne. Z tego rodzaju sprzecznościami nie jestem pewien, czy jesteś poważny, czy technicznie zdolny.
Ta „trywialna” spekulacja zawiera kilka poważnych błędów normalizacji (projektowania DB).
Dopóki ich nie poprawisz, są nienaturalne i nienormalne i nie mają żadnego sensu. Równie dobrze możesz nazwać je nienormalne_1, anormalne_2 itd.
Masz „dostawców”, którzy niczego nie dostarczają; odwołania cykliczne (nielegalne i niepotrzebne); klienci kupujący produkty bez żadnego instrumentu komercyjnego (takiego jak faktura lub zamówienie sprzedaży) jako podstawy do zakupu (czy też klienci „posiadają” produkty?); nierozwiązane relacje „wiele do wielu”; itp.
Po znormalizowaniu i zidentyfikowaniu wymaganych tabel ich nazwy staną się oczywiste. Naturalnie.
W każdym razie postaram się obsłużyć Twoje zapytanie. Co oznacza, że będę musiał nadać temu trochę sensu, nie wiedząc, co masz na myśli, więc proszę o wyrozumiałość. Jest zbyt wiele poważnych błędów, aby je wymienić, a biorąc pod uwagę niepełną specyfikację, nie jestem pewien, czy poprawiłem je wszystkie.
Zakładam, że jeśli produkt składa się z komponentów, to produkt jest zespołem, a komponenty są używane w więcej niż jednym zespole.
Ponadto, ponieważ „Dostawca sprzedaje komponenty od zera do wielu”, nie sprzedaje produktów ani zespołów, sprzedaje tylko komponenty.
Spekulacje a model znormalizowany
Jeśli nie jesteś świadomy, różnica między narożnikami kwadratowymi (niezależne) i zaokrąglonymi (zależne) jest znacząca, zapoznaj się z linkiem Notation IDEF1X. Podobnie linie ciągłe (identyfikujące) w porównaniu z liniami przerywanymi (nieidentyfikujące).
Teraz, gdy rozwiązałem tabele, nie rozumiem twojego problemu. Być może możesz zadać konkretne pytanie.
Zakładając, że nie ma błędów normalizacji,
User likes Product
jest predykatem, a nie tabelą. Nie myl ich. Zapoznaj się z moją odpowiedzią, gdzie odnosi się do tematów, czasowników i orzeczeń, oraz moją odpowiedź dla Larry'ego bezpośrednio powyżej.Każda tabela zawiera zestaw faktów (każdy wiersz to fakt). Predykaty (lub zdania) nie są faktami, mogą być prawdziwe lub nie.
Relacyjny model jest oparty na rachunku predykatów pierwszego (bardziej znany jako pierwsze zamówienie Logic). Predykat to zdanie składające się z pojedynczej klauzuli w prostym, precyzyjnym języku angielskim, którego wynikiem jest prawda lub fałsz.
Co więcej, każda tabela reprezentuje lub jest implementacją wielu Predykatów, a nie jednego.
Zapytanie to test Predykatu (lub pewnej liczby Predykatów połączonych w łańcuch), którego wynikiem jest prawda (Fakt istnieje) lub fałsz (Fakt nie istnieje).
Dlatego tabele powinny być nazywane zgodnie z moją odpowiedzią (konwencje nazewnictwa), dla wiersza, fakt i predykaty powinny być udokumentowane (jak najbardziej jest to część dokumentacji bazy danych), ale jako osobna lista Predykatów .
To nie jest sugestia, że nie są one ważne. Są bardzo ważne, ale nie napiszę tego tutaj.
Więc szybko. Ponieważ model relacyjny jest oparty na FOPC, o całej bazie danych można powiedzieć, że jest zbiorem deklaracji FOPC, zbiorem predykatów. Ale (a) istnieje wiele typów Predykatów i (b) tabela nie reprezentuje jednego Predykatu (jest to fizyczna implementacja wielu Predykatów i różnych typów Predykatów).
Dlatego nazwanie tabeli „orzeczeniem, które reprezentuje” jest absurdalną koncepcją.
„Teoretycy” są świadomi tylko kilku Predykatów, nie rozumieją, że skoro RM została założona na FOL, cała baza danych jest zbiorem Predykatów i jest różnych typów.
I oczywiście wybierają absurdalne spośród nielicznych, które znają
EXISTING_PERSON
:;PERSON_IS_CALLED
. Gdyby to nie było takie smutne, byłoby przezabawne.Zauważ również, że standardowa lub atomowa nazwa tabeli (nazywająca wiersz) działa doskonale w przypadku wszystkich wyrażeń (w tym wszystkich predykatów dołączonych do tabeli). I odwrotnie, idiotyczna „tabela reprezentuje predykat” nie może. Co jest dobre dla „teoretyków”, którzy niewiele rozumieją o orzeczeniach, ale mają inne opóźnienie.
Predykaty, które są istotne dla modelu danych, są wyrażone w modelu, mają dwa rzędy.
Jednoargumentowy predykat
Pierwszy zestaw jest schematyczny , a nie tekstowy: sam zapis . Należą do nich różne egzystencjalne; Zorientowany na ograniczenia; i Predykaty deskryptorowe (atrybuty).
Predykat binarny
Drugi zestaw to te, które tworzą relacje między faktami. To jest linia relacji. Fraza czasownika (szczegółowo opisana powyżej) identyfikuje predykat, zdanie , które zostało zaimplementowane (które można sprawdzić za pomocą zapytania). Nie można wyrazić się bardziej wprost.
Oto model danych , w którym wymieniłem predykaty. Wybrałem ten przykład, ponieważ pokazuje on predykaty egzystencjalne itp., A także predykaty relacyjne, jedynymi predykatami, które nie zostały wymienione, są deskryptory. Tutaj, ze względu na poziom wiedzy poszukiwacza, traktuję go jako użytkownika.
Dlatego zdarzenie więcej niż jednej tabeli podrzędnej między dwiema tabelami nadrzędnymi nie stanowi problemu, po prostu nazwij je jako fakt egzystencjalny w ich zawartości i znormalizuj nazwy.
Reguły, które podałem dla wyrażeń czasownikowych dla nazw relacji dla tabel asocjacyjnych, wchodzą tutaj w grę. Oto podsumowanie dyskusji Predykat vs Tabela , obejmującej wszystkie wspomniane punkty.
Aby uzyskać dobry krótki opis właściwego używania predykatów i sposobu ich używania (co jest całkiem innym kontekstem niż odpowiadanie na komentarze tutaj), odwiedź tę odpowiedź i przewiń w dół do sekcji Predykaty .
Ok, to właśnie nazywamy tabelą Key lub NextKey. Nazwij to tak. Jeśli masz SubjectAreas, użyj COM_NextKey, aby wskazać, że jest wspólny dla całej bazy danych.
Przy okazji, to bardzo słaba metoda generowania kluczy. W ogóle nie jest skalowalny, ale z wydajnością Oracle prawdopodobnie jest „po prostu w porządku”. Co więcej, wskazuje, że twoja baza danych jest pełna surogatów, a nie relacyjnych w tych obszarach. Co oznacza wyjątkowo słabą wydajność i brak integralności.
źródło
Liczba pojedyncza a liczba mnoga: Wybierz jedną i trzymaj się jej.
Kolumny nie powinny być poprzedzane / sufiksowane / wrostane ani w żaden sposób poprawiane z odniesieniami do faktu, że jest to kolumna. To samo dotyczy stołów. Nie nazywaj tabel EMPLOYEE_T ani TBL_EMPLOYEES, ponieważ w drugiej kolejności jest zastępowana widokiem, sprawy stają się naprawdę zagmatwane.
Nie osadzaj informacji o typie w nazwach, takich jak „vc_firstname” dla varchar lub „flavour_enum”. Nie osadzaj też ograniczeń w nazwach kolumn, takich jak „dział_fk” lub „pracownik_pk”.
Właściwie jedyną dobrą rzeczą * Poprawki można myślę, jest to, że można używać zarezerwowanych słów takich jak
where_t
,tbl_order
,user_vw
. Oczywiście w tych przykładach użycie liczby mnogiej rozwiązałoby problem :)Nie nazywaj wszystkich kluczy „ID”. Klucze odnoszące się do tej samej rzeczy powinny mieć tę samą nazwę we wszystkich tabelach. Kolumna identyfikatora użytkownika może mieć nazwę USER_ID w tabeli użytkowników i wszystkich tabelach odwołujących się do użytkownika. Zmiana nazwy następuje tylko wtedy, gdy różni użytkownicy odgrywają różne role, na przykład Message (sender_user_id, receiver_user_id). To naprawdę pomaga w przypadku większych zapytań.
Odnośnie CaSe:
Ogólnie lepiej jest nazwać „tabele odwzorowań”, aby pasowały do relacji, które opisują, zamiast nazw tabel, do których istnieją odniesienia. Użytkownik może mieć dowolną liczbę relacji do produktów:
user_likes_product
,user_bought_product
,user_wants_to_buy_product
.źródło
{table_name}_id
a nie tylkoid
, ponieważ kolumna będzie zawsze odwoływana tylko z nazwą tabeli poprzedzoną prefiksem jako kwalifikator, nptable_name.id
. Ze względów kontekstowych działam w ekosystemie, w którym składnia złączenia formularzatable_a JOIN table_b ON table_b_id_column
nie jest obsługiwana; Muszę to zrobićtable_a JOIN table_b ON table_b.id_column = table_a.table_b_id_column
.Nie ma „poprawności” w liczbie pojedynczej i mnogiej - jest to głównie kwestia gustu.
Po części zależy to od twojego skupienia. Jeśli myślisz o tabeli jako jednostce, zawiera ona `` liczbę mnogą '' (ponieważ zawiera wiele wierszy - więc nazwa w liczbie mnogiej jest odpowiednia). Jeśli myślisz o nazwie tabeli jako identyfikującej wiersz w tabeli, wolisz „liczbę pojedynczą”. Oznacza to, że twój SQL będzie traktowany jako pracujący na jednym wierszu z tabeli. To jest OK, choć zwykle jest to nadmierne uproszczenie; SQL działa na zbiorach (mniej więcej). Jednak w przypadku odpowiedzi na to pytanie możemy użyć liczby pojedynczej.
Ponieważ prawdopodobnie będziesz potrzebować tabeli „user”, innego „produktu” i trzeciego do łączenia użytkowników z produktami, potrzebujesz tabeli „user_product”.
Ponieważ opis dotyczy produktu, należy użyć „opis_produktu”. Chyba że każdy użytkownik nazwałby każdy produkt dla siebie ...
Tabela „user_product” jest (lub może być) przykładem tabeli z identyfikatorem produktu i identyfikatorem użytkownika i niewiele więcej. Nazwij tabele z dwoma atrybutami w ten sam ogólny sposób: „user_stuff”. Dekoracyjne przedrostki, takie jak „rel_”, tak naprawdę nie pomagają. Na przykład niektóre osoby używają „t_” przed nazwą każdej tabeli. To niewiele pomaga.
źródło
Liczba mnoga nie jest zła, o ile jest używana konsekwentnie - ale wolę liczbę pojedynczą.
Zrezygnowałbym z podkreślenia, chyba że chcesz nakreślić relację wiele do wielu; i używaj kapitału początkowego, ponieważ pomaga to odróżnić rzeczy w ORMach.
Ale istnieje wiele konwencji nazewnictwa, więc jeśli chcesz używać podkreśleń, jest to w porządku, o ile jest to wykonywane konsekwentnie.
Więc:
Jeśli tylko jeden użytkownik może mieć dowolny produkt
Ale jeśli produkt jest udostępniany przez użytkowników:
Jeśli zapiszesz podkreślenia dla relacji wiele do wielu, możesz zrobić coś takiego:
aby utworzyć M-to-M między UserProduct a Stuff - nie jestem pewien, z pytania, jaki jest dokładny charakter wymaganej liczby do wielu.
źródło
Nie ma lepszego sposobu na użycie liczby pojedynczej niż liczba mnoga. Gdzie to słyszałeś? Powiedziałbym raczej, że liczba mnoga jest bardziej powszechna w nazewnictwie tabel bazy danych ... i moim zdaniem jest też bardziej logiczna. Tabela najczęściej zawiera więcej niż jeden wiersz;) W modelu koncepcyjnym chociaż nazwy jednostek są często w liczbie pojedynczej.
Jeśli chodzi o twoje pytanie, jeśli „Produkt” i „Opis produktu” są pojęciami z tożsamością (tj. Bytami) w Twoim modelu, nazwałbym tabele „Produkty” i „Opisy produktów”. W przypadku tabel używanych w celu zaimplementowania relacji wiele-do-wielu najczęściej używam konwencji nazewnictwa „SideA2SideB”, na przykład „Student2Course”.
źródło