Na czym polega zabieg porównywania "jedynek" w zapytaniu SQL

Na czym polega zabieg porównywania "jedynek" w zapytaniu SQL
AdamWox
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 8 godzin
  • Lokalizacja:Jastrzębie-Zdrój
  • Postów:2153
1

Witam.
Czy jest w stanie mi ktoś wytłumaczyć dlaczego Comarch w swoich zapytaniach robi taki zabieg

Kopiuj
WHERE ((((1=1) AND (1=1))))

Jaki to ma sens?

Całe, przykładowe zapytanie

Kopiuj
SELECT BRp_BRpId, CASE WHEN BRp_NumerObcy<>'' THEN BRp_NumerObcy ELSE BRp_NumerPelny END AS Numer, CASE WHEN BRp_TS_Export Is Not Null THEN 'E' ELSE '' END AS exprE, BRp_DataDok, BRp_SaldoBO AS exprSaldoBO, BRp_Przychody - BRp_Rozchody AS exprObroty, BRp_Przychody AS exprPrzychody, BRp_Rozchody AS exprRozchody, CASE WHEN BRp_Zamkniety=1 THEN BRp_SaldoBO + BRp_Przychody - BRp_Rozchody ELSE 0 END AS exprSaldo, CASE WHEN BRa_Waluta = '' THEN 'PLN' ELSE BRa_Waluta END AS exprWaluta, BRp_DataZam, BRp_BRaID, BRp_NumerPelny, BRa_Symbol, BRp_DekID, BRp_Zamkniety, BRp_PreDekId 
FROM CDN.BnkRaporty A 
JOIN CDN.BnkRachunki B ON B.BRa_BRaID = A.BRp_BRaID
WHERE ((((1=1) AND (1=1))))
ORDER BY BRp_BRaID, BRp_DataDok
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:5 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
3

1=1 to jest sposób na zapisanie true SQLu. Czasem przydaje się przy automatycznym generowaniu zapytań. Jednak w tym przypadku wydaje się to nie mieć żadnego sensu. Jeden kopioał od drugiego i tak zostało, jakbym miał strzelać


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
edytowany 1x, ostatnio: KamilAdam
AdamWox
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 8 godzin
  • Lokalizacja:Jastrzębie-Zdrój
  • Postów:2153
0

No ok, ale bez 1=1 wynik będzie taki sam. Jak by musiało wyglądać to automatyczne generowanie zapytań żeby to miało sens? Czy w tym automatycznym generowaniu brak 1=1 powoduje inny wynik?

KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:5 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
11
AdamWox napisał(a):

Czy w tym automatycznym generowaniu brak 1=1 powoduje inny wynik?

Oczywiście nie powoduje innego wyniku. Prościej tylko napisać generator np.

Kopiuj
val w = "where 1=1 " + (conditions.map(c => "AND " + c).mkString)

Czyli nie trzeba pamiętać o usuwaniu pierwszego AND przy generowaniu warunków


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
titako
No po prostu zmieniłeś mi życie - genialne :D
Marcin.Miga
Też to stosuję. Daję WHERE True, a potem przy każdym warunku (nigdy nie wiem, ile ich będzie) dodaję na początku AND ...
titako
No i tu się kłania moja amatorka - po prostu dziś nie zasnę :D - tyle bezsensownego kodu ...
MisiekNaLuzie
  • Rejestracja:ponad 4 lata
  • Ostatnio:6 miesięcy
  • Lokalizacja:Warszawa
  • Postów:169
4

W tym zapytaniu nie ma to sensu tak jak pisze @KamilAdam.
Jest to warunek pusty. Jest uzywany gdy zapytanie potrzebuje warunku zeby zadzialac na calej tabeli np.

Kopiuj
delete from tabela where 1=1
edytowany 1x, ostatnio: MisiekNaLuzie
UglyMan
  • Rejestracja:około 6 lat
  • Ostatnio:około 3 lata
  • Postów:2206
2

Ja takie rzeczy stosuje w narzędziach gdzie np. w definicji okna czasem jest warunek a czasem go nie ma. I jak jest warunek to podstawiam tu odpowiedni warunek. Jak go nie ma a konstrukcja czegoś wymaga to się wrzucam takie 1=1, które logicznie nie ma żadnego wpływu.

S9
  • Rejestracja:ponad 4 lata
  • Ostatnio:około 2 lata
  • Lokalizacja:Warszawa
  • Postów:1092
2

Takie coś może być też zastosowanie w złych intencjach jako SQL Injection ;)


