Come dichiarare la variabile e usarla nello stesso script Oracle SQL?


133

Voglio scrivere codice riutilizzabile e devo dichiarare alcune variabili all'inizio e riutilizzarle nello script, come:

DEFINE stupidvar = 'stupidvarcontent';

SELECT stupiddata
FROM stupidtable
WHERE stupidcolumn = &stupidvar;

Come posso dichiarare una variabile e riutilizzarla in istruzioni che seguono, come ad esempio nell'usarla SQLDeveloper.


tentativi

  • Utilizzare una sezione DECLARE e inserire la seguente istruzione SELECT in BEGINe END;. Accedi alla variabile usando &stupidvar.
  • Usa la parola chiave DEFINEe accedi alla variabile.
  • Usando la parola chiave VARIABLEe accedi alla variabile.

Ma durante i miei tentativi ricevo tutti i tipi di errori (variabile non associata, errore di sintassi, previsto SELECT INTO...).


2
Si noti che l'approccio nella risposta accettata da @APC può essere utilizzato senza PL / SQL, ad esempio in un foglio di lavoro per sviluppatori SQL come da domanda. Dichiarare semplicemente la variabile su una riga (senza punto e virgola), quindi la riga exec per impostarne il valore (terminare con punto e virgola), quindi l'istruzione select. Infine, eseguilo come uno script (F5), non come un'istruzione (F9).
Amos M. Carpenter,

Risposte:


139

Esistono diversi modi per dichiarare le variabili negli script SQL * Plus.

Il primo è usare VAR, per dichiarare una variabile di bind. Il meccanismo per assegnare valori a un VAR è con una chiamata 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 è particolarmente utile quando vogliamo chiamare una procedura memorizzata che ha parametri OUT o una funzione.

In alternativa possiamo usare le variabili di sostituzione. Questi sono buoni per la modalità interattiva:

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>

Quando stiamo scrivendo uno script che chiama altri script può essere utile DEFINIRE le variabili in anticipo. Questo frammento viene eseguito senza chiedermi di inserire un valore:

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>

Infine c'è il blocco anonimo PL / SQL. Come vedi, possiamo ancora assegnare i valori alle variabili dichiarate in modo interattivo:

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>

6
Tutto bene, tranne per l'uso del termine "variabile di bind". La dichiarazione VAR crea una variabile di bind, mentre ACCEPT o DEFINE crea una variabile di sostituzione.
Dave Costa,

1
È possibile concatenare variabili + stringhe?
Ecropolis,

@Ecropolis - sì, in SQL Plus utilizzare il periodo per impostazione predefinita. Utilizzare SET CONCAT per definire il carattere che separa il nome di una variabile di sostituzione dai caratteri alfanumerici che seguono immediatamente il nome della variabile. In PL / SQL o SQL utilizzare la doppia pipe || concatenare.
Laszlo Lugosi,

Se SQL è un linguaggio standard, perché è così difficile trovare un riferimento canonico che funzioni ovunque? WTF ???
1919

1
@jww - SQL è uno standard ma non specifica sempre l'esatta sintassi, quindi diversi prodotti RDBMS possono implementare le cose in modo diverso; l'aritmetica della data è un buon esempio. Anche i vecchi prodotti di database come Oracle hanno spesso introdotto funzionalità prima dello Standard: ad esempio la sintassi gerarchica CONNECT BY. Ma in questo caso stiamo discutendo di SQL * Plus, che è uno strumento client e quindi non coperto dallo standard ANSI.
APC

28

Prova a usare le virgolette doppie se è una variabile 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

Grazie per la tua risposta, ma se includo il var tra virgolette doppie, ottengo un ORA-01008: not all variables bound.
bl4ckb0l7,

1
Sicuro! DEFINE num = 1; SELECT &num FROM dual;porta a: ORA-01008: not all variables bound
bl4ckb0l7,

@ bl4ckb0l7 - Scommetto che stai provando questo non in SQL * Plus.
Laszlo Lugosi,

20

In PL / SQL v.10

la parola chiave declare viene utilizzata per dichiarare la variabile

DECLARE stupidvar varchar(20);

per assegnare un valore puoi impostarlo quando dichiari

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

o per selezionare qualcosa in quella variabile che usi INTOstatement, tuttavia devi racchiudere l'istruzione in BEGINeEND , inoltre, devi assicurarti che venga restituito un solo valore e non dimenticare i punti e virgola.

quindi la dichiarazione completa verrebbe fuori come segue:

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

La tua variabile è utilizzabile solo all'interno BEGINe ENDquindi se vuoi usarne più di una dovrai fare più BEGIN ENDavvolgimenti

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;

Spero che questo ti faccia risparmiare un po 'di tempo


7

Se si desidera dichiarare la data e quindi utilizzarla in SQL Developer.

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

SELECT * 
FROM proposal 
WHERE prop_start_dt = &PROPp_START_DT

5

Voglio solo aggiungere la risposta di Matas . Forse è ovvio, ma ho cercato a lungo per capire che la variabile è accessibile solo all'interno della costruzione BEGIN-END , quindi se è necessario utilizzarla in un codice in un secondo momento, è necessario inserire questo codice all'interno del BEGIN -END blocco .

Si noti che questi blocchi possono essere nidificati :

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;

5

La domanda sta per usare una variabile in uno script significa per me che verrà usata in SQL * Plus.

Il problema è che hai perso le virgolette e Oracle non può analizzare il valore in numero.

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

Questo esempio funziona perfettamente a causa della conversione automatica del tipo (o come viene chiamato).

Se si controlla digitando DEFINE in SQL * Plus, verrà mostrato che la variabile num è CHAR.

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

In questo caso non è un problema, perché Oracle può gestire l'analisi della stringa da numerare se si tratta di un numero valido.

Quando la stringa non può analizzare il numero, Oracle non può gestirla.

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 un preventivo, quindi non forzare Oracle ad analizzare il numero, andrà bene:

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

Quindi, per rispondere alla domanda originale, dovrebbe essere come in questo esempio:

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

Esiste un altro modo per archiviare le variabili in SQL * Plus utilizzando il valore Colonna query .

Il COL [UMN] ha nuovo_valore opzione per memorizzare il valore di query nome 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;

Come puoi vedere, il valore X.log è stato impostato nella variabile stupid_var , quindi possiamo trovare un file X.log nella directory corrente con qualche log in esso.


2

Ecco la tua risposta:

DEFINE num := 1;       -- The semi-colon is needed for default values.
SELECT &num FROM dual;

1
Lo stesso con me. Uso ODT ed eseguo: DEFINE num: = 1; SELEZIONA num DA doppio; E quello che ottengo è: ORA-00904: "NUM": identificatore non valido 00904. 00000 - "% s: identificatore non valido" * Causa: * Azione: errore alla riga: 2 Colonna: 8
toha

0

In Toad utilizzo questo funziona:

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;

Quindi il valore verrà stampato su DBMS OutputWindow.

Riferimento a qui e qui2 .


0

A volte è necessario utilizzare una variabile macro senza chiedere all'utente di immettere un valore. Molto spesso questo deve essere fatto con parametri di script opzionali. Il seguente codice è perfettamente funzionante

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

Codice simile è stato trovato in qualche modo nella directory rdbms / sql.


0

Un possibile approccio, se devi solo specificare un parametro una volta e replicarlo in più punti, è fare qualcosa del genere:

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 */

Questo codice genera una stringa di 8 cifre casuali.

Si noti che creo un tipo di alias chiamato str_sizeche contiene la costante 8. È unito per essere utilizzato più di una volta nella query.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.