Comment déclarer une variable et l'utiliser dans le même script Oracle SQL?

133

Je souhaite écrire du code réutilisable et dois déclarer certaines variables au début et les réutiliser dans le script, telles que:

DEFINE stupidvar = 'stupidvarcontent';

SELECT stupiddata
FROM stupidtable
WHERE stupidcolumn = &stupidvar;

Comment puis-je déclarer une variable et la réutiliser dans les instructions qui suivent, par exemple en l'utilisant SQLDeveloper.


Tentatives

  • Utilisez une section DECLARE et insérez l'instruction SELECT suivante dans BEGINet END;. Accède à la variable en utilisant &stupidvar.
  • Utilisez le mot-clé DEFINEet accédez à la variable.
  • En utilisant le mot-clé VARIABLEet accédez à la variable.

Mais j'obtiens toutes sortes d'erreurs lors de mes essais (variable non liée, erreur de syntaxe, attendue SELECT INTO...).

bl4ckb0l7
la source
2
Notez que l'approche dans la réponse acceptée par @APC peut être utilisée sans PL / SQL, par exemple dans une feuille de calcul SQL Developer selon votre question. Déclarez simplement la variable sur une ligne (pas de point-virgule), puis la ligne exec pour définir sa valeur (finissez par un point-virgule), puis votre instruction select. Enfin, exécutez-le en tant que script (F5), pas en tant qu'instruction (F9).
Amos M. Carpenter

Réponses:

139

Il existe plusieurs façons de déclarer des variables dans les scripts SQL * Plus.

La première consiste à utiliser VAR, pour déclarer une variable de liaison. Le mécanisme d'attribution de valeurs à un VAR est avec un appel 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 est particulièrement utile lorsque nous voulons appeler une procédure stockée qui a des paramètres OUT ou une fonction.

Nous pouvons également utiliser des variables de substitution. Ceux-ci sont bons pour le mode interactif:

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>

Lorsque nous écrivons un script qui appelle d'autres scripts, il peut être utile de DÉFINIR les variables à l'avance. Cet extrait de code s'exécute sans me demander de saisir une valeur:

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>

Enfin, il y a le bloc PL / SQL anonyme. Comme vous le voyez, nous pouvons toujours attribuer des valeurs aux variables déclarées de manière interactive:

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
la source
6
Tout va bien, sauf pour votre utilisation du terme «variable de liaison». La déclaration VAR crée une variable de liaison, tandis que ACCEPT ou DEFINE crée une variable de substitution.
Dave Costa
1
Est-il possible de concaténer des variables + des chaînes?
Ecropolis
@Ecropolis - oui, dans la période d'utilisation de SQL Plus par défaut. Utilisez SET CONCAT pour définir le caractère qui sépare le nom d'une variable de substitution des caractères alphanumériques qui suivent immédiatement le nom de la variable. En PL / SQL ou SQL, utilisez le double tube || concaténer.
Laszlo Lugosi
Si SQL est un langage standard, pourquoi est-il si difficile de trouver une référence canonique qui fonctionne partout? WTF ???
jww
1
@jww - SQL est un standard mais il ne spécifie pas toujours la syntaxe exacte, donc différents produits SGBDR peuvent implémenter les choses différemment; l'arithmétique des dates est un bon exemple. De plus, les anciens produits de base de données comme Oracle ont souvent introduit des fonctionnalités avant que la norme ne les couvre: par exemple la syntaxe hiérarchique CONNECT BY. Mais dans ce cas, nous discutons de SQL * Plus, qui est un outil client et donc non couvert par la norme ANSI de toute façon.
APC
28

Essayez d'utiliser des guillemets doubles s'il s'agit d'une variable char:

DEFINE stupidvar = "'stupidvarcontent'";

ou

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
la source
Merci pour votre réponse, mais si j'inclus le var entre guillemets, j'obtiens un ORA-01008: not all variables bound.
bl4ckb0l7
1
Sûr! DEFINE num = 1; SELECT &num FROM dual;mène à: ORA-01008: not all variables bound
bl4ckb0l7
@ bl4ckb0l7 - Je parie que vous essayez ceci pas dans SQL * Plus.
Laszlo Lugosi
20

