¿Cómo declarar variable y usarla en el mismo script Oracle SQL?

133

Quiero escribir código reutilizable y necesito declarar algunas variables al principio y reutilizarlas en el script, como:

DEFINE stupidvar = 'stupidvarcontent';

SELECT stupiddata
FROM stupidtable
WHERE stupidcolumn = &stupidvar;

¿Cómo puedo declarar una variable y reutilizarla en las siguientes afirmaciones, como al usar SQLDeveloper?


Intentos

  • Use una sección DECLARE e inserte la siguiente instrucción SELECT en BEGINy END;. Acceda a la variable usando &stupidvar.
  • Use la palabra clave DEFINEy acceda a la variable.
  • Usando la palabra clave VARIABLEy acceda a la variable.

Pero recibo todo tipo de errores durante mis intentos (variable independiente, error de sintaxis, esperado SELECT INTO...).

bl4ckb0l7
fuente
2
Tenga en cuenta que el enfoque en la respuesta aceptada por @APC se puede usar sin PL / SQL, por ejemplo, en una hoja de trabajo de Desarrollador SQL según su pregunta. Simplemente declare la variable en una línea (sin punto y coma), luego la línea ejecutiva para establecer su valor (finalice con punto y coma), luego su instrucción de selección. Finalmente, ejecútelo como un script (F5), no como una declaración (F9).
Amos M. Carpenter

Respuestas:

139

Hay varias formas de declarar variables en los scripts SQL * Plus.

El primero es usar VAR, para declarar una variable de enlace. El mecanismo para asignar valores a un VAR es con una llamada EXEC:

SQL> var name varchar2(20)
SQL> exec :name := 'SALES'

PL/SQL procedure successfully completed.

SQL> select * from dept
  2  where dname = :name
  3  /

    DEPTNO DNAME          LOC
---------- -------------- -------------
        30 SALES          CHICAGO

SQL>

Un VAR es particularmente útil cuando queremos llamar a un procedimiento almacenado que tiene parámetros OUT o una función.

Alternativamente, podemos usar variables de sustitución. Estos son buenos para el modo interactivo:

SQL> accept p_dno prompt "Please enter Department number: " default 10
Please enter Department number: 20
SQL> select ename, sal
  2  from emp
  3  where deptno = &p_dno
  4  /
old   3: where deptno = &p_dno
new   3: where deptno = 20

ENAME             SAL
---------- ----------
CLARKE            800
ROBERTSON        2975
RIGBY            3000
KULASH           1100
GASPAROTTO       3000

SQL>

Cuando estamos escribiendo un script que llama a otros scripts, puede ser útil DEFINIR las variables por adelantado. Este fragmento se ejecuta sin pedirme que ingrese un valor:

SQL> def p_dno = 40
SQL> select ename, sal
  2  from emp
  3  where deptno = &p_dno
  4  /
old   3: where deptno = &p_dno
new   3: where deptno = 40

no rows selected

SQL>

Finalmente está el bloque anónimo PL / SQL. Como puede ver, aún podemos asignar valores a las variables declaradas de forma interactiva:

SQL> set serveroutput on size unlimited
SQL> declare
  2      n pls_integer;
  3      l_sal number := 3500;
  4      l_dno number := &dno;
  5  begin
  6      select count(*)
  7      into n
  8      from emp
  9      where sal > l_sal
 10      and deptno = l_dno;
 11      dbms_output.put_line('top earners = '||to_char(n));
 12  end;
 13  /
Enter value for dno: 10
old   4:     l_dno number := &dno;
new   4:     l_dno number := 10;
top earners = 1

PL/SQL procedure successfully completed.

SQL>
APC
fuente
66
Todo bien, excepto por el uso del término "variable de enlace". La declaración VAR crea una variable de enlace, mientras que ACCEPT o DEFINE crea una variable de sustitución.
Dave Costa
1
¿Es posible concatenar variables + cadenas?
Ecropolis
@Ecropolis: sí, en SQL Plus usa el período de forma predeterminada. Use SET CONCAT para definir el carácter que separa el nombre de una variable de sustitución de los caracteres alfanuméricos que siguen inmediatamente al nombre de la variable. En PL / SQL o SQL use doble canalización || para concatenar
Laszlo Lugosi
Si SQL es un lenguaje estándar, ¿por qué es tan difícil encontrar una referencia canónica que funcione en todas partes? WTF ???
jww
1
@jww: SQL es un estándar, pero no siempre especifica la sintaxis exacta, por lo que diferentes productos RDBMS pueden implementar cosas de manera diferente; La aritmética de fechas es un buen ejemplo. Además, los productos de bases de datos más antiguos como Oracle a menudo introducían características antes de que el Estándar los cubriera: por ejemplo, la sintaxis jerárquica CONNECT BY. Pero en este caso estamos discutiendo SQL * Plus, que es una herramienta cliente y, por lo tanto, no está cubierta por el estándar ANSI de todos modos.
APC
28

