sql >> Databáze >  >> RDS >> Oracle

Lomítko nebo žádné lomítko?

To je otázka.

Nedávný příspěvek na fórech OTN se ptal na používání středníků a lomítek jako terminátorů příkazů. Oprášil jsem článek, který jsem na toto téma napsal pro náš vývojový tým před více než 4 lety. Tento článek získal dobré recenze a v případě potřeby je k dispozici na fórech OTN. Napadlo mě, že to dám také na svůj blog. Zde je článek:

Lomítko nebo žádné lomítko

od Briana Peaslanda

V naší společnosti se skripty SQL, které jsou nasazeny, spouštějí v nástroji příkazového řádku SQL*Plus společnosti Oracle, zatímco mnoho vývojářů používá nástroj GUI, jako je PL/SQL Developer nebo SQL Developer. Dopředné lomítko znamená pro SQL*Plus něco, co není potřeba v PL/SQL Developer nebo SQL Developer. Jako takové může být matoucí vědět, zda potřebujete do skriptů SQL zahrnout lomítko nebo ne. Doufejme, že tato část osvětlí, co dělá lomítko, kdy jej použít a kdy nepoužít. Středník Terminátor U většiny příkazů SQL je středník ukončovacím znakem příkazu. Zvažte například tento jednoduchý příkaz SQL spuštěný v SQL*Plus:

SQL> vyberte sysdate z dual;

SYSDATE

———

18. ČERVNA 12

Když SQL*Plus uvidí středník, ví, že bylo dosaženo konce příkazu SQL, a nyní může příkaz provést.

Vyrovnávací paměť SQL*Plus

Možná si neuvědomujete, že SQL*Plus má vyrovnávací paměť pro své příkazy. Pokud stisknu klávesu ‚l‘ pro ‚seznam‘, uvidím příkaz aktuálně ve vyrovnávací paměti mé relace.

SQL> l

1* vyberte sysdate z dual

Není překvapením, že je zde příkaz, který jsem právě provedl. Potom jsem provedl další příkaz SQL a takto vypadá můj buffer:

SQL> l

1 vyberte sysdate,user

2* od dual

Jak vidíte, nyní mám ve vyrovnávací paměti SQL*Plus své relace dva řádky.

Lomítko =Spustit vyrovnávací paměť

První pravidlo, které je třeba pochopit o dopředném lomítku, je, že pro SQL*Plus znamená lomítko spustit obsah vyrovnávací paměti. Pro ilustraci tohoto konceptu provedu příkaz SQL, počkám několik sekund a pak znovu provedu stejný příkaz SQL, ale pouze spustím vyrovnávací paměť.

SQL> vyberte to_char(sysdate,‘MM/DD/RRRR HH24:MI:SS‘) z dual;

