¿Cuándo necesito usar un punto y coma frente a una barra diagonal en Oracle SQL?

179

Hemos tenido un debate esta semana en mi compañía sobre cómo debemos escribir nuestros scripts SQL.

Antecedentes: nuestra base de datos es Oracle 10g (se actualizará a 11 pronto). Nuestro equipo de DBA utiliza SQLPlus para implementar nuestros scripts en producción.

Ahora, tuvimos un despliegue recientemente que falló porque había usado tanto un punto y coma como una barra diagonal ( /). El punto y coma estaba al final de cada declaración y la barra inclinada estaba entre declaraciones.

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

Hubo algunos desencadenantes que se agregaron más adelante en el script, se crearon algunas vistas y algunos procedimientos almacenados. Tener tanto el ;y el /causó que cada instrucción se ejecute dos veces causando errores (especialmente en las inserciones, que debían ser únicas).

En SQL Developer esto no sucede, en TOAD esto no sucede. Si ejecuta ciertos comandos, no funcionarán sin /ellos.

En PL / SQL si tiene un subprograma (DECLARE, BEGIN, END), el punto y coma utilizado se considerará parte del subprograma, por lo que debe usar la barra diagonal.

Entonces mi pregunta es esta: si su base de datos es Oracle, ¿cuál es la forma correcta de escribir su script SQL? Ya que sabe que su base de datos es Oracle, ¿debe usar siempre el /?

amischiefr
fuente
1
En caso de que alguien esté haciendo una exportación de base de datos con SQLDeveloper, hay una casilla de verificación llamada "Terminator" que, cuando se selecciona, utiliza punto y coma para terminar cada declaración. Esta opción es seleccionada por defecto. Anule la selección para eliminar puntos y comas y para evitar la ejecución de instrucciones duplicadas
Ruslans Uralovs
77
Solo para inutilizar este viejo hilo hasta la muerte, mencionaré que el lenguaje SQL no tiene punto y coma. Es simplemente el carácter terminador predeterminado en SQL * Plus (se puede establecer sqlterminatora !si lo desea) y esta convención tiende a ser seguido por otras herramientas. Sin embargo, el lenguaje PL / SQL usa punto y coma como elemento de sintaxis obligatoria.
William Robertson

Respuestas:

31

Es una cuestión de preferencia, pero prefiero ver secuencias de comandos que usen sistemáticamente la barra diagonal - de esta manera todas las "unidades" de trabajo (crear un objeto PL / SQL, ejecutar un bloque anónimo PL / SQL y ejecutar una declaración DML) pueden ser elegido más fácilmente a simple vista.

Además, si eventualmente se muda a algo como Ant para su implementación, simplificará la definición de objetivos para tener un delimitador de enunciado consistente.

dpbradley
fuente
1
esta respuesta no explica por qué /ni ;ve la respuesta de @a_horse_with_no_name o @Mr_Moneybags para más contexto
Kay
333

Sé que este es un hilo viejo, pero me topé con él y siento que esto no se ha explicado por completo.

Hay una gran diferencia en SQL * Plus entre el significado de a /y a ;porque funcionan de manera diferente.

Los ;extremos de una sentencia SQL, mientras que las /ejecuta lo que está en la corriente "buffer". Así que cuando se utiliza una ; y una /la declaración es en realidad ejecuta dos veces.

Puede verlo fácilmente usando un /después de ejecutar una declaración:

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

En este caso, uno realmente nota el error.


Pero suponiendo que haya un script SQL como este:

drop table foo;
/

Y esto se ejecuta desde SQL * Plus, entonces esto será muy confuso:

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

Se /requiere principalmente para ejecutar declaraciones que se han incrustado ;como una CREATE PROCEDUREdeclaración.

