sql >> Databasteknik >  >> RDS >> Oracle

Slash eller ingen Slash?

Det är frågan.

Ett nyligen inlägg på OTN-forumen frågade om användning av semikolon och snedstreck som uttalandeavslutare. Jag dammade av en artikel jag skrev för vårt utvecklingsteam för över 4 år sedan om detta ämne. Den här artikeln fick bra recensioner och finns tillgänglig på OTN-forum om så önskas. Jag tänkte också lägga upp det på min blogg. Här är artikeln:

Snedstreck eller inget snedstreck

av Brian Peasland

På vårt företag exekveras SQL-skript som distribueras i Oracles SQL*Plus kommandoradsverktyg, medan många utvecklare använder ett GUI-verktyg som PL/SQL Developer eller SQL Developer. Snedstrecket betyder något för SQL*Plus som inte behövs i PL/SQL Developer eller SQL Developer. Som sådan kan det vara förvirrande att veta om du behöver inkludera ett snedstreck i dina SQL-skript eller inte. Förhoppningsvis kommer det här avsnittet att kasta lite ljus över vad snedstrecket gör, när det ska användas och när det inte ska användas. Semi-kolon Terminator För de flesta SQL-satser är semikolon satsterminatorn. Tänk till exempel att denna enkla SQL-sats körs i SQL*Plus:

SQL> välj sysdate från dual;

SYSDATE

———

18-JUN-12

När SQL*Plus ser semikolonet vet den att slutet av SQL-satsen har nåtts och den kan nu köra kommandot.

SQL*Plus-buffert

Du kanske inte är medveten om att SQL*Plus har en buffert för sina kommandon. Om jag trycker på 'l'-tangenten för 'lista' kan jag se kommandot för närvarande i min sessions buffert.

SQL> l

1* välj sysdate från dubbel

Inte överraskande finns det kommandot jag just körde. Jag körde sedan en annan SQL-sats och så här ser min buffert ut nu:

SQL> l

1 välj sysdatum, användare

2* från dubbel

Som du kan se har jag nu två rader i min sessions SQL*Plus-buffert.

Snedstreck =Exekvera buffert

Den första regeln att förstå om snedstrecket är att för SQL*Plus betyder snedstrecket att exekvera innehållet i bufferten. För att illustrera detta koncept kommer jag att köra en SQL-sats, vänta några sekunder och sedan bara köra samma SQL-sats igen men bara köra bufferten.

SQL> välj to_char(sysdate,’MM/DD/YYYY HH24:MI:SS’) från dubbel;

