Relacje pomiędzy dwiema tabelami - pobieranie danych z użyciem dbExpress

Relacje pomiędzy dwiema tabelami - pobieranie danych z użyciem dbExpress
LA
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:17
0

Witam,

To jest mój pierwszy post tutaj na forum - witam wszystkich i proszę o zrozumienie:)

Mam problem z utworzeniem relacji pomiędzy dwoma tablicami.

Pierwsza tablica to:

Kopiuj
SQLDataSet1.CommandText:='CREATE TABLE users ('+
  'id INT(11) NOT NULL AUTO_INCREMENT,'+
  'name VARCHAR(255) NOT NULL DEFAULT "",'+
  'password VARCHAR(255) NOT NULL DEFAULT "",'+
  'permissions SMALLINT(2) NOT NULL DEFAULT "0",'+
  'UNIQUE KEY id (id)'+
  ') TYPE=MyISAM;';
  if SQLDataSet1.ExecSQL(True) = 0 then ShowMessage('Table users created');

Druga tablica to:

Kopiuj
SQLDataSet1.CommandText:='CREATE TABLE visualcontrol ('+
  'id INT(11) NOT NULL AUTO_INCREMENT,'+
  'number VARCHAR(255) NOT NULL DEFAULT "",'+
  'name VARCHAR(255) NOT NULL DEFAULT "",'+
  'date datetime NOT NULL DEFAULT "0000-00-00 00:00:00",'+
  'result VARCHAR(16) NOT NULL DEFAULT "",'+
  'controller_id INT(11) NOT NULL DEFAULT "0",'+
  'UNIQUE KEY id (id)'+
  ') TYPE=MyISAM;';
  if SQLDataSet1.ExecSQL(True) = 0 then ShowMessage('Table visualcontrol created');

Powstawiałem trochę danych do jednej i drugiej tablicy.

Polecenia:

Kopiuj
SQLDataSet1.CommandText:='SELECT * FROM users';
  SQLDataSet1.Open;

oraz:

Kopiuj
SQLDataSet1.CommandText:='SELECT * FROM visualcontrol';
  SQLDataSet1.Open;

dają poprawne rezultaty i odczytuję te dane tak jak powinny być.

Jednak, gdy chcę nawiązać relację pomiędzy tymi dwiema tablicami, gdzie visualcontrol.controller_id=users.id, tak jak poniżej:

Kopiuj
SQLDataSet1.CommandText:='SELECT visualcontrol.id, visualcontrol.number, visualcontrol.name, visualcontrol.date, visualcontrol.result, visualcontrol.controller_id, users.name FROM (visualcontrol,users) WHERE (visualcontrol.controller_id=users.id)';

wyskakuje błąd, że nieznane jest sformułowanie users.id.

Gdy w klazuli:

Kopiuj
FROM (visualcontrol,users)

zamienię miejscami te dwie tablice, błąd dotyczy wówczas visualcontrol.controller_id.

Podejrzewam, że w jakiś sposób TSQLDataSet obsługuje tylko jedną tablicę z klazuli FROM, a o drugiej nie chce słyszeć.
Zaznaczam, że ta komenda wypisana w phpMyAdmin działa całkiem poprawnie.

Czy ktoś może wie, w jaki sposób można zrobić tę relację, czy lepiej będzie użyć innych komponentów do tego celu (np. ADO?)

Pozdrawiam i dziękuję za podpowiedzi,
Wojtek

dodanie znaczników <code class="delphi"> - furious programming

