Bagaimana cara mendeklarasikan variabel dan menggunakannya dalam skrip Oracle SQL yang sama?

133

Saya ingin menulis kode yang dapat digunakan kembali dan perlu mendeklarasikan beberapa variabel di awal dan menggunakannya kembali dalam skrip, seperti:

DEFINE stupidvar = 'stupidvarcontent';

SELECT stupiddata
FROM stupidtable
WHERE stupidcolumn = &stupidvar;

Bagaimana saya bisa mendeklarasikan variabel dan menggunakannya kembali dalam pernyataan yang mengikuti seperti dalam menggunakannya SQLDeveloper.


Mencoba

  • Gunakan bagian DECLARE dan masukkan pernyataan SELECT berikut di BEGINdan END;. Akses variabel menggunakan &stupidvar.
  • Gunakan kata kunci DEFINEdan akses variabel.
  • Menggunakan kata kunci VARIABLEdan mengakses variabel.

Tapi saya mendapatkan semua jenis kesalahan selama percobaan saya (variabel Tidak terikat, kesalahan Sintaks, Diharapkan SELECT INTO...).

bl4ckb0l7
sumber
2
Perhatikan bahwa pendekatan dalam jawaban yang diterima oleh @APC dapat digunakan tanpa PL / SQL, misalnya dalam lembar kerja Pengembang SQL sesuai pertanyaan Anda. Cukup deklarasikan variabel pada satu baris (tanpa titik koma), lalu baris exec untuk mengatur nilainya (akhiri dengan titik koma), lalu pernyataan pilih Anda. Akhirnya, jalankan sebagai skrip (F5), bukan sebagai pernyataan (F9).
Amos M. Carpenter

Jawaban:

139

Ada beberapa cara mendeklarasikan variabel dalam skrip SQL * Plus.

Yang pertama adalah menggunakan VAR, untuk mendeklarasikan variabel bind. Mekanisme untuk menetapkan nilai ke VAR adalah dengan panggilan 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 sangat berguna ketika kita ingin memanggil prosedur tersimpan yang memiliki parameter atau fungsi OUT.

Atau kita bisa menggunakan variabel substitusi. Ini bagus untuk mode interaktif:

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>

Ketika kita sedang menulis sebuah skrip yang memanggil skrip lain, akan sangat berguna untuk mendefinisikan variabel di muka. Cuplikan ini berjalan tanpa meminta saya untuk memasukkan nilai:

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>

Akhirnya ada blok PL / SQL anonim. Seperti yang Anda lihat, kami masih dapat menetapkan nilai ke variabel yang dideklarasikan secara interaktif:

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
sumber
6
Semua baik, kecuali Anda menggunakan istilah "variabel terikat". Deklarasi VAR menciptakan variabel bind, sementara ACCEPT atau DEFINE membuat variabel substitusi.
Dave Costa
1
Apakah mungkin untuk menyatukan variabel + string?
Ecropolis
@Ecropolis - ya, dalam periode penggunaan SQL Plus secara default. Gunakan SET CONCAT untuk menentukan karakter yang memisahkan nama variabel substitusi dari karakter alfanumerik yang segera mengikuti nama variabel. Dalam PL / SQL atau SQL gunakan pipa ganda || untuk menyatukan.
Laszlo Lugosi
Jika SQL adalah bahasa standar, mengapa begitu sulit untuk menemukan referensi kanonik yang hanya bekerja di mana-mana? WTF ???
jww
1
@jww - SQL adalah standar tetapi tidak selalu menentukan sintaks yang tepat sehingga produk RDBMS yang berbeda dapat mengimplementasikan berbagai hal secara berbeda; aritmatika tanggal adalah contoh yang baik. Juga produk-produk database yang lebih lama seperti Oracle sering memperkenalkan fitur-fitur sebelum Standar membahasnya: misalnya sintaks HUBUNGI OLEH sintaksis. Tetapi dalam kasus ini kita membahas SQL * Plus, yang merupakan alat klien dan karenanya tidak tercakup oleh standar ANSI.
APC
28

Coba gunakan tanda kutip ganda jika itu variabel char:

DEFINE stupidvar = "'stupidvarcontent'";

atau

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
sumber
Terima kasih atas jawaban Anda, tetapi jika saya memasukkan var dalam tanda kutip ganda, saya mendapatkan ORA-01008: not all variables bound.
bl4ckb0l7
1
Tentu! DEFINE num = 1; SELECT &num FROM dual;mengarah ke: ORA-01008: not all variables bound
bl4ckb0l7
@ bl4ckb0l7 - Saya yakin Anda mencoba ini bukan dalam SQL * Plus.
Laszlo Lugosi
20