Intente usar comillas dobles si es una variable char:

DEFINE stupidvar = "'stupidvarcontent'";

o

DEFINE stupidvar = 'stupidvarcontent';

SELECT stupiddata  
FROM stupidtable  
WHERE stupidcolumn = '&stupidvar'

upd:

SQL*Plus: Release 10.2.0.1.0 - Production on Wed Aug 25 17:13:26 2010

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

SQL> conn od/od@etalon
Connected.
SQL> define var = "'FL-208'";
SQL> select code from product where code = &var;
old   1: select code from product where code = &var
new   1: select code from product where code = 'FL-208'

CODE
---------------
FL-208

SQL> define var = 'FL-208';
SQL> select code from product where code = &var;
old   1: select code from product where code = &var
new   1: select code from product where code = FL-208
select code from product where code = FL-208
                                      *
ERROR at line 1:
ORA-06553: PLS-221: 'FL' is not a procedure or is undefined
Kirill Leontev
fuente
Gracias por su respuesta, pero si incluyo la var entre comillas dobles, obtengo un ORA-01008: not all variables bound.
bl4ckb0l7
1
¡Por supuesto! DEFINE num = 1; SELECT &num FROM dual;conduce a: ORA-01008: not all variables bound
bl4ckb0l7
@ bl4ckb0l7 - Apuesto a que estás intentando esto no en SQL * Plus.
Laszlo Lugosi
20

En PL / SQL v.10

la palabra clave declare se usa para declarar variable

DECLARE stupidvar varchar(20);

para asignar un valor, puede establecerlo cuando declara

DECLARE stupidvar varchar(20) := '12345678';

o para seleccionar algo en esa variable, usa la INTOdeclaración, sin embargo, necesita ajustar la declaración BEGINyEND , también, debe asegurarse de que solo se devuelva un solo valor, y no olvide el punto y coma.

entonces la declaración completa saldría a continuación:

DECLARE stupidvar varchar(20);
BEGIN
    SELECT stupid into stupidvar FROM stupiddata CC 
    WHERE stupidid = 2;
END;

La variable sólo es utilizable dentro BEGINy ENDpor lo que si desea utilizar más de uno le va a tener que hacer múltiplesBEGIN END envoltorios

DECLARE stupidvar varchar(20);
BEGIN
    SELECT stupid into stupidvar FROM stupiddata CC 
    WHERE stupidid = 2;

    DECLARE evenmorestupidvar varchar(20);
    BEGIN
        SELECT evenmorestupid into evenmorestupidvar FROM evenmorestupiddata CCC 
        WHERE evenmorestupidid = 42;

        INSERT INTO newstupiddata (newstupidcolumn, newevenmorestupidstupidcolumn)
        SELECT stupidvar, evenmorestupidvar 
        FROM dual

    END;
END;

Espero que esto te ahorre algo de tiempo

Matas Vaitkevicius
fuente
7

Si desea declarar la fecha y luego usarla en SQL Developer.

DEFINE PROPp_START_DT = TO_DATE('01-SEP-1999')

SELECT * 
FROM proposal 
WHERE prop_start_dt = &PROPp_START_DT
SVK
fuente
5

Solo quiero agregar la respuesta de Matas . Tal vez sea obvio, pero he buscado durante mucho tiempo descubrir que la variable es accesible solo dentro de la construcción BEGIN-END , por lo que si necesita usarla en algún código más adelante, debe poner este código dentro de BEGIN -END bloque .

Tenga en cuenta que estos bloques se pueden anidar :

DECLARE x NUMBER;
  BEGIN
    SELECT PK INTO x FROM table1 WHERE col1 = 'test';

    DECLARE y NUMBER;
    BEGIN
    SELECT PK INTO y FROM table2 WHERE col2 = x;

    INSERT INTO table2 (col1, col2)
      SELECT y,'text'
      FROM dual
      WHERE exists(SELECT * FROM table2);
    COMMIT;
  END;
END;
Katia Savina
fuente
5

La pregunta está a punto de usar una variable en un script significa para mí que se usará en SQL * Plus.

El problema es que perdió las comillas y Oracle no puede analizar el valor en número.

SQL> DEFINE num = 2018
SQL> SELECT &num AS your_num FROM dual;
old   1: SELECT &num AS your_num FROM dual
new   1: SELECT 2018 AS your_num FROM dual

  YOUR_NUM
----------
      2018