TO_CHAR(SYSDATE,’MM

——————-

2012-06-18 15:20:40

SQL> /
TO_CHAR(SYSDATE,’MM

——————-

2012-06-18 15:21:17

SQL> /

TO_CHAR(SYSDATE,’MM

——————-

2012-06-18 15:21:50

Du kan se att allt jag gjorde andra och tredje gången var att bara skriva '/' och trycka på enter och SQL*Plus exekverade innehållet i dess kommandobuffert varje gång.

PL/SQL-block

Semikolonsatsterminatorn fungerade alldeles utmärkt av sig själv tills Oracle introducerade PL/SQL i Oracle version 7. Problemet är att PL/SQL-block kan ha flera semikolon för att avsluta de individuella satserna som utgör blocket. Tänk på detta mycket enkla PL/SQL-block som inte gör något:

SQL> börja

2 null;

3 null;

4 slut;

5

Rad 2 och 3 innehåller helt giltiga påståenden som var och en avslutas med semikolon. Och på rad 4 har vi nyckelordet END som betecknar slutet på PL/SQL-blocket. Om vi ​​inte tilläts kapslade BEGIN/END-par, ser SQL*Plus varje gång "END;" det skulle veta att slutet av PL/SQL-blocket har nåtts, men vi tillåts kapslade BEGIN/END-par så följande är helt lagligt och giltigt:

SQL> börja

2 börjar

3 null;

4 slut;

5 null;

6 slut;

7

Du kan se från ovan att bara leta efter "SLUT"; räcker inte eftersom SQL*Plus skulle ha försökt köra blocket efter rad 4. Så hur bestämde sig Oracle för att ange att PL/SQL-blocket var redo att köras? Svaret är genom att använda snedstrecket som du kanske redan är medveten om. Den andra regeln att förstå är att allt som snedstrecket gör när du använder det för att avsluta ett PL/SQL-block är att säga åt SQL*Plus att köra det som finns i bufferten! Detta har inte ändrats sedan innan PL/SQL skapades för Oracle 7. Tänk på följande exempel:

SQL> börja

2 null;

3 slut;

4 /

PL/SQL-proceduren har slutförts.

SQL> l

1 start
2 null;

3* slut;

På rad 4 skrev jag snedstrecket för att exekvera PL/SQL-blocket. Du kan se att min blockering slutfördes. Om vi ​​går tillbaka och tittar på innehållet i min kommandobuffert kan du se att den innehåller allt utom snedstrecket. Det framåtriktade snedstrecket är inte en del av kommandobufferten. Så nu kör jag ett annat PL/SQL-block:

SQL> börja

2 dbms_output.put_line(‘Idag är ‘||to_char(sysdate,’MM/DD/ÅÅÅÅ HH24:MI:SS’));

3 slut;

4 /

Idag är 06/18/2012 15:39:32

PL/SQL-proceduren har slutförts.

Det framåtriktade snedstrecket sa till SQL*Plus att köra det som finns i dess buffert, och resultaten visas. Låt oss nu bara skriva snedstrecket igen och vi bör se vårt PL/SQL-block köras igen.

SQL> /

Idag är 06/18/2012 15:40:42

PL/SQL-proceduren har slutförts.

Jag behövde inte skriva mitt PL/SQL-block på nytt eftersom det för närvarande finns i kommandobufferten.

PL/SQL- och SQL-utvecklare och PL/SQL-block

Det största problemet för de flesta utvecklare är att PL/SQL-utvecklare och SQL-utvecklare inte kräver att du använder snedstrecket. Varför? Eftersom du kan trycka på Execute (F8) eller Run Script (F5) för att köra ditt PL/SQL-block. PL/SQL-utvecklaren vet att när du trycker på F8, tänker du skicka in PL/SQL-blocket som ska exekveras. I det här fallet gör F8 i PL/SQL Developer samma jobb som snedstrecket i SQL*Plus. På samma sätt för F5 i SQL Developer.

Problemet på mitt företag är att vårt team som distribuerar kod till produktion inte distribuerar kod med PL/SQL-utvecklare eller SQL-utvecklare. De använder SQL*Plus eftersom det är lättare att skripta flera körningar med ett kommandoradsverktyg. Många utvecklare gör misstaget att inte inkludera snedstrecket för PL/SQL-block i skript eftersom de inte behöver det, men om du vill distribuera det kodavsnittet i ett SQL-skript krävs snedstrecket i slutet av varje PL /SQL-block.

När man inte ska använda snedstreck

Så vi har sett när och varför vi använder snedstrecket, men när är det dåligt att använda det? Den tredje regeln att veta är att det är dåligt att använda snedstrecket efter en enda SQL-sats (inte i ett PL/SQL-block), särskilt när det snedstrecket omedelbart följer efter en DML-sats (INSERT, UPDATE eller DELETE). Om mitt skript innehåller följande:

välj sysdate från dubbel;

/

Då får jag "dubbel output" vilket inte är vad jag normalt tänker göra i ett script. Jag vill egentligen bara ha en rad tillbaka, inte två som ovanstående skript skulle göra:

SQL> välj sysdate från dual;

SYSDATE

———

18-JUN-12
SQL> /

SYSDATE

———

18-JUN-12

Det är ännu värre när jag använder snedstrecket efter en DML-sats eftersom den satsen kommer att köras två gånger. Tänk på följande skript:

infoga i test_tab-värden (10);

/

Vi vet nu att när jag kör de två raderna ovan i ett skript kommer SQL*Plus att köra det en gång på grund av semikolonsatsterminatorn och sedan köra en andra gång eftersom snedstrecket säger åt SQL*Plus att köra det som finns i kommandobuffert. När jag kör skriptet med två rader ovan får jag följande utdata:

SQL> infoga i test_tab-värden (10);

1 rad skapad.

SQL>

/

infoga i test_tab-värden (10) *

FEL på rad 1:ORA-00001:unik begränsning (PEASLAND.SYS_C00767176) överträtt

hoppsan! Den första infogningen fungerade (1 rad skapades.) men när snedstrecket angavs försökte SQL*Plus infoga samma data och jag fastnade för en unik överträdelse av begränsningen.

Slutsats

Förhoppningsvis visar den här sidan varför snedstrecket behövs, vad det gör och när det inte ska användas. För att sammanfatta:

  • Inkludera snedstrecket i slutet av varje PL/SQL-block
  • Inkludera inte snedstrecket efter några SQL-satser som inte finns i ett PL/SQL-block.
  • Snedstrecket efter en enskild SQL-sats gör att SQL-kommandot körs två gånger.

  1. Hur implicita transaktioner fungerar i SQL Server

  2. MySQL:Felkod:1118 Radstorleken är för stor (> 8126). Ändra vissa kolumner till TEXT eller BLOB

  3. Fel:välj kommando nekat för användare '<användarid>'@'<ip-adress>' för tabellen '<tabellnamn>'

  4. Använda Jenkins med Kubernetes AWS, del 2