edytowany 1x, ostatnio: flowCRANE
Zobacz pozostałe 8 komentarzy
LA
Pokaż mi gdzie napisałem że moduł Delphi to skrypt.
flowCRANE
A czy ja napisałem, że to Ty gdzieś napisałeś? Skończmy już tę dyskusję, bo widzę że końca nie będzie; Napisałem ogólnie, co z resztą także Ciebie dotyczy, nazywającego tabele tablicami; Koniec dyskusji - wszystko nazywa się tak, jak się ma nazywać i koniec - nie ma żanych "konwencji", bo tylko wynikłyby z niej nieporozumienia;
KA
@light.archer chyba nie napisałeś a @furious programming chyba zasugerował się moim komentarzem w którym miałem na myśli kogoś innego (nie pamiętam kogo ale widziałem takie rzeczy i to nawet chyba nie u jednej osoby) a napisałem o tym tak przy okazji zwracając uwagę na błędne nazewnictwo.
LA
@kAzek, podziękowałem Ci za uwagę nt tablic i tabel, tylko po prostu nie wiedziałem czemu @furious programming czepia się tych "skryptów delphi". To było niegrzeczne i męczące, zwróciłem uwagę że to jest mój pierwszy temat na tym forum i nie łapałem się do końca o co chodzi.
flowCRANE
Przecież sam ciągnąłeś tę dyskusję, odpowiadając na moje komentarze, więc w czym problem? Trzeba zwracać uwagę, jak ktoś coś źle nazywa - nie jesteś jedynym na tym forum, który użył złych terminów i którego ktoś upomniał;
KA
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 22 godziny
  • Lokalizacja:Gorlice
1

Zdaje się że chodzi o jakiś JOIN ale nie wiem co dokładnie chcesz uzyskać.


Nie odpowiadam na PW w sprawie pomocy programistycznej.
Pytania zadawaj na forum, bo:
od tego ono jest ;) | celowo nie zawracasz gitary | przeczyta to więcej osób a więc większe szanse że ktoś pomoże.
abrakadaber
abrakadaber
  • Rejestracja:ponad 12 lat
  • Ostatnio:7 miesięcy
  • Postów:6610
1

wszystkie nawiasy w tych zapytaniach (select) są zbędne i bardzo możliwe, że to one stanowią problem


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.
LA
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:17
0

Witam,

JOIN służy do permanentnego złączenia tablic. Mi chodzi o to, aby kolumnę w tablicy 1 (visualcontrol.controller_id) zastąpić kolumną z tablicy 2 (users.name). Do tego służy relacja pomiędzy tablicami, i chodzi o to, że wpisując to polecenie (nieważne czy z nawiasami czy bez) poprzez phpMyAdmin poprawnie działa, a poprzez dbExpress w Delphi już nie.

_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
0
light.archer napisał(a):

JOIN służy do permanentnego złączenia tablic.
Kto ci takich głupot naopowiadał.
Usuń nawiasy.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
1
light.archer napisał(a):

Witam,
JOIN służy do permanentnego złączenia tablic.

W Twojej mózgownicy chyba...

Mi chodzi o to, aby kolumnę w tablicy 1 (visualcontrol.controller_id) zastąpić kolumną z tablicy 2 (users.name). Do tego służy relacja pomiędzy tablicami,

Do tego właśnie służy JOIN, a dokladnie LEFT JOIN. Relacja to jest zupelnie co innego, wg ISO relacja to de-facto tabela (tu kopara w dół, ale zanim coś napiszesz doczytaj...).
Ty pewnie masz na myśli jeszce co innego, a mianowci kluicze obce. I one służą, mniej więcej, do tego co napisałeś...

i chodzi o to, że wpisując to polecenie (nieważne czy z nawiasami czy bez) poprzez phpMyAdmin poprawnie działa, a poprzez dbExpress w Delphi już nie.

I to jest problem bo powinno działać i w dbExpress. Ciekawe po co ktoś jeszcze tego badziewia używa?
No ale nic, może da sie to ogarnąć wpsiując dodatkowe parametry do połączenia, ale na pewno zadziała tak:

Kopiuj
SELECT VC.id,
       VC.number,
       VC.name,
       VC.date,
       VC.result,
       VC.controller_id,
       U.name
FROM visualcontrol VC 
lef join users U on U.id = VC.controller_id
edytowany 1x, ostatnio: flowCRANE
LA
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:17
0

Witam,

Dziękuję bardzo za odpowiedzi (i mycie głowy)