Dalam PL / SQL v.10

kata kunci menyatakan digunakan untuk mendeklarasikan variabel

DECLARE stupidvar varchar(20);

untuk menetapkan nilai, Anda dapat mengaturnya saat Anda mendeklarasikan

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

atau untuk memilih sesuatu ke dalam variabel yang Anda gunakan INTOpernyataan, namun Anda harus memasukkan pernyataan BEGINdan END, juga Anda perlu memastikan bahwa hanya nilai tunggal yang dikembalikan, dan jangan lupa titik koma.

jadi pernyataan lengkapnya akan keluar sebagai berikut:

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

Variabel Anda hanya dapat digunakan di dalam BEGINdan ENDjadi jika Anda ingin menggunakan lebih dari satu, Anda harus melakukan beberapa BEGIN ENDpembungkus

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;

Semoga ini menghemat waktu Anda

Matas Vaitkevicius
sumber
7

Jika Anda ingin mendeklarasikan tanggal dan kemudian menggunakannya dalam SQL Developer.

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

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

Hanya ingin menambahkan jawaban Matas . Mungkin sudah jelas, tapi saya sudah lama mencari untuk mengetahui bahwa variabel hanya dapat diakses di dalam konstruksi BEGIN-END , jadi jika Anda perlu menggunakannya dalam beberapa kode nanti, Anda harus memasukkan kode ini di dalam BEGIN -Blokir .

Perhatikan bahwa blok ini dapat disarangkan :

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
sumber
5

Pertanyaannya adalah tentang menggunakan variabel dalam skrip berarti bagi saya itu akan digunakan dalam SQL * Plus.

Masalahnya adalah Anda melewatkan tanda kutip dan Oracle tidak dapat menguraikan nilai ke angka.

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

Sampel ini berfungsi dengan baik karena konversi tipe otomatis (atau apa pun namanya).

Jika Anda memeriksa dengan mengetikkan DEFINE di SQL * Plus, itu akan menunjukkan bahwa variabel num adalah CHAR.

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

Ini bukan masalah dalam kasus ini, karena Oracle dapat menangani string parsing ke nomor jika itu akan menjadi nomor yang valid.

Ketika string tidak dapat menguraikan angka, maka Oracle tidak bisa mengatasinya.

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

Dengan kutipan, jadi jangan memaksa Oracle untuk menguraikan angka, akan baik-baik saja:

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

Jadi, untuk menjawab pertanyaan awal, harus dilakukan seperti contoh ini:

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

Ada cara lain untuk menyimpan variabel dalam SQL * Plus dengan menggunakan Nilai Kolom Kueri .

The COL [UMN] memiliki new_value pilihan untuk menyimpan nilai dari query dengan nama field.

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;

Seperti yang Anda lihat, nilai X.log diatur ke dalam variabel stupid_var , sehingga kita dapat menemukan file X.log di direktori saat ini memiliki beberapa login di dalamnya.

Laszlo Lugosi
sumber
2

Inilah jawaban Anda:

DEFINE num := 1;       -- The semi-colon is needed for default values.
SELECT &num FROM dual;
stephen meckstroth
sumber
1
Sama denganku. Saya menggunakan ODT dan menjalankan: DEFINE num: = 1; SELECT num FROM dual; Dan yang saya dapatkan adalah: ORA-00904: "NUM": pengidentifikasi tidak valid 00904. 00000 - "% s: pengidentifikasi tidak valid" * Penyebab: * Tindakan: Kesalahan pada Baris: 2 Kolom: 8
toha
0

Di Toad saya menggunakan karya ini:

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;

Maka nilainya akan dicetak ke DBMS OutputWindow.

Referensi ke sini dan sini2 .

yu yang Jian
sumber
0

Terkadang Anda perlu menggunakan variabel makro tanpa meminta pengguna untuk memasukkan nilai. Paling sering ini harus dilakukan dengan parameter skrip opsional. Kode berikut berfungsi penuh

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

Kode serupa entah bagaimana ditemukan di direktori rdbms / sql.

pengguna12273401
sumber
0

Salah satu pendekatan yang mungkin, jika Anda hanya perlu menentukan parameter sekali dan mereplikasi di beberapa tempat, adalah melakukan sesuatu seperti ini:

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

Kode ini menghasilkan string 8 digit acak.

Perhatikan bahwa saya membuat semacam alias bernama str_sizeyang memegang konstanta 8. Ini bergabung-silang untuk digunakan lebih dari sekali dalam kueri.

Diego Queiroz
sumber