edytowany 1x, ostatnio: scibi_92
vpiotr
Z tego co pamietam ktorys z DBMSow z tego wzgledu ma opcje zablokowania 1=1
UglyMan
Mówienie w przypadków systemów ERP o podatnościach, a zwłaszcza podatnościach na SQL injection jest jak naśmiewanie sie z niepełnosprawnego dziecka.
PerlMonk
  • Rejestracja:około 6 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Warszawa 🐪
  • Postów:1719
0

To ma sens np. w Oracle https://stackoverflow.com/questions/400255/how-to-put-more-than-1000-values-into-an-oracle-in-clause

Kopiuj
--- zamiast
select * from table t where t.dupa in(1,3,...)
--- piszemy 
select * from table t where (t.dupa, 'a') in(
    (1, 'a'),
    (2, 'a'),
    (3, 'a'),
    (4, 'a'),
---...
)

Działa to na tej zasadzie, że im więcej wartości porównujemy na raz, tym większy mamy limit. Dla jednej wartości jest to 1000, dla dwóch ponad milion (albo jakoś tak). Tak że to - zależnie od bazy danych - może używać efektów ubocznych w celu obejścia limitów itp.


Nie sztuka uciec gdy w dupie sztuciec. 🐪🐪🐪
edytowany 2x, ostatnio: PerlMonk
UglyMan
System, o którym pisze @AdamWox stoi albo na SQl serverze, albo na Postgresie.
KamilAdam
To jedno z ciekaszych obejść problemu 1000 elementów w Oraclu. Ale kiedyś znalazłem lepsze. Nie pisać zapytań dla Oracla a najlepie w ogóle nie używać Oracla
UglyMan
@KamilAdam: kiedyś Oracle to była jedyna baza, która nadawała się do komercyjnego użycia w firmach, które były spółkami akcyjnymi, albo miały kilka/kilkaset tysięcy klientów (sprzedaż mediów).
KamilAdam
@UglyMan: kiedyś tak, ale już nie. BTW Oracle częściowo samo się samoora podnosząc ceny w kosmos. A PostgreSQL prawie za darmo :)
UglyMan
@KamilAdam: Poza cenami to oni zostali z technologią 20 lat temu (niestety).
TR
  • Rejestracja:ponad 7 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:700m n.p.m.
  • Postów:677
1

Nie trzeba 1=1, wystarczy 1:

Kopiuj
SELECT * FROM my_table WHERE 1 AND name = 'john';

DRY > SOLID (nie bierz tego zbyt poważnie)
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:5 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
0
TomRZ napisał(a):

Nie trzeba 1=1, wystarczy 1:

Kopiuj
SELECT * FROM my_table WHERE 1 AND name = 'john';

Jaka baza?
Na Postgresie dostaje błąd: argument of AND must be type boolean, not type integer


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
edytowany 1x, ostatnio: KamilAdam
Marcin.Miga
WHERE 1::Boolean :)
TR
Albo po prostu true zamiast 1::bolean
Marcin.Miga
To już pisałem w komentarzu wcześniej :)
TR
Tak w ogóle w PostgreSQLu jeszcze tego nie używałem, więc dobrze wiedzieć, że trzeba zrobić true.
UglyMan
  • Rejestracja:około 6 lat
  • Ostatnio:około 3 lata
  • Postów:2206
2
KamilAdam napisał(a):
TomRZ napisał(a):

Nie trzeba 1=1, wystarczy 1:

Kopiuj
SELECT * FROM my_table WHERE 1 AND name = 'john';

Jaka baza?
Na Postgresie dostaje błąd: argument of AND must be type boolean, not type integer

Zgodne ze standardem (powinno działać wszędzie) jest 1=1. Zapisy w stylu where 1 lub where true zadziałają tylko na wybranych implementacjach języka SQL.

PA
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 5 godzin
  • Postów:3866
0

SQLserver rzuci

Kopiuj
Msg 4145, Level 15, State 1, Line 1
An expression of non-boolean type specified in a context where a condition is expected, near 'and'.

z tego co kojarze na mysql zadziala sama jedynka

UglyMan
  • Rejestracja:około 6 lat
  • Ostatnio:około 3 lata
  • Postów:2206
0
Panczo napisał(a):

SQLserver rzuci

Kopiuj
Msg 4145, Level 15, State 1, Line 1
An expression of non-boolean type specified in a context where a condition is expected, near 'and'.

z tego co kojarze na mysql zadziala sama jedynka

Zadziała tam, gdzie jest zdefiniowanie rzutowanie, że 1 - to true a 0 false. Czyli pewnie wszędzie tam, gdzie jest zdefiniowany niestandardowy typ SQL - boolean.

KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:5 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
0
UglyMan napisał(a):