Poprawny kod wykorzystując komponent TSQLDataSet powinien wyglądać tak:

Kopiuj
SQLDataSet1.CommandText:='SELECT VC.id, VC.number, VC.name, VC.date, VC.result, VC.controller_id, U.controller_name FROM visualcontrol VC LEFT JOIN users U ON U.id=VC.controller_id';
SQLDataSet1.Open;

Następnie aby odczytywać kolejne rekordy (do StringGrida), należy:

Kopiuj
StringGrid2.RowCount:=SQLDataSet1.RecordCount+1;
  StringGrid2.Cells[0,0]:='Id';
  StringGrid2.Cells[1,0]:='Number';
  StringGrid2.Cells[2,0]:='Name';
  StringGrid2.Cells[3,0]:='Date';
  StringGrid2.Cells[4,0]:='Result';
  StringGrid2.Cells[5,0]:='Controller ID';
  StringGrid2.Cells[6,0]:='Controller name';
  For i:=0 to SQLDataSet1.RecordCount-1 do
  Begin
    StringGrid2.Cells[0,i+1]:=SQLDataSet1.FieldValues['id'];
    StringGrid2.Cells[1,i+1]:=SQLDataSet1.FieldValues['number'];
    StringGrid2.Cells[2,i+1]:=SQLDataSet1.FieldValues['name'];
    StringGrid2.Cells[3,i+1]:=SQLDataSet1.FieldValues['date'];
    StringGrid2.Cells[4,i+1]:=SQLDataSet1.FieldValues['result'];
    StringGrid2.Cells[5,i+1]:=SQLDataSet1.FieldValues['controller_id'];
    StringGrid2.Cells[6,i+1]:=SQLDataSet1.FieldValues['controller_name'];
    SQLDataSet1.Next;
  End;
  SQLDataSet1.Close;

Przy czym jest tutaj pułapka, aby nazwy kolumn (nawet w różnych tabelach) miały inne nazwy (pierwotnie w tabeli visualcontrol i users była ta sama kolumna name, ale w tym przypadku musiałem w tabeli users zmienić ją na controller_name).

Skoro kolega powiedział, że dbexpress to badziew i ja chyba jestem jedynym, który go używa, to czy mógłby zasugerować inny "engine", który pozwoli na komercyjne zastosowanie?

Pozdrawiam i dziękuję bardzo za pomoc.

GS
  • Rejestracja:ponad 14 lat
  • Ostatnio:około 9 godzin
0

pomijam problem zapytania do bazy , ale czy do pobrania danych z wyniku zapytania nie była by lepsza konstrukcja :

Kopiuj
if not SQLDataSet1.isempty then 
begin
   while not SQLDataSet1.eof do 
     begin
        /// tutaj odczyt i podstawienie do zmiennych 
        ///
       SQLDataSet1.next
     end
end
LA
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:17
0

Mogłaby być lepsza, ale i tak potrzebowałem zmiennej i aby wstawiać do kolejnych wierszy StringGrida.

olesio
  • Rejestracja:prawie 17 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Szczecin
  • Postów:4191
0

No to co za problem zwiększać sobie zmienną pomocniczą w pętli while ... do i przypisywać do kolejnych wierszy StringGrid. Musisz się ogarnąć. Przecież już tak proste rzeczy jak operacje na komponencie w pętli, nawet niezwiązane z bazą danych toż to banalne i elementarne podstawy podstaw :/