un caballo sin nombre
fuente
2
@amis, soy nuevo en Oracle y me meto en el mismo problema. Esta pregunta es muy útil, pero todas las respuestas dieron una explicación sobre el "por qué", no la "mejor manera" de trabajar o alguna forma de solucionarlo. Entonces, si entendí bien, no hay forma de tener un solo script y mantenerlo utilizable para todas las herramientas ... ¿o descubres alguna forma?
ceinmart
55
@ceinmart: la "mejor manera" es definir una (y solo una) herramienta para ejecutar scripts SQL, y la "corrección" de un script se valida con esa herramienta. Similar a tener un compilador para su lenguaje de programación o una versión específica de su entorno de ejecución (Java 7, .Net 4.0, PHP 5.x, ...)
a_horse_with_no_name
1
Buena respuesta. ¿Soy solo yo o Oracle es tonto y arcaico en comparación con otros DB? He usado mucho Sybase y parece mucho más intuitivo.
splashout
1
@splashout: bueno, si desea ejecutar declaraciones que contengan el delimitador predeterminado ( ;), entonces debe encontrar una manera de especificar un delimitador alternativo
a_horse_with_no_name
97

Quería aclarar un poco más de uso entre el ;y el/

En SQLPLUS:

  1. ; significa "terminar la declaración actual, ejecutarla y almacenarla en el búfer SQLPLUS"
  2. <newline>después de una instrucción DML (SELECCIONAR, ACTUALIZAR, INSERTAR ...) o algunos tipos de instrucciones DDL (Creación de tablas y vistas) (que no contienen ;), significa, almacenar la instrucción en el búfer pero no ejecutarla.
  3. /después de ingresar una declaración en el búfer (con un espacio en blanco <newline>) significa "ejecutar el DML o DDL o PL / SQL en el búfer.
  4. RUNo Res un comando sqlsplus para mostrar / generar el SQL en el búfer y ejecutarlo. No terminará una declaración SQL.
  5. / durante la entrada de un DML o DDL o PL / SQL significa "terminar la declaración actual, ejecutarla y almacenarla en el búfer SQLPLUS"

NOTA: Debido a que ;se usan para que PL / SQL termine una declaración, ;SQLPLUS no puede usar para significar "terminar la declaración actual, ejecutarla y almacenarla en el búfer SQLPLUS" porque queremos que todo el bloque PL / SQL esté completamente en el buffer, luego ejecútelo. Los bloques PL / SQL deben terminar con:

END;
/
Mr_Moneybags
fuente
22

Casi todas las implementaciones de Oracle se realizan a través de SQL * Plus (esa pequeña y extraña herramienta de línea de comando que utiliza su DBA). Y en SQL * Plus, una barra inclinada básicamente significa "volver a ejecutar el último comando SQL o PL / SQL que acabo de ejecutar".

Ver

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

La regla general sería usar una barra diagonal con cosas que hacen BEGIN .. ENDo dónde puedes usar CREATE OR REPLACE.

Para insertos que necesitan ser de uso único

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
fuente
14

Según tengo entendido, todas las declaraciones SQL no necesitan barra diagonal, ya que se ejecutarán automáticamente al final de los puntos y comas, incluidas las declaraciones DDL, DML, DCL y TCL.

Para otros bloques PL / SQL, incluidos procedimientos, funciones, paquetes y disparadores, debido a que son programas de varias líneas, Oracle necesita una forma de saber cuándo ejecutar el bloque, por lo que debemos escribir una barra diagonal al final de cada bloque para deja que Oracle lo ejecute.

alemán
fuente
1

Solo uso la barra diagonal una vez al final de cada script, para decirle a sqlplus que no hay más líneas de código. En medio de un script, no uso una barra inclinada.

Jonathan
fuente
Entonces, ¿ordena cosas que requieren el / (como subprogramas y disparadores) al final? ¿Qué pasa si tienes múltiples desencadenantes? Ejecuté una prueba y solo la primera se ejecuta a menos que tenga un / entre cada una. ¿Me estoy perdiendo de algo?
amischiefr 03 de
Intento evitarlo (si es posible), pero si no puedo (como en los disparadores), uso los puntos y comas exactamente como se usan en los scripts oficiales que generan los esquemas de muestra de Oracle: download.oracle.com/docs /cd/B19306_01/server.102/b14198/… Para el problema de las inserciones, trato de separar los scripts que crean objetos de los que pueblan las tablas.
Jonathan
1
Lo sentimos, pero esto no responde la pregunta.
DerMike