Zadziała tam, gdzie jest zdefiniowanie rzutowanie, że 1 - to true a 0 false. Czyli pewnie wszędzie tam, gdzie jest zdefiniowany niestandardowy typ SQL - boolean.

Postgres ma typ boolean więc where true i where 1::Boolean działają. Jednak where 1 nie działa bo SQL w Postgresie jest statycznie typowany :D


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
hauleth
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:10 dni
2

Nie wiem dlaczego jest tam porównanie podwójnie, może to wyszło z jakiegoś generatora. A WHERE 1=1 czasem jest używane by takie generatory uprościć (dzięki temu nowe elementy do zapytania możesz dodawać w postaci query + " AND " + new_case).


YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 4 godziny
  • Postów:2367
0

Takie generowanie zapytań = zabójstwo wydajności i niekiedy bezpieczeństwa.

UglyMan
  • Rejestracja:około 6 lat
  • Ostatnio:około 3 lata
  • Postów:2206
3
yarel napisał(a):

Takie generowanie zapytań = zabójstwo wydajności i niekiedy bezpieczeństwa.

A dlaczego zabójstwo wydajności?

YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 4 godziny
  • Postów:2367
0

@UglyMan: Zapytania traktowane są jako "nowe" przez silnik bazodanowy. W efekcie sporo czasu idzie na ich przetwarzanie "od zera", zamiast wykorzystanie wersji, która jest już silnikowi znana. Dla której został opracowany plan zapytania.

Mogę pokusić się o taką przewrotną analogię do przetwarzania kodu źródłowego:

  1. Nowe zapytanie -> nowy plik źródłowy -> kompilacja -> uruchomienie.
  2. Istniejące zapytanie -> uruchomienie.
    (istniejące = widziane już kiedyś przez silnik bazodanowy, przetworzone, cachowane)
UglyMan
  • Rejestracja:około 6 lat
  • Ostatnio:około 3 lata
  • Postów:2206
0
yarel napisał(a):

@UglyMan: Zapytania traktowane są jako "nowe" przez silnik bazodanowy. W efekcie sporo czasu idzie na ich przetwarzanie "od zera", zamiast wykorzystanie wersji, która jest już silnikowi znana. Dla której został opracowany plan zapytania.

Mogę pokusić się o taką przewrotną analogię do przetwarzania kodu źródłowego:

  1. Nowe zapytanie -> nowy plik źródłowy -> kompilacja -> uruchomienie.
  2. Istniejące zapytanie -> uruchomienie.
    (istniejące = widziane już kiedyś przez silnik bazodanowy, przetworzone, cachowane)

Ale nie wiem jak to się ma do generowanych zapytań - jak zawsze je wygenerujesz tak samo?

YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 4 godziny
  • Postów:2367
0

@UglyMan: tak, że generujesz na podstawie danych wprowadzanych przez użytkowników. Jeśli Kazio wstawi order=123, a Zosia order=456, to masz 2 różne zapytania. Jeśli takich userów masz więcej i każdy pracuje nad czym innym, to masz odpowiednio więcej unikalnych zapytań. Część obskoczysz przez zmienne wiązane (bind variables), część ogarnie DBA, bo zobaczy, że developer nie użył bind variables. Jeśli dynamicznie będziesz budował bloki wartosc IN (x,y,...,z), to ani DBA ani bind variables nie pomogą za dużo.

PA
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 5 godzin
  • Postów:3866
0

Zapytania traktowane są jako "nowe" przez silnik bazodanowy. W efekcie sporo czasu idzie na ich przetwarzanie "od zera", zamiast wykorzystanie wersji, która jest już silnikowi znana. Dla której został opracowany plan zapytania.

Co do zasady sie zgodzę, co do spadku wydajności niekoniecznie. W przypadku SQL Server kazde zapytanie adhoc ma przygotowywany plan wykonania, jednak taki plan jest zapamiętywany w cache.

Mechanizm mniej wiecej taki:

  1. Puszczenie zapytania adhoc
  2. wyliczenie wartości hasha dla zapytania
  3. Jeżeli dla danego hasha jest zrobiony plan to wykorzystaj, jesli nie to stworz i zapamietaj.

Czyli puszczenie po raz kolejny takiego samego zapytania nie wplywa znaczaco na utrate wydajnosci (nie w kontekscie calego proceszu potrzebnego przez silnik na wygenerowaniu planu itd)

Oczywiscie znam pulapki jak i obejscia, ale Dynamiczne zapytania to temat na dluga rozmowe. Jak ktos zainteresowany to dla SQL Servera polecam: https://www.sommarskog.se/dynamic_sql.html

KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:5 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
0
yarel napisał(a):

