Kiedy w Oracle SQL należy używać średnika, a nie ukośnika?

179

W tym tygodniu debatowaliśmy w mojej firmie na temat tego, jak powinniśmy pisać nasze skrypty SQL.

Kontekst: Nasza baza danych to Oracle 10g (wkrótce zostanie zaktualizowana do wersji 11). Nasz zespół DBA używa SQLPlus do wdrażania naszych skryptów do produkcji.

Teraz mieliśmy niedawno wdrożenie, które nie powiodło się, ponieważ użyło zarówno średnika, jak i ukośnika ( /). Średnik znajdował się na końcu każdej instrukcji, a ukośnik między instrukcjami.

alter table foo.bar drop constraint bar1;
/
alter table foo.can drop constraint can1;
/

Niektóre wyzwalacze zostały dodane później w skrypcie, niektóre widoki zostały utworzone, a także niektóre procedury składowane. Posiadanie zarówno polecenia, jak ;i /wywoływało dwukrotne uruchomienie każdej instrukcji, powodując błędy (szczególnie we wstawkach, które musiały być unikalne).

W SQL Developer tak się nie dzieje, w TOAD tak się nie dzieje. Jeśli uruchomisz pewne polecenia, nie będą one działać bez /w nich.

W PL / SQL, jeśli masz podprogram (DECLARE, BEGIN, END) użyty średnik będzie traktowany jako część podprogramu, więc musisz użyć ukośnika.

Więc moje pytanie brzmi: jeśli twoją bazą danych jest Oracle, jaki jest właściwy sposób pisania skryptu SQL? Skoro wiesz, że Twoją bazą danych jest Oracle, czy zawsze powinieneś używać /?

amischiefr
źródło
1
W przypadku, gdy ktoś dokonuje eksportu bazy danych za pomocą SQLDeveloper, istnieje pole wyboru o nazwie „Terminator”, które po zaznaczeniu używa średników do zakończenia każdej instrukcji. Ta opcja jest domyślnie zaznaczona. Un-wybierz usunąć średniki i uniknąć powielania wykonania instrukcji
Ruslans Uralovs
7
Żeby bezcelowo chłostać ten stary wątek na śmierć, wspomnę, że język SQL nie ma średnika. Jest to jedynie charakter domyślny terminator w SQL * Plus (można ustawić sqlterminator, aby !jeśli chcesz) i konwencja ta ma tendencję do być przestrzegane przez innych narzędzi. Jednak język PL / SQL używa średników jako obowiązkowego elementu składni.
William Robertson

Odpowiedzi:

31

To kwestia preferencji, ale wolę widzieć skrypty, które konsekwentnie używają ukośnika - w ten sposób wszystkie „jednostki” pracy (tworzenie obiektu PL / SQL, uruchamianie anonimowego bloku PL / SQL i wykonywanie instrukcji DML) mogą być łatwiej wybierać wzrokiem.

Ponadto, jeśli ostatecznie przejdziesz do czegoś takiego jak Ant w celu wdrożenia, uprości to definicję celów, aby uzyskać spójny ogranicznik instrukcji.

dpbradley
źródło
1
ta odpowiedź nie wyjaśnia, dlaczego /ani nie ;widzisz odpowiedzi @a_horse_with_no_name lub @Mr_Moneybags, aby uzyskać więcej kontekstu
Kay,
333

Wiem, że to stary wątek, ale właśnie się na niego natknąłem i czuję, że nie zostało to do końca wyjaśnione.

W SQL * Plus istnieje ogromna różnica między znaczeniem a /i a, ;ponieważ działają one inaczej.

Te ;końce oświadczenie SQL, podczas gdy /sporządzi co jest na prąd „bufor”. Więc kiedy używasz a ; i a, /instrukcja jest wykonywana dwukrotnie.

Możesz łatwo zobaczyć, że używając /po uruchomieniu instrukcji:

SQL*Plus: Release 11.2.0.1.0 Production on Wed Apr 18 12:37:20 2012

Copyright (c) 1982, 2010, Oracle.  All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning and OLAP options

SQL> drop table foo;

Table dropped.

SQL> /
drop table foo
           *
ERROR at line 1:
ORA-00942: table or view does not exist

W tym przypadku faktycznie zauważa się błąd.


Ale zakładając, że istnieje taki skrypt SQL:

drop table foo;
/

A to jest uruchamiane z poziomu SQL * Plus, wtedy będzie to bardzo mylące:

SQL*Plus: Release 11.2.0.1.0 Production on Wed Apr 18 12:38:05 2012

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning and OLAP options

SQL> @drop

Table dropped.

drop table foo
           *
ERROR at line 1:
ORA-00942: table or view does not exist

Jest /on wymagany głównie do uruchamiania instrukcji, które są osadzone ;jak CREATE PROCEDUREinstrukcja.