Pozdrawiam.
Zobacz pozostałe 2 komentarze
LA
Skorzystałem z metody for ponieważ opierałem się na artykule Adama Boducha w Kompendium (Rozdział 17). O tej drugiej metodzie słyszę dopiero tutaj po raz pierwszy, i dlatego się pytałem czy jest w czymś lepsza? Nie chcę robić niepotrzebnej dyskusji, tylko pytam się... Nie sugeruj się tylko tym, jakobym nie potrafił robić różnych pętli.
GS
ponieważ wywołałem temat , więc się wtrącę :) używam konstrukcji "While.... do" ponieważ nie miałem pewności czy każdy silnik bazodanowy zawsze zwraca liczbę wierszy którą zawiera wynik zapytania . być może był to mój błąd i niewiedza, ale rozwiązanie z pętlą "while ... do" było od tego niezależne, czytam dopóki są jakieś dane do odczytania
LA
O dzięki, czyli po prostu możemy się zabezpieczać przed tym, że składnia SQLDataSet1.RecordCount może zawierać nieprawidłową liczbę. Jednak zauważyłbym, że jeśli następuje jakieś przerwanie w transmisji tego zestawu danych z serwera, to również i drugie rozwiązanie z dużym prawdopodobieństwem padnie - nie zawsze zerwanie musi nastąpić z pełnym wierszem tabeli.
GS
@light.archer. Oczywiście że padnie , trzeba to opakować w "try except end" i odpowiednio obsłużyć powstały wyjątek
WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
0
light.archer napisał(a):

Witam,

Dziękuję bardzo za odpowiedzi (i mycie głowy)

Poprawny kod wykorzystując komponent TSQLDataSet powinien wyglądać tak:

Kopiuj
SQLDataSet1.CommandText:='SELECT VC.id, VC.number, VC.name, VC.date, VC.result, VC.controller_id, U.controller_name FROM visualcontrol VC LEFT JOIN users U ON U.id=VC.controller_id';
SQLDataSet1.Open;

Następnie aby odczytywać kolejne rekordy (do StringGrida), należy:

Kopiuj
StringGrid2.RowCount:=SQLDataSet1.RecordCount+1;
  StringGrid2.Cells[0,0]:='Id';
  StringGrid2.Cells[1,0]:='Number';
  StringGrid2.Cells[2,0]:='Name';
  StringGrid2.Cells[3,0]:='Date';
  StringGrid2.Cells[4,0]:='Result';
  StringGrid2.Cells[5,0]:='Controller ID';
  StringGrid2.Cells[6,0]:='Controller name';
  For i:=0 to SQLDataSet1.RecordCount-1 do
  Begin
    StringGrid2.Cells[0,i+1]:=SQLDataSet1.FieldValues['id'];
    StringGrid2.Cells[1,i+1]:=SQLDataSet1.FieldValues['number'];
    StringGrid2.Cells[2,i+1]:=SQLDataSet1.FieldValues['name'];
    StringGrid2.Cells[3,i+1]:=SQLDataSet1.FieldValues['date'];
    StringGrid2.Cells[4,i+1]:=SQLDataSet1.FieldValues['result'];
    StringGrid2.Cells[5,i+1]:=SQLDataSet1.FieldValues['controller_id'];
    StringGrid2.Cells[6,i+1]:=SQLDataSet1.FieldValues['controller_name'];
    SQLDataSet1.Next;
  End;
  SQLDataSet1.Close;

Nie do końca się z tym zgadzam...
Może tak - jednym z wielu poprawnych rozwiązań ładowania danych z TDataSet do StringGrida jest taka procedura:

Kopiuj
procedure LoadData(AStringGrid: TStringGrid; ADS: TDataSet);
var
  lCol  : Integer;
  lField: TField;
begin
  AStringGrid.ColCount  := ADS.FieldCount;
  AStringGrid.RowCount  := 1;

  lCol := 0;
  for lField in ADS.Fields do
  begin
    AStringGrid.Cells[lCol, 0] := lField.DisplayLabel;
    AStringGrid.Cols[lCol].BeginUpdate;
    Inc(lCol);
  end;

  ADS.First;
  ADS.DisableControls;
  try
    while not ADS.Eof do
    begin
      lCol := 0;
      for lField in ADS.Fields do
      begin
        AStringGrid.Cells[lCol, AStringGrid.RowCount] := lField.Text;
        Inc(lCol);
      end;

      ADS.Next;
      AStringGrid.RowCount := AStringGrid.RowCount + 1;
    end;
  finally
    ADS.EnableControls;
  end;

  lCol := 0;
  for lCol := 0 to AStringGrid.Color - 1 do
    AStringGrid.Cols[lCol].EndUpdate;

  AStringGrid.FixedCols := 1;
  AStringGrid.FixedRows := 1;