Jeśli Kazio wstawi order=123, a Zosia order=456, to masz 2 różne zapytania.

Ale takich zapytań się nie generuje :D O wiele częście są to przypadki gdy jeden szuka po cenie, a drugi po nazwie lub innym kolorze.
Widziałem SQLe poskładane w Javie na ifach na cały ekran w zależności od tego które z 20 parametrów do yszukiwania wypełnił użytkownik


Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
edytowany 2x, ostatnio: KamilAdam
TR
  • Rejestracja:ponad 7 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:700m n.p.m.
  • Postów:677
1

Ja kiedyś dawno tego w MySQLu używałem, i generalnie brzydkie to jest.

Teraz po prostu przy generowaniu warunków mam zmienną która określa czy jest już jakiś warunek, czy nie, i jeżeli jeszcze żadnego nie ma to nie dodaje AND przed początkiem całego warunku.

Przy czym w dobie różnego rodzaju ORMów i gotowych generatorów SQL, to robienie tego własnoręcznie coraz bardziej traci sens.


DRY > SOLID (nie bierz tego zbyt poważnie)
YA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 4 godziny
  • Postów:2367
0

@KamilAdam: nie powinno się takowych generować, ale niestety rzeczywistość pokazuje, że jednak bind variable nie są powszechnie używane i mogą lecieć dwa różne zapytania:
select * from orders where order=123
select * from orders where order=456

W przypadku pól typu wybór wielu wartości, np. Kolor={zielony,czerwony, niebieski} daje to 4 różne zapytania:

  • bez IN,
  • IN (:a),
  • IN (:a,:b),
  • IN (:a,:b,:c) przy użyciu bind variables, a bez takowych to nie chce mi się liczyć kombinacji ;)

Problemem nie jest wówczas Twoja porządna aplikacja, która generuje porządne zapytania, tylko aplikacja, które generuje masę śmiecia, które wyrzucają plan Twojego zapytania z cache silnika bazodanowego.

Jeśli lista do IN nie ma określonej długości (bo jest np. wyciągana z jakiejś konfiguracji, bądź rezultatów wyszukiwania), to ilość zapytań, które ominą cache'a rośnie. Co gorsza, inne sesje mogą być zmuszone do oczekiwania, aż aż taki cache zostanie zaktualizowany. Można, żyć, ale to jak jazda za autobusem, który się zatrzymuje co przystanek, ale nie zjeżdża do wysepki. Można się z tym pogodzić ;)

@Panczo: dla takich zapytań (bez bind variable) MS SQL liczy ten sam hasz? Czy jest sprytny i zakłada, że jak zapytanie przyszło od aplikacji, to i tak wartości należy wyciąć i zastąpić zmiennymi?

Poglądowo:
HASZ(select * from orders where order=123)=123
HASZ(select * from orders where order=456)=456

HASZ(select * from orders where order=:order)=42 /* np. silnik uznał, że aplikacja jest słaba i zastąpił 123, 456 przez zmienną */

PA
  • Rejestracja:ponad 22 lata
  • Ostatnio:około 5 godzin
  • Postów:3866
2

To dziala bardziej topornie bo hash liczy z tekstu zapytania i tak

Kopiuj
--zapytanie 1
select * from orders where order=123

--zapytanie 2
select * from orders Where order=123

Oba beda mialy rozne hashe (zmiana w->W w where), co do twojego przykladu to tu zadziala mechanizm Simple Parameterization gdzie w cachu bedzie:

Kopiuj
select * from orders where order=@1

Mozna tez zmusić silnik do tego by każdą wartość parametryzowal (Forced Parameterization)

Nie jestem specem od oracle ale te wspomniane bind values, po krótkim googlaniu, można przyrownac do sp_executesql z podanymi parametrami, ale dziala dokladnie ten sam mechanizm cacheowania jak dla zapytan adhoc => zmiana tekstu w przekazywanym zapytaniu powoduje wygenerowanie nowego planu

YA
Dzięki, doczytam sobie jak robi to Mssql. W oraclu jest coś podobnego, Cursor sharing, https://docs.oracle.com/cd/B19306_01/server.102/b14237/initparams035.htm#REFRN10025
hauleth
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:10 dni
0

@yarel: ale Ty wiesz, że praktycznie wszystkie biblioteki obecnie używają prepared statements. A prepared statements też nie są lekiem na całe zło i czasem jednak lepiej generować plan dla każdego zapytania osobno.


AdamWox
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 8 godzin
  • Lokalizacja:Jastrzębie-Zdrój
  • Postów:2153
0

Ja cię! Panowie, ja się tylko zapytałem :D a tu debata poważna 😱

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)