Elapsed: 00:00:00.01

Esta muestra funciona bien debido a la conversión automática de tipo (o como se llame).

Si marca escribiendo DEFINE en SQL * Plus, mostrará que la variable num es CHAR.

SQL>define
DEFINE NUM             = "2018" (CHAR)

No es un problema en este caso, porque Oracle puede manejar el análisis de cadenas a números si fuera un número válido.

Cuando la cadena no puede analizarse en número, Oracle no puede lidiar con ella.

SQL> DEFINE num = 'Doh'
SQL> SELECT &num AS your_num FROM dual;
old   1: SELECT &num AS your_num FROM dual
new   1: SELECT Doh AS your_num FROM dual
SELECT Doh AS your_num FROM dual
       *
ERROR at line 1:
ORA-00904: "DOH": invalid identifier

Con una cita, así que no obligue a Oracle a analizar el número, estará bien:

17:31:00 SQL> SELECT '&num' AS your_num FROM dual;
old   1: SELECT '&num' AS your_num FROM dual
new   1: SELECT 'Doh' AS your_num FROM dual

YOU
---
Doh

Entonces, para responder la pregunta original, debería ser como esta muestra:

SQL> DEFINE stupidvar = 'X'
SQL>
SQL> SELECT 'print stupidvar:' || '&stupidvar'
  2  FROM dual
  3  WHERE dummy = '&stupidvar';
old   1: SELECT 'print stupidvar:' || '&stupidvar'
new   1: SELECT 'print stupidvar:' || 'X'
old   3: WHERE dummy = '&stupidvar'
new   3: WHERE dummy = 'X'

'PRINTSTUPIDVAR:'
-----------------
print stupidvar:X

Elapsed: 00:00:00.00

Hay otra forma de almacenar variables en SQL * Plus utilizando el valor de la columna de consulta .

El COL [UMN] tiene nuevo_valor opción para almacenar el valor de la consulta por el nombre del campo.

SQL> COLUMN stupid_column_name new_value stupid_var noprint
SQL> SELECT dummy || '.log' AS stupid_column_name
  2  FROM dual;

Elapsed: 00:00:00.00
SQL> SPOOL &stupid_var.
SQL> SELECT '&stupid_var' FROM DUAL;
old   1: SELECT '&stupid_var' FROM DUAL
new   1: SELECT 'X.log' FROM DUAL

X.LOG
-----
X.log

Elapsed: 00:00:00.00
SQL>SPOOL OFF;

Como puede ver, el valor X.log se configuró en la variable stupid_var , por lo que podemos encontrar que un archivo X.log en el directorio actual tiene algún registro.

Laszlo Lugosi
fuente
2

Aquí está tu respuesta:

DEFINE num := 1;       -- The semi-colon is needed for default values.
SELECT &num FROM dual;
Stephen Meckstroth
fuente
1
Lo mismo conmigo. Yo uso ODT y ejecuto: DEFINE num: = 1; SELECCIONE num desde dual; Y lo que obtengo es: ORA-00904: "NUM": identificador no válido 00904. 00000 - "% s: identificador no válido" * Causa: * Acción: Error en la línea: 2 Columna: 8
toha
0

En Toad utilizo estos trabajos:

declare 
    num number;
begin 
    ---- use 'select into' works 
    --select 123 into num from dual;

    ---- also can use :=
    num := 123;
    dbms_output.Put_line(num);
end;

Entonces el valor se imprimirá en la DBMS Outputventana.

Referencia aquí y aquí 2 .

Yu Jang Jian
fuente
0

A veces necesita usar una macro variable sin pedirle al usuario que ingrese un valor. En la mayoría de los casos, esto debe hacerse con parámetros de script opcionales. El siguiente código es completamente funcional.

column 1 noprint new_value 1
select '' "1" from dual where 2!=2;
select nvl('&&1', 'VAH') "1" from dual;
column 1 clear
define 1

Código similar se encontró de alguna manera en el directorio rdbms / sql.

usuario12273401
fuente
0

Un enfoque posible, si solo necesita especificar un parámetro una vez y replicarlo en varios lugares, es hacer algo como esto:

SELECT
  str_size  /* my variable usage */
  , LPAD(TRUNC(DBMS_RANDOM.VALUE * POWER(10, str_size)), str_size, '0') rand
FROM
  dual  /* or any other table, or mixed of joined tables */
  CROSS JOIN (SELECT 8 str_size FROM dual);  /* my variable declaration */

Este código genera una cadena de 8 dígitos aleatorios.

Tenga en cuenta que creo un tipo de alias llamado str_sizeque contiene la constante 8. Se cruza para usarse más de una vez en la consulta.

Diego Queiroz
fuente