TO_CHAR(SYSDATE;‘MM

——————-

18. 6. 2012 15:20:40

SQL> /
TO_CHAR(SYSDATE,‘MM

——————-

18. 6. 2012 15:21:17

SQL> /

TO_CHAR(SYSDATE;‘MM

——————-

18. 6. 2012 15:21:50

Můžete vidět, že všechno, co jsem udělal podruhé a potřetí, bylo jen napsat „/“ a stisknout Enter a SQL*Plus pokaždé provedl obsah svého příkazového bufferu.

PL/SQL bloky

Ukončovací znak středník fungoval dobře sám o sobě, dokud Oracle nezavedl PL/SQL v Oracle verzi 7. Problém je v tom, že bloky PL/SQL mohou mít více středníků pro ukončení jednotlivých příkazů, které daný blok tvoří. Zvažte tento velmi jednoduchý blok PL/SQL, který nic nedělá:

SQL> začít

2 null;

3 null;

4 konec;

5

Řádky 2 a 3 obsahují dokonale platné příkazy, které jsou zakončeny středníkem. A na řádku 4 máme klíčové slovo END označující konec bloku PL/SQL. Pokud bychom neměli povoleno vnořené páry BEGIN/END, pak pokaždé, když SQL*Plus uvidí „END;“ věděl by, že bylo dosaženo konce bloku PL/SQL, ale máme povoleno vnořené páry BEGIN/END, takže následující je naprosto legální a platné:

SQL> začít

2 začít

3 null;

4 konec;

5 null;

6 konec;

7

Z výše uvedeného můžete říci, že stačí hledat „END;“ nestačí, protože SQL*Plus by se pokusil spustit blok po řádku 4. Jak se tedy Oracle rozhodl naznačit, že blok PL/SQL je připraven ke spuštění? Odpověď je pomocí dopředného lomítka, jak už možná víte. Druhé pravidlo, kterému je třeba porozumět, je, že vše, co dělá lomítko, když ho použijete k ukončení PL/SQL bloku, je říct SQL*Plus, aby spustil to, co je ve vyrovnávací paměti! To se nezměnilo od doby před vytvořením PL/SQL pro Oracle 7. Zvažte následující příklad:

SQL> začít

2 null;

3 konec;

4 /

Procedura PL/SQL byla úspěšně dokončena.

SQL> l

1 begin
2 null;

3* konec;

Na řádku 4 jsem zadal lomítko, abych provedl blok PL/SQL. Můžete vidět, že můj blok byl úspěšně dokončen. Pokud se vrátíme zpět a podíváme se na obsah mého příkazového bufferu, můžete vidět, že obsahuje vše kromě lomítka. Dopředné lomítko není součástí vyrovnávací paměti příkazů. Nyní tedy spustím jiný blok PL/SQL:

SQL> začít

2 dbms_output.put_line(‘Dnes je ‘||to_char(sysdate,’MM/DD/RRRR HH24:MI:SS’));

3 konec;

4 /

Dnes je 18. 6. 2012 15:39:32

Procedura PL/SQL byla úspěšně dokončena.

Dopředné lomítko řeklo SQL*Plus, aby spustil to, co je v jeho vyrovnávací paměti, a zobrazí se výsledky. Nyní znovu napíšeme pouze lomítko a měli bychom vidět, že se náš blok PL/SQL znovu spustí.

SQL> /

Dnes je 18. 6. 2012 15:40:42

Procedura PL/SQL byla úspěšně dokončena.

Nemusel jsem znovu zadávat svůj PL/SQL blok, protože je aktuálně ve vyrovnávací paměti příkazů.

PL/SQL a SQL Developer a PL/SQL bloky

Největším problémem pro většinu vývojářů je, že PL/SQL Developer a SQL Developer nevyžadují, abyste používali lomítko. Proč? Protože blok PL/SQL můžete spustit stisknutím Execute (F8) nebo Run Script (F5). Vývojář PL/SQL ví, že v okamžiku, kdy stisknete F8, máte v úmyslu odeslat blok PL/SQL ke spuštění. V tomto případě F8 v PL/SQL Developer dělá stejnou práci jako lomítko v SQL*Plus. Podobně pro F5 v SQL Developer.

Problém v mé společnosti je, že náš tým nasazující kód do produkce nenasazuje kód s PL/SQL Developerem nebo SQL Developerem. Používají SQL*Plus, protože skriptování vícenásobných spouštění je jednodušší s nástrojem příkazového řádku. Mnoho vývojářů dělá tu chybu, že do skriptů nezahrnují dopředné lomítko pro bloky PL/SQL, protože je nepotřebují, ale pokud chcete nasadit tuto část kódu do skriptu SQL, je lomítko vyžadováno na konci každého PL. /blok SQL.

Kdy nepoužívat lomítko

Takže jsme viděli, kdy a proč používáme lomítko, ale kdy je špatné ho použít? Třetí pravidlo, které je třeba vědět, je, že je špatné používat dopředné lomítko po jediném příkazu SQL (ne v bloku PL/SQL), zvláště když toto lomítko bezprostředně následuje za příkazem DML (INSERT, UPDATE nebo DELETE). Pokud můj skript obsahuje následující:

vyberte sysdate z dual;

/

Pak dostanu „dvojitý výstup“, což není to, co normálně zamýšlím ve skriptu dělat. Opravdu chci vrátit pouze jeden řádek, ne dva, jak by to udělal výše uvedený skript:

SQL> vyberte sysdate z dual;

SYSDATE

———

18-JUN-12
SQL> /

SYSDATE

———

18. ČERVNA 12

Je to ještě horší, když použiji lomítko po příkazu DML, protože tento příkaz bude proveden dvakrát. Zvažte následující skript:

vložit do hodnot test_tab (10);

/

Nyní víme, že když spustím dva výše uvedené řádky ve skriptu, SQL*Plus je provede jednou kvůli ukončení příkazu středníkem a poté se provede podruhé, protože lomítko říká SQL*Plus, aby spustil to, co je v příkazová vyrovnávací paměť. Když spustím výše uvedený dvouřádkový skript, dostanu následující výstup:

SQL> vložit do hodnot test_tab (10);

Byl vytvořen 1 řádek.

SQL>

/

vložte do test_tab hodnoty (10) *

CHYBA na řádku 1:ORA-00001:porušení jedinečného omezení (PEASLAND.SYS_C00767176)

Jejda! První vložení fungovalo (vytvořen 1 řádek.), ale když bylo zadáno lomítko, SQL*Plus se pokusil vložit stejná data a byl jsem zachycen při jedinečném porušení omezení.

Závěr

Doufejme, že tato stránka ukazuje, proč je nutné lomítko, co dělá a kdy jej nepoužívat. Pro rekapitulaci:

  • Zahrňte dopředné lomítko na konec každého bloku PL/SQL
  • Nezahrnujte dopředné lomítko za příkazy SQL, které nejsou v bloku PL/SQL.
  • Lomitko za jedním příkazem SQL způsobí, že se tento příkaz SQL provede dvakrát.

  1. Použití Dapper s Oracle

  2. Přehled klastrování ProxySQL v ClusterControl

  3. CHYBA PostgreSQL:funkce to_tsvector(znak různý, neznámý) neexistuje

  4. Příkaz INSERT v Oracle