変数を宣言して同じOracle SQLスクリプトで使用する方法


133

再利用可能なコードを書きたいので、最初にいくつかの変数を宣言し、スクリプトでそれらを再利用する必要があります。

DEFINE stupidvar = 'stupidvarcontent';

SELECT stupiddata
FROM stupidtable
WHERE stupidcolumn = &stupidvar;

変数を宣言して、SQLDeveloperを使用する場合など、後続のステートメントで再利用するにはどうすればよいですか。


試み

  • DECLAREセクションを使用し、次のSELECTステートメントをBEGINandに挿入しますEND;。を使用して変数にアクセスします&stupidvar
  • キーワードDEFINEを使用して変数にアクセスします。
  • キーワードVARIABLEを使用して変数にアクセスします。

しかし、試行中にすべての種類のエラー(Unbound変数、構文エラー、予期されるSELECT INTO...)が発生します。


2
@APCが承認した回答のアプローチは、PL / SQLなしでも使用できます。たとえば、質問に応じてSQL Developerワークシートで使用できます。変数を1行(セミコロンなし)で宣言し、次にexec行でその値(セミコロンで終了)を設定してから、selectステートメントを宣言します。最後に、ステートメント(F9)ではなく、スクリプト(F5)として実行します。
Amos M. Carpenter

回答:


139

SQL * Plusスクリプトで変数を宣言する方法はいくつかあります。

1つ目は、VARを使用してバインド変数を宣言することです。VARに値を割り当てるメカニズムは、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>

VARは、OUTパラメータまたは関数を持つストアドプロシージャを呼び出すときに特に役立ちます。

あるいは、代替変数を使用することもできます。これらはインタラクティブモードに適しています。

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>

他のスクリプトを呼び出すスクリプトを作成しているときは、変数を事前に定義しておくと便利です。このスニペットは、値の入力を要求せずに実行されます。

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>

最後に、匿名のPL / SQLブロックがあります。ご覧のとおり、宣言された変数にインタラクティブに値を割り当てることができます。

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
「バインド変数」という用語の使用を除いて、すべて問題ありません。VAR宣言はバインド変数を作成し、ACCEPTまたはDEFINEは置換変数を作成します。
デイブ・コスタ

1
変数+文字列を連結することは可能ですか?
エクロポリス2014年

@Ecropolis-はい、SQL Plusではデフォルトで期間を使用します。SET CONCATを使用して、変数名の直後に続く英数字から置換変数の名前を区切る文字を定義します。PL / SQLまたはSQLでは二重パイプを使用します|| 連結する。
Laszlo Lugosi、2018

SQLが標準言語である場合、どこでも機能する正規の参照を見つけることがなぜそれほど難しいのでしょうか。WTF ???
jww

1
@jww-SQLは標準ですが、常に正確な構文を指定しているわけではないため、RDBMS製品によって実装方法が異なります。日付計算が良い例です。また、Oracleのような古いデータベース製品は、標準がそれらをカバーする前に、たとえば階層CONNECT BY構文などの機能をしばしば導入しました。ただし、ここでは、SQL * Plusについて説明します。SQL* Plusはクライアントツールであるため、ANSI標準ではカバーされていません。
APC

28

char変数の場合は、二重引用符を使用してみてください。

DEFINE stupidvar = "'stupidvarcontent'";

または

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

回答ありがとうございます。ただし、varを二重引用符で囲んだ場合、が返されますORA-01008: not all variables bound
bl4ckb0l7 2010

1
承知しました!DEFINE num = 1; SELECT &num FROM dual;:へのリード線 ORA-01008: not all variables bound
bl4ckb0l7

@ bl4ckb0l7-SQL * Plusではなくこれを試みているに違いありません。
Laszlo Lugosi、2018

20

PL / SQL v.10の場合

キーワードdeclareは変数を宣言するために使用されます

DECLARE stupidvar varchar(20);

値を割り当てるには、宣言するときに設定できます

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

または、INTOステートメントを使用してその変数に何かを選択するには、ステートメントをBEGINand ENDでラップする必要があります。また、単一の値のみが返されることを確認し、セミコロンを忘れないようにする必要があります。

したがって、完全なステートメントは次のようになります。

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

あなたの変数は内でのみ使用可能であるBEGINENDあなたはより多くのものより使用したい場合は、複数行う必要がありますBEGIN END包装を

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;

これがあなたの時間を節約することを願っています


7

日付を宣言してSQL Developerで使用する場合。

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

SELECT * 
FROM proposal 
WHERE prop_start_dt = &PROPp_START_DT

5

Matasの回答を追加したいだけです。多分それは明白ですが、変数がBEGIN-END構造の内部でのみアクセス可能であることを理解するために長い間検索してきたため、後でいくつかのコードで使用する必要がある場合は、このコードをBEGIN内配置する必要があります-ENDブロック

これらのブロックはネストできることに注意してください:

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

スクリプトで変数を使用するというのは、SQL * Plusで使用されるという意味です。

問題は、引用符を逃したことであり、Oracleは値を数値に解析できません。

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

このサンプルは、自動型変換(またはそれが呼び出されたもの)のため、正常に機能します。

SQL * PlusでDEFINEと入力してチェックすると、num変数がCHARであることが示されます。

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

Oracleは、文字列が有効な数値である場合、数値への解析文字列を処理できるため、この場合は問題になりません。

文字列が数値に解析できない場合、Oracleはそれを処理できません。

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

引用があるので、Oracleに数値まで解析させないでください。問題はありません。

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

したがって、元の質問に答えるには、次のサンプルのようにする必要があります。

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

Query Column Valueを使用してSQL * Plusに変数を格納する別の方法があります。

COL [UMN]はありNEW_VALUEクエリからフィールド名で保存値にオプションを選択します。

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;

ご覧のとおり、X.log値はstupid_var変数に設定されているため、現在のディレクトリにあるX.logファイルにログが含まれていることがわかります。


2

これがあなたの答えです:

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

1
私と同じ。私はODTを使用して実行します。DEFINE num:= 1; デュアルから番号を選択; そして、何私が取得することである:ORA-00904: "NUM":無効な識別子00904. 00000 - "%sの:無効な識別子" *原因:*アクション:行でエラー:2カラム:8
toha

0

ヒキガエルでは、この作品を使用します:

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;

次に、値はDBMS Outputウィンドウに出力されます。

hereおよびhere2への参照。


0

ユーザーに値の入力を求めずにマクロ変数を使用する必要がある場合があります。ほとんどの場合、これはオプションのスクリプトパラメータを使用して行う必要があります。次のコードは完全に機能しています

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

同様のコードが、どういうわけかrdbms / sqlディレクトリに見つかりました。


0

パラメータを1回指定し、それを複数の場所に複製する必要がある場合の1つの可能なアプローチは、次のようなことです。

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

このコードは、ランダムな8桁の文字列を生成します。

str_size定数を保持するという名前のエイリアスを作成していることに注意してください8。クエリで複数回使用するためにクロス結合されています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.