Değişken nasıl bildirilir ve aynı Oracle SQL betiğinde nasıl kullanılır?


133

Yeniden kullanılabilir kod yazmak istiyorum ve başlangıçta bazı değişkenler tanımlamam ve bunları komut dosyasında yeniden kullanmam gerekiyor, örneğin:

DEFINE stupidvar = 'stupidvarcontent';

SELECT stupiddata
FROM stupidtable
WHERE stupidcolumn = &stupidvar;

Bir değişkeni nasıl bildirebilirim ve onu SQLDeveloper gibi aşağıdaki ifadelerde yeniden kullanabilirim.


Denemeler

  • Bir BILDIRMEK bölümünü kullanın ve bu sorgu eklemek BEGINve END;. Kullanarak değişkene erişir &stupidvar.
  • Anahtar kelimeyi kullanın DEFINEve değişkene erişin.
  • Anahtar kelimeyi kullanarak VARIABLEve değişkene erişin.

Ancak denemelerim sırasında her türlü hatayı alıyorum (Sınırsız değişken, Sözdizimi hatası, Beklenen SELECT INTO...).


2
@APC tarafından kabul edilen cevaptaki yaklaşımın PL / SQL olmadan, örneğin sorunuza göre bir SQL Developer çalışma sayfasında kullanılabileceğini unutmayın. Değişkeni bir satırda (noktalı virgül yok), ardından değerini ayarlamak için exec satırını (noktalı virgülle biten) ve ardından select ifadenizi bildirin. Son olarak, bunu bir ifade (F9) olarak değil, bir komut dosyası (F5) olarak çalıştırın.
Amos M. Carpenter

Yanıtlar:


139

SQL * Plus betiklerinde değişkenleri tanımlamanın birkaç yolu vardır.

Birincisi, bir bağlanma değişkeni bildirmek için VAR kullanmaktır. Bir VAR'a değer atama mekanizması bir EXEC çağrısıdır:

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>

Bir VAR, OUT parametreleri veya bir işlevi olan bir saklı yordamı çağırmak istediğimizde özellikle yararlıdır.

Alternatif olarak ikame değişkenleri kullanabiliriz. Bunlar etkileşimli mod için iyidir:

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>

Diğer betikleri çağıran bir betik yazarken, değişkenleri önceden TANIMLAMAK yararlı olabilir. Bu pasaj, bir değer girmemi istemeden çalışıyor:

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>

Son olarak anonim PL / SQL bloğu var. Gördüğünüz gibi, tanımlanmış değişkenlere etkileşimli olarak değerler atayabiliriz:

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
"Bağlayıcı değişken" terimini kullanmanız dışında her şey yolunda. VAR bildirimi bir bağlama değişkeni yaratırken, ACCEPT veya DEFINE bir ikame değişkeni oluşturur.
Dave Costa

1
Değişkenleri + dizeleri birleştirmek mümkün mü?
Ecropolis

@Ecropolis - evet, SQL Plus varsayılan olarak kullanım periyodunda. Bir ikame değişkeninin adını, değişken adını hemen takip eden alfasayısal karakterlerden ayıran karakteri tanımlamak için CONCAT AYARLA'yı kullanın. PL / SQL veya SQL'de çift boru kullanın || birleştirmek için.
Laszlo Lugosi

SQL standart bir dilse, her yerde çalışan bir kanonik referans bulmak neden bu kadar zor? O NE LAN???
jww

1
@jww - SQL bir standarttır, ancak her zaman tam sözdizimini belirtmez, bu nedenle farklı RDBMS ürünleri işleri farklı şekilde uygulayabilir; tarih aritmetiği iyi bir örnektir. Ayrıca Oracle gibi eski veritabanı ürünleri, Standardın kapsamından önce sık sık özellikler sunmuştur: örneğin hiyerarşik CONNECT BY sözdizimi. Ancak bu durumda, bir istemci aracı olan ve bu nedenle ANSI standardı tarafından kapsanmayan SQL * Plus'ı tartışıyoruz.
APC

28

Bir char değişkeni ise çift tırnak kullanmayı deneyin:

DEFINE stupidvar = "'stupidvarcontent'";

veya

DEFINE stupidvar = 'stupidvarcontent';

SELECT stupiddata  
FROM stupidtable  
WHERE stupidcolumn = '&stupidvar'

gnc:

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

Cevabınız için teşekkür ederim, ancak değişkeni çift tırnak içine eklersem, bir ORA-01008: not all variables bound.
bl4ckb0l7