Dans PL / SQL v.10

Le mot-clé declare est utilisé pour déclarer une variable

DECLARE stupidvar varchar(20);

pour attribuer une valeur, vous pouvez la définir lorsque vous déclarez

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

ou pour sélectionner quelque chose dans cette variable, vous utilisez l' INTOinstruction, mais vous devez encapsuler l'instruction dans BEGINet END, vous devez également vous assurer qu'une seule valeur est renvoyée, et n'oubliez pas les points-virgules.

donc la déclaration complète serait publiée comme suit:

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

Votre variable n'est utilisable que dedans BEGINet ENDdonc si vous voulez en utiliser plusieurs, vous devrez faire plusieurs BEGIN ENDwrappings

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;

J'espère que cela vous fera gagner du temps

Matas Vaitkevicius
la source
7

Si vous souhaitez déclarer la date, puis l'utiliser dans SQL Developer.

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

SELECT * 
FROM proposal 
WHERE prop_start_dt = &PROPp_START_DT
SVK
la source
5

Je veux juste ajouter la réponse de Matas . C'est peut-être évident, mais j'ai cherché pendant longtemps pour comprendre que la variable n'est accessible que dans la construction BEGIN-END , donc si vous devez l'utiliser dans un code plus tard, vous devez mettre ce code dans BEGIN -END bloc .

Notez que ces blocs peuvent être imbriqués :

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
la source
5

La question est sur le point d'utiliser une variable dans un script signifie pour moi qu'elle sera utilisée dans SQL * Plus.

Le problème est que vous avez manqué les citations et Oracle ne peut pas analyser la valeur en nombre.

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

Cet exemple fonctionne très bien en raison de la conversion automatique de type (ou peu importe son nom).

Si vous vérifiez en tapant DEFINE dans SQL * Plus, cela montrera que la variable num est CHAR.

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

Ce n'est pas un problème dans ce cas, car Oracle peut gérer l'analyse de chaîne en nombre s'il s'agit d'un nombre valide.

Lorsque la chaîne ne peut pas analyser en nombre, Oracle ne peut pas y faire face.

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

Avec un devis, alors ne forcez pas Oracle à analyser le nombre, tout ira 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

Donc, pour répondre à la question d'origine, il devrait être fait comme cet exemple:

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

Il existe un autre moyen de stocker une variable dans SQL * Plus à l'aide de la valeur de colonne de requête .

Le COL [UMN] a l' option new_value pour stocker la valeur de la requête par nom de champ.

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;

Comme vous pouvez le voir, la valeur X.log a été définie dans la variable stupid_var , nous pouvons donc trouver un fichier X.log dans le répertoire actuel contenant un journal.

Laszlo Lugosi
la source
2

Voici votre réponse:

DEFINE num := 1;       -- The semi-colon is needed for default values.
SELECT &num FROM dual;
Stephen Meckstroth
la source
1
Pareil pour moi. J'utilise ODT et lance: DEFINE num: = 1; SELECT num FROM dual; Et ce que j'obtiens est: ORA-00904: "NUM": identifiant invalide 00904. 00000 - "% s: identifiant invalide" * Cause: * Action: Erreur à la ligne: 2 Colonne: 8
toha
0

Dans Toad, j'utilise cela fonctionne:

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;

Ensuite, la valeur sera imprimée dans DBMS OutputWindow.

Référence à ici et ici 2 .

yu yang jian
la source
0

Parfois, vous devez utiliser une variable macro sans demander à l'utilisateur de saisir une valeur. Le plus souvent, cela doit être fait avec des paramètres de script facultatifs. Le code suivant est entièrement fonctionnel

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

Un code similaire a été trouvé dans le répertoire rdbms / sql.

user12273401
la source
0

Une approche possible, si vous avez juste besoin de spécifier un paramètre une fois et de le répliquer à plusieurs endroits, consiste à faire quelque chose comme ceci:

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

Ce code génère une chaîne de 8 chiffres aléatoires.

Notez que je crée une sorte d'alias nommé str_sizequi contient la constante 8. Il est croisé pour être utilisé plus d'une fois dans la requête.

Diego Queiroz
la source