Oto jest pytanie.
Niedawny post na forach OTN pytał o używanie średników i ukośników jako terminatorów instrukcji. Odkurzyłem artykuł, który napisałem dla naszego zespołu programistów ponad 4 lata temu na ten temat. Ten artykuł otrzymał dobre recenzje i jest dostępny na forach OTN w razie potrzeby. Pomyślałem, że opublikuję to również na moim blogu. Oto artykuł:
Ukośnik lub bez ukośnika
autorstwa Briana Peaslanda
W naszej firmie skrypty SQL, które są wdrażane, są wykonywane w narzędziu wiersza poleceń Oracle SQL*Plus, podczas gdy wielu programistów korzysta z narzędzi GUI, takich jak PL/SQL Developer lub SQL Developer. Ukośnik oznacza dla SQL*Plus coś, co nie jest potrzebne w PL/SQL Developer lub SQL Developer. W związku z tym wiedza o tym, czy w skryptach SQL musisz zawierać ukośnik, może być myląca. Mamy nadzieję, że ta sekcja rzuci trochę światła na to, co robi ukośnik, kiedy go używać, a kiedy nie. Terminator średnika W przypadku większości instrukcji SQL średnik jest terminatorem instrukcji. Rozważmy na przykład tę prostą instrukcję SQL uruchomioną w SQL*Plus:
SQL> wybierz sysdate z dual;
SYSDATE
———
18-CZE-12
Kiedy SQL*Plus widzi średnik, wie, że osiągnięto koniec instrukcji SQL i może teraz wykonać polecenie.
Bufor SQL*Plus
Możesz nie wiedzieć, że SQL*Plus ma bufor dla swoich poleceń. Jeśli nacisnę klawisz „l” dla „listy”, zobaczę polecenie aktualnie w buforze mojej sesji.
SQL> l
1* wybierz sysdate z podwójnego
Nic dziwnego, że właśnie wykonałem polecenie. Następnie wykonałem kolejną instrukcję SQL i oto jak teraz wygląda mój bufor:
SQL> l
1 wybierz datę systemową, użytkownik
2* od podwójnego
Jak widać, mam teraz dwie linie w buforze SQL*Plus mojej sesji.
Ukośnik =Wykonaj bufor
Pierwszą zasadą, którą należy zrozumieć o ukośniku, jest to, że dla SQL*Plus ukośnik oznacza wykonanie zawartości bufora. Aby zilustrować tę koncepcję, wykonam instrukcję SQL, poczekam kilka sekund, a następnie ponownie wykonam tę samą instrukcję SQL, ale tylko wykonam bufor.
SQL> wybierz to_char(sysdate,’MM/DD/RRRR HH24:MI:SS’) z dual;
TO_CHAR(SYSDATE,’MM
)——————-
18.06.2012 15:20:40
SQL> /
TO_ZNAK(SYSDATE;'MM
——————-
18.06.2012 15:21:17
SQL> /
TO_CHAR(SYSDATE,’MM
)——————-
18.06.2012 15:21:50
Widać, że wszystko, co zrobiłem drugi i trzeci raz, to po prostu wpisanie „/” i naciśnięcie enter, a SQL*Plus za każdym razem wykonał zawartość swojego bufora poleceń.
Bloki PL/SQL
Terminator instrukcji średnika działał sam, dopóki Oracle nie wprowadziło PL/SQL w wersji Oracle 7. Problem polega na tym, że bloki PL/SQL mogą mieć wiele średników, aby zakończyć poszczególne instrukcje, które tworzą ten blok. Rozważ ten bardzo prosty blok PL/SQL, który nic nie robi:
SQL>rozpocznij
2 brak;
3 brak;
4 koniec;
5
Wiersze 2 i 3 zawierają całkowicie poprawne instrukcje, z których każda jest zakończona średnikiem. W wierszu 4 mamy słowo kluczowe END oznaczające koniec bloku PL/SQL. Jeśli nie wolno nam było zagnieżdżać par BEGIN/END, to za każdym razem SQL*Plus widzi „END;” wiedziałby, że osiągnięto koniec bloku PL/SQL, ale wolno nam zagnieżdżać pary BEGIN/END, więc poniższe jest całkowicie legalne i poprawne:
SQL>rozpocznij
2 początek
3 brak;
4 koniec;
5 brak;
6 koniec;
7
Z powyższego można wywnioskować, że po prostu szukam „KONIEC”; to za mało, ponieważ SQL*Plus próbowałby uruchomić blok po wierszu 4. Jak więc firma Oracle zdecydowała się oznaczyć, że blok PL/SQL jest gotowy do wykonania? Odpowiedzią jest użycie prawego ukośnika, o czym być może już wiesz. Drugą zasadą, którą należy zrozumieć, jest to, że ukośnik używany do zakończenia bloku PL/SQL polega na tym, aby nakazać SQL*Plus uruchomienie tego, co znajduje się w buforze! Nie zmieniło się to od czasu utworzenia PL/SQL dla Oracle 7. Rozważmy następujący przykład:
SQL>rozpocznij
2 brak;
3 koniec;
4 /
Procedura PL/SQL zakończona pomyślnie.
SQL> l
1 początek
2 null;
3* koniec;
W wierszu 4 wpisałem ukośnik, aby wykonać blok PL/SQL. Widać, że mój blok został pomyślnie zakończony. Jeśli cofniemy się i spojrzymy na zawartość mojego bufora poleceń, zobaczysz, że zawiera on wszystko oprócz ukośnika. Ukośnik nie jest częścią bufora poleceń. Więc teraz uruchomię inny blok PL/SQL:
SQL>rozpocznij
2 dbms_output.put_line('Dzisiaj jest'||to_char(sysdate,'MM/DD/RRRR HH24:MI:SS'));
3 koniec;
4 /
Dzisiaj jest 18.06.2012 15:39:32
Procedura PL/SQL zakończona pomyślnie.
Ukośnik mówi do SQL*Plus, aby uruchomił zawartość bufora, a wyniki są wyświetlane. Teraz wpiszmy ponownie tylko ukośnik i powinniśmy zobaczyć, jak nasz blok PL/SQL zostanie ponownie wykonany.
SQL> /
Dzisiaj jest 18.06.2012 15:40:42
Procedura PL/SQL zakończona pomyślnie.
Nie musiałem wpisywać mojego bloku PL/SQL od nowa, ponieważ znajduje się on obecnie w buforze poleceń.
PL/SQL i SQL Developer oraz bloki PL/SQL
Największym problemem większości programistów jest to, że PL/SQL Developer i SQL Developer nie wymagają używania ukośnika. Czemu? Ponieważ możesz nacisnąć Wykonaj (F8) lub Uruchom skrypt (F5), aby uruchomić swój blok PL/SQL. Programista PL/SQL wie, że w momencie naciśnięcia klawisza F8 zamierzasz przesłać blok PL/SQL do wykonania. W tym przypadku klawisz F8 w PL/SQL Developer wykonuje to samo zadanie, co ukośnik w SQL*Plus. Podobnie dla F5 w SQL Developer.
Problem w mojej firmie polega na tym, że nasz zespół wdrażający kod do produkcji nie wdraża kodu za pomocą PL/SQL Developer lub SQL Developer. Używają SQL*Plus, ponieważ skrypty wielu wykonań są łatwiejsze dzięki narzędziu wiersza poleceń. Wielu programistów popełnia błąd polegający na nieuwzględnianiu ukośnika dla bloków PL/SQL w skryptach, ponieważ go nie potrzebują, ale jeśli chcesz wdrożyć tę sekcję kodu w skrypcie SQL, ukośnik jest wymagany na końcu każdego PL Blok /SQL.
Kiedy nie używać ukośnika
Widzieliśmy więc, kiedy i dlaczego używamy ukośnika, ale kiedy jest źle go używać? Trzecią zasadą, o której trzeba wiedzieć, jest to, że używanie ukośnika następującego po pojedynczej instrukcji SQL (nie w bloku PL/SQL) jest złe, zwłaszcza gdy ten ukośnik następuje bezpośrednio po instrukcji DML (INSERT, UPDATE lub DELETE). Jeśli mój skrypt zawiera następujące elementy:
wybierz sysdate z dual;
/
Wtedy otrzymam „podwójne wyjście”, co nie jest tym, co normalnie zamierzam robić w skrypcie. Naprawdę chcę zwrócić tylko jedną linię, a nie dwie, jak zrobiłby powyższy skrypt:
SQL> wybierz sysdate z dual;
SYSDATE
———
18-CZE-12
SQL> /
SYSDATE
———
18-CZE-12
Jeszcze gorzej jest, gdy używam ukośnika następującego po instrukcji DML, ponieważ ta instrukcja zostanie wykonana dwukrotnie. Rozważ następujący skrypt:
wstaw do test_tab wartości (10);
/
Teraz wiemy, że kiedy wykonuję dwie powyższe linie w skrypcie, SQL*Plus wykona je raz ze względu na terminator instrukcji średnika, a następnie wykona drugi raz, ponieważ ukośnik mówi SQL*Plus, aby uruchomić to, co jest w bufor poleceń. Kiedy wykonuję powyższy dwuwierszowy skrypt, otrzymuję następujące dane wyjściowe:
SQL> wstawiamy do test_tab wartości (10);
Utworzono 1 wiersz.
SQL>
/
wstaw do test_tab wartości (10) *
BŁĄD w wierszu 1:ORA-00001:naruszone ograniczenie unikatowe (PEASLAND.SYS_C00767176)
Ups! Pierwsze wstawienie zadziałało (utworzono 1 wiersz), ale kiedy wprowadzono ukośnik, SQL*Plus próbował wstawić te same dane i zostałem złapany na naruszeniu unikatowego ograniczenia.
Wniosek
Mamy nadzieję, że ta strona pokazuje, dlaczego ukośnik jest potrzebny, co robi i kiedy go nie używać. Podsumowując:
- Dołącz ukośnik na końcu każdego bloku PL/SQL
- Nie dołączaj ukośnika po żadnych instrukcjach SQL spoza bloku PL/SQL.
- Ukośnik po pojedynczej instrukcji SQL spowoduje dwukrotne wykonanie tego polecenia SQL.