1
Elbette! DEFINE num = 1; SELECT &num FROM dual;yol açar: ORA-01008: not all variables bound
bl4ckb0l7

@ bl4ckb0l7 - Bahse girerim bunu SQL * Plus'ta denemiyorsunuzdur.
Laszlo Lugosi

20

PL / SQL v.10'da

anahtar kelime bildirimi, değişken bildirmek için kullanılır

DECLARE stupidvar varchar(20);

bir değer atamak için beyan ettiğinizde ayarlayabilirsiniz

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

veya INTOifadeyi kullandığınız değişkene bir şey seçmek için , ancak ifadeyi içine sarmalısınız BEGINve ENDayrıca yalnızca tek bir değerin döndürüldüğünden emin olmalısınız ve noktalı virgülleri unutmayın.

böylece tam ifade şu şekilde çıkar:

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

Değişkeniniz yalnızca içinde kullanılabilir BEGINve ENDbu nedenle birden fazla kullanmak istiyorsanız, birden fazla BEGIN ENDsarmalama yapmanız gerekecektir.

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;

Umarım bu sana biraz zaman kazandırır


7

Tarihi bildirmek ve ardından SQL Developer'da kullanmak istiyorsanız.

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

SELECT * 
FROM proposal 
WHERE prop_start_dt = &PROPp_START_DT

5

Sadece Matas'ın cevabını eklemek istiyorum . Belki açıktır, ancak değişkene yalnızca BEGIN-END yapısının içinden erişilebileceğini bulmak için uzun bir süre aradım , bu nedenle onu daha sonra bir kodda kullanmanız gerekirse, bu kodu BEGIN'in içine koymanız gerekir. -SON blok .

Bu blokların yuvalanabileceğini unutmayın :

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

Soru, bir komut dosyasında bir değişken kullanmak üzere olması, bana göre onun SQL * Plus'ta kullanılacağı anlamına geliyor.

Sorun şu ki, teklifleri kaçırdınız ve Oracle değeri sayıya ayrıştıramıyor.

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

Bu örnek, otomatik tür dönüştürme (veya adı ne olursa olsun) nedeniyle iyi çalışıyor.

SQL * Plus'ta DEFINE yazarak kontrol ederseniz, num değişkeninin CHAR olduğunu gösterir.

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

Bu durumda sorun olmaz, çünkü Oracle geçerli bir sayı olacaksa dizeyi sayıya göre ayrıştırabilir.

Dizge sayıya ayrıştırılamadığında, Oracle onunla başa çıkamaz.

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

Bir alıntıyla, Oracle'ı sayıya ayrıştırmaya zorlamayın, sorun olmaz:

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

Yani, orijinal soruyu cevaplamak için aşağıdaki örnek gibi yapılmalıdır:

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

Sorgu Sütunu Değerini kullanarak değişkeni SQL * Plus'ta depolamanın başka bir yolu vardır .

COL [UMN] sahip new_value sorgu alanı adıyla değeri saklamak için bir seçenek.

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;

Gördüğünüz gibi, X.log değeri stupid_var değişkenine ayarlandı , bu nedenle mevcut dizinde bir X.log dosyası bulabiliriz, içinde bir miktar günlük var.


2

İşte cevabınız:

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

1
Benimle aynı. ODT kullanıyorum ve şunu çalıştırıyorum: DEFINE num: = 1; Dual'den num SEÇİN; Ve şunu elde ediyorum: ORA-00904: "NUM": geçersiz tanımlayıcı 00904. 00000 - "% s: geçersiz tanımlayıcı" * Neden: * İşlem: Satırda Hata: 2 Sütun: 8
toha

0

Toad'da bu işleri kullanıyorum:

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;

Ardından değer DBMS OutputPencereye yazdırılacaktır .

Buraya ve buraya referans 2 .


0

Bazen kullanıcıdan bir değer girmesini istemeden bir makro değişkeni kullanmanız gerekir. Çoğu zaman bu, isteğe bağlı komut dosyası parametreleriyle yapılmalıdır. Aşağıdaki kod tamamen işlevseldir

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

Benzer kod bir şekilde rdbms / sql dizininde bulundu.


0

Olası bir yaklaşım, bir parametreyi yalnızca bir kez belirtmeniz ve onu birkaç yerde çoğaltmanız gerekiyorsa, aşağıdaki gibi bir şey yapmaktır:

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

Bu kod, 8 rastgele basamaktan oluşan bir dizi oluşturur.

str_sizeSabiti tutan bir tür takma ad oluşturduğuma dikkat edin 8. Sorguda birden fazla kullanılmak üzere çapraz birleştirilmiştir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.