end;

Zauważ, że to załaduje Ci dane z DataSeta o dowolnej strukturze. Łatwo to uzupełnić o takie rzeczy jak ładowanie tylko widocznych kolumn, lub tylko kolumn które chcemy ładować; Twój kod nie jest ani fajny ani do końca poprawny (DataSet.FieldValues zwraca Variant, wystarczy że pojawi się wartość null i Twój kod leci w kosmos.)

Przy czym jest tutaj pułapka, aby nazwy kolumn (nawet w różnych tabelach) miały inne nazwy (pierwotnie w tabeli visualcontrol i users była ta sama kolumna name, ale w tym przypadku musiałem w tabeli users zmienić ją na controller_name).

A po co mają mieć różne nazwy? Uważam, że ta sama informacja w różnych tabelach powinna mieć tą samą nazwę kolumny.

Skoro kolega powiedział, że dbexpress to badziew i ja chyba jestem jedynym, który go używa, to czy mógłby zasugerować inny "engine", który pozwoli na komercyjne zastosowanie?

FireDAC - na przykład.

LA
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:17
0

@wloochacz, dzięki za odpowiedź. Ponieważ ten post odbiega już od głównego tematu tego wątku, czy można np. zmienić temat (dopisać o pobieraniu danych z użyciem dbexpress)?

Swoją drogą, jak piszesz, że jest to jeden z wielu poprawnych sposobów. Jak widzę, podobne rozwiązanie, z wykorzystaniem

Kopiuj
 while not ADS.Eof do

jest opisane w MySQL w Delphi, z tym że nie ma nic tam wspomnianego o tym, żeby stosować typ TField. Opisano to tak:

Kopiuj
 while not DM.SQLDataSet1.Eof do begin // petla
           id := DM.SQLDataSet1.FieldValues['id']; // przypisujemy wartości rekordu do zmiennych
           imie := DM.SQLDataSet1.FieldValues['imie'];
           nazwisko := DM.SQLDataSet1.FieldValues['nazwisko'];
           gg := DM.SQLDataSet1.FieldValues['gg'];
           telefon := DM.SQLDataSet1.FieldValues['telefon'];

W artykule Adama Boducha, o czym wspomniałem wcześniej w komentarzu pod postem (Rozdział 17),, jest napisane dokładnie tak jak sugerowałem:

Kopiuj
 for I := 1 to SQL.RecordCount do
  begin
  { dodaj kolejne wartości }
    ListItem := ListView.Items.Add;
    ListItem.Caption := IntToStr(SQL.FieldValues['id']);
    ListItem.SubItems.Add(SQL.FieldValues['name']);
    ListItem.SubItems.Add(SQL.FieldValues['mail']);
    SQL.Next;
  end;

W każdym razie bardzo dziękuję za pomoc, Twoja propozycja jest bardzo ciekawa. Czy mógłbyś mi powiedzieć, skąd o tym się dowiedziałeś/nauczyłeś?

edytowany 1x, ostatnio: light.archer
flowCRANE
Dopisałem do tytułu wątku to, co podałeś; Chyba nawet sam możesz zmienić tytuł, przechodząc do pełnej edycji pierwszego posta; Ale nie pamiętam, bo już dość długo mam szersze uprawnienia, więc musiałbyś sprawdzić;
LA
Dzięki, rzeczywiście tak mogę
WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
0
light.archer napisał(a):

@wloochacz, dzięki za odpowiedź. Ponieważ ten post odbiega już od głównego tematu tego wątku, czy można np. zmienić temat (dopisać o pobieraniu danych z użyciem dbexpress)?

Swoją drogą, jak piszesz, że jest to jeden z wielu poprawnych sposobów. Jak widzę, podobne rozwiązanie, z wykorzystaniem

Kopiuj
 while not ADS.Eof do