koń bez imienia
źródło
2
@amis, jestem nowy w Oracle i mam ten sam problem. To pytanie jest bardzo przydatne, ale wszystkie odpowiedzi zawierały wyjaśnienie „dlaczego” nie jest „najlepszym sposobem” na pracę lub jakikolwiek sposób obejścia tego problemu. Tak więc, jeśli dobrze zrozumiałem, nie ma sposobu, aby mieć tylko jeden skrypt i zachować go dla wszystkich narzędzi ... czy odkryjesz jakiś sposób?
ceinmart
5
@ceinmart: „najlepszym sposobem” jest zdefiniowanie jednego (i jedynego) narzędzia do wykonywania skryptów SQL - a „poprawność” skryptu jest sprawdzana za pomocą tego narzędzia. Podobnie jak w przypadku posiadania jednego kompilatora dla języka programowania lub jednej określonej wersji środowiska wykonawczego (Java 7, .Net 4.0, PHP 5.x, ...)
a_horse_with_no_name
1
Dobra odpowiedź. Czy to tylko ja, czy też Oracle jest głupkowate i archaiczne w porównaniu z innymi DB? Używałem dużo Sybase i wydaje się to o wiele bardziej intuicyjne.
splashout
1
@splashout: cóż, jeśli chcesz uruchamiać instrukcje zawierające domyślny separator ( ;), musisz znaleźć sposób na określenie alternatywnego separatora
a_horse_with_no_name
97

Chciałem wyjaśnić trochę więcej użycia między ;i/

W SQLPLUS:

  1. ; oznacza "zakończ bieżącą instrukcję, wykonaj ją i zapisz w buforze SQLPLUS"
  2. <newline>po instrukcji DML (SELECT, UPDATE, INSERT, ...) lub niektórych typach instrukcji DDL (tworzenie tabel i widoków) (które nie zawierają ;), oznacza to, że przechowuj instrukcję w buforze, ale nie uruchamiaj jej.
  3. /po wpisaniu instrukcji do bufora (ze spacją <newline>) oznacza „uruchomić DML lub DDL lub PL / SQL w buforze.
  4. RUNlub Rjest komendą sqlsplus, która wyświetla / wyświetla kod SQL w buforze i uruchamia go. Nie zakończy instrukcji SQL.
  5. / podczas wpisywania DML lub DDL lub PL / SQL oznacza "przerwanie aktualnej instrukcji, wykonanie jej i zapisanie do bufora SQLPLUS"

UWAGA: Ponieważ ;są używane dla PL / SQL do zakończenia instrukcji, ;nie mogą być używane przez SQLPLUS w znaczeniu „zakończ bieżącą instrukcję, wykonaj ją i zapisz w buforze SQLPLUS”, ponieważ chcemy, aby cały blok PL / SQL znajdował się całkowicie w bufor, a następnie wykonaj go. Bloki PL / SQL muszą kończyć się:

END;
/
Mr_Moneybags
źródło
22

Prawie wszystkie wdrożenia Oracle są wykonywane przez SQL * Plus (to dziwne małe narzędzie wiersza poleceń, z którego korzysta Twój administrator). A w SQL * Plus samotny ukośnik oznacza w zasadzie „ponownie wykonaj ostatnie polecenie SQL lub PL / SQL, które właśnie wykonałem”.

Widzieć

http://ss64.com/ora/syntax-sqlplus.html

Praktyczną zasadą jest użycie ukośnika w przypadku rzeczy, które działają BEGIN .. ENDlub gdzie możesz użyć CREATE OR REPLACE.

Do wkładek, które wymagają wyjątkowego zastosowania

INSERT INTO my_table ()
SELECT <values to be inserted>
FROM dual
WHERE NOT EXISTS (SELECT 
                  FROM my_table
                  WHERE <identify data that you are trying to insert>)
jva
źródło
14

Z mojego zrozumienia, wszystkie instrukcje SQL nie wymagają ukośnika, ponieważ będą uruchamiane automatycznie na końcu średnika, w tym instrukcje DDL, DML, DCL i TCL.

W przypadku innych bloków PL / SQL, w tym procedur, funkcji, pakietów i wyzwalaczy, ponieważ są to programy wielowierszowe, Oracle potrzebuje sposobu, aby wiedzieć, kiedy uruchomić blok, więc musimy napisać ukośnik na końcu każdego bloku, aby niech Oracle to uruchomi.

Nocnik
źródło
1

Używam ukośnika tylko raz na końcu każdego skryptu, aby powiedzieć sqlplus, że nie ma więcej linii kodu. W środku skryptu nie używam ukośnika.

Jonathan
źródło
Czy więc na końcu zamawiasz rzeczy, które wymagają / (takie jak podprogramy i wyzwalacze)? Co jeśli masz wiele wyzwalaczy? Uruchomiłem test i tylko pierwszy jest wykonywany, chyba że ma / między każdym z nich. Czy coś mi brakuje?
amischiefr,
Staram się tego unikać (jeśli to możliwe), ale jeśli nie mogę (jak w wyzwalaczach), używam średników i ukośników dokładnie tak, jak są używane w oficjalnych skryptach, które generują schematy próbek Oracle: download.oracle.com/docs /cd/B19306_01/server.102/b14198/ ... W przypadku problemu z wstawkami próbuję oddzielić skrypty, które tworzą obiekty, od tych, które zapełniają tabele.
Jonathan,
1
Przepraszamy, ale to nie odpowiada na pytanie.
DerMike