jest opisane w MySQL w Delphi, z tym że nie ma nic tam wspomnianego o tym, żeby stosować typ TField. Opisano to tak:

Spójrz w kod TDataSet.FieldValues, a zobaczysz że używany jest tam TField i to dodatkowo dość naokoło... Po prostu FieldValues napisano po to, aby za jednym zamachem zwrócić wiele wartości z wielu pól jako wektor (tu - jednowymiarowa tablica Variantów).

Kopiuj
 while not DM.SQLDataSet1.Eof do begin // petla
           id := DM.SQLDataSet1.FieldValues['id']; // przypisujemy wartości rekordu do zmiennych
           imie := DM.SQLDataSet1.FieldValues['imie'];
           nazwisko := DM.SQLDataSet1.FieldValues['nazwisko'];
           gg := DM.SQLDataSet1.FieldValues['gg'];
           telefon := DM.SQLDataSet1.FieldValues['telefon'];

W artykule Adama Boducha, o czym wspomniałem wcześniej w komentarzu pod postem (Rozdział 17),, jest napisane dokładnie tak jak sugerowałem:

Kopiuj
 for I := 1 to SQL.RecordCount do
  begin
  { dodaj kolejne wartości }
    ListItem := ListView.Items.Add;
    ListItem.Caption := IntToStr(SQL.FieldValues['id']);
    ListItem.SubItems.Add(SQL.FieldValues['name']);
    ListItem.SubItems.Add(SQL.FieldValues['mail']);
    SQL.Next;
  end;

Tyle, że ten kod w poradniku jest nie tyle błędny, co nie do końca bezpieczny (korzystanie z Variant bez testowania czy jest null/unassigned, opieranie się na RecordCount, i pewnie wiele innych - nie czytałem całego), a cały poradnik powinien być... przepisany ;-)

W każdym razie bardzo dziękuję za pomoc, Twoja propozycja jest bardzo ciekawa. Czy mógłbyś mi powiedzieć, skąd o tym się dowiedziałeś/nauczyłeś?

Skąd wiem? Po prostu, programuję od dość dawna i coś tam, zwłaszcza o bazach danych w Delphi, wiem ;-)

LA
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:17
0

Dzięki za szybką odpowiedź.

Jeśli chodzi o pytanie, czemu nadałem inne nazwy tych kolumn, to wynikało z tego:

Kopiuj
    StringGrid2.Cells[0,i+1]:=SQLDataSet1.FieldValues['id'];
    StringGrid2.Cells[1,i+1]:=SQLDataSet1.FieldValues['number'];
    StringGrid2.Cells[2,i+1]:=SQLDataSet1.FieldValues['name'];
    StringGrid2.Cells[3,i+1]:=SQLDataSet1.FieldValues['date'];
    StringGrid2.Cells[4,i+1]:=SQLDataSet1.FieldValues['result'];
    StringGrid2.Cells[5,i+1]:=SQLDataSet1.FieldValues['controller_id'];
    StringGrid2.Cells[6,i+1]:=SQLDataSet1.FieldValues['controller_name'];

Nie dało się po prostu rozróżnić w tym przypadku tych kolumn, nie da się użyć visualcontrol.name czy users.name...

WL
  • Rejestracja:około 21 lat
  • Ostatnio:około 2 miesiące
  • Postów:1082
0
light.archer napisał(a):

Nie dało się po prostu rozróżnić w tym przypadku tych kolumn, nie da się użyć visualcontrol.name czy users.name...

OK, ale chodzi o to, że zmiana nazwy kolumny w tabeli jest niepotrzebna. Przecież zawsze możesz w SQL skorzystać z operatora AS, aby zmienić nazwę zwracanej kolumny dla danego zapytania, a więc:

Kopiuj
SELECT VC.id,
       VC.number,
       VC.name,
       VC.date,
       VC.result,
       VC.controller_id,
       U.name as controller_name
FROM visualcontrol VC
LEFT JOIN users U ON (U.id = VC.controller_id)
LA
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:17
0

Dzięki :)

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)