私はSQL Serverの出身ですが、Oracle PL/SQL変数の使用方法を理解しようとしています。変数を宣言してから、その変数を選択しようとしています。簡単に聞こえますが、私は何か間違ったことをしています。これが私のコードです:
declare
num number;
begin
num := 64;
select num from dual; --error here
end;
/
これにより、「PLS-00428:このSELECTステートメントにはINTO句が必要です」というエラーメッセージが表示されます。
私はこれの他のいくつかの順列を試しましたが、それぞれがエラーを出します:
declare
num number;
begin
num := 64;
end;
select num from dual; --"num" invalid identifier
/
これもエラーになります。
declare
num number;
begin
num := 64;
end;
/
select num from dual; --"num" invalid identifier
ミハイのコメントに基づいて、私は宣言を最初に置いてみましたが、それもエラーをスローしました:
begin
declare
num number;
num := 64; --encountered symbol "=" when expecting ...
end;
/
select num from dual; --"num" invalid identifier
参考までに、SQL Serverでこれを行う方法を次に示します。明確ではないかもしれませんが、以下の@num変数のスコープは宣言を含むファイルです。この変数はグローバルではありません。
declare @num int = 64
select @num
これはDBArtisanです。この質問は this this here に似ていますが、変数をuseする方法も尋ねています。そして、私はバインド変数に興味がありません(私は思いません)。このような1回限りのクエリを記述したいと思います:select * from employee where manager_id = mgrID
は、私が宣言する変数であるmgrIDを使用します。
これらの回答はすべて、a)非常に複雑になっており、b)user2023861が達成したいことと比較して、軌道に乗っていないと思います。
「変数を宣言してから、その変数を選択しようとしています。」 PL/SQLまたはSQLplusのいずれかで2つの異なることを意味し、DBArtisanでさらに2つのことを意味します。 SQLplusで目的を達成するには、「置換変数」を使用します... 優れた背景がここにあります。
私の例は、SQL Server T-SQLの例に厳密に従っていませんが、近いものであり、手続き型ではありません(読み取り:匿名のPL/SQLブロックはありません。)
PL/SQLと置換変数:
DEFINE min_salary = 1000
DEFINE mgrID = 7
select *
from employees
where
salary > &min_salary
and mgrID = &mgrID
;
すべてSQL-Plusプロンプトで...架空の従業員テーブルから、次の結果を得ました。
SALARY MGRID
---------- ----------
2000 7
1001 7
2 row selected.
この半手続きを作成する場合は、BIND変数と、T-SQLに類似したPL/SQLの宣言構文を使用します。 (私の意見では、これは多大な労力の浪費ですが、変数の型を明確にするために含まれています。)
PL/SQLバインド変数を使用したSQLPlus:
VARIABLE v_in_min_salary number;
VARIABLE v_mgrID number; /* vars are defined within SQL+ */
VARIABLE v_out_salary number;
VARIABLE v_out_mgrID number;
BEGIN
:v_in_min_salary := 1000; /* vars are assigned values in PL/SQL */
:v_mgrID := 7;
select salary, mgrID
into :v_out_salary, :v_out_mgrID
from employees
where salary > :v_in_min_salary and mgrID = :v_mgrID
;
end;
/
PRINT :v_in_min_salary /* here the in and out vars are displayed */
PRINT :v_mgrID
PRINT :v_out_salary
PRINT :v_out_mgrID
PL/SQLを使用した完全手続き型アプローチ:
set serveroutput on; /* environment setting within SQLplus to see output */
DECLARE
v_in_min_salary number := 1000;
v_mgrID number :=7;
v_out_salary number;
v_out_mgrID number;
BEGIN
SELECT salary, mgrID
into :v_out_salary, :v_out_mgrID
from employees
where salary > :v_in_min_salary and mgrID = :v_mgrID
;
DBMS_OUTPUT.PUT_LINE('Salary Output is= '||:v_out_salary);
DBMS_OUTPUT.PUT_LINE('Manager ID = '||:v_out_mgrID);
END;
/
それで、いつそれぞれの場合を使うのですか?入力をパラメーター化するSQLスクリプトを作成するときは、75%の確率でSQLplus Substitution変数を使用します。 SQLplusプロンプトでスクリプトを実行すると、入力引数を渡すことができるため、次の例のように、私のお気に入りの置換変数は&1と&2です。
@get_table_size.sql <schema> <table_name>
which in practice becomes
@get_table_size jason employees
と同様のSQLコードを実行します
SELECT extents
FROM all_tables
WHERE UPPER(table_owner) = upper('&1') /* inbound first argument */
and UPPER(table_name) = upper('&2') /* inbound 2nd argument */
;
インバウンド引数がどのように置換変数に割り当てられ、SQLステートメントで使用されるかに注意してください。私は真ん中の例を決して使用せず、関数、プロシージャ、およびパッケージを作成するときは常に3番目の例(手続き型PL/SQL)を使用します。
最初の試みは、無名PL/SQLブロックの正しい構文です。
エラーメッセージ
このSELECTステートメントにはINTO句が必要です
問題が何であるかを正確にあなたに言いました。
ストアドプロシージャ(またはPL/SQLブロック)内で単に「選択」して、そこから結果を魔法のように「返す」ことはできません。これは、PL/SQLとT-SQLの根本的な違いです。
プロシージャが結果を返すようにする場合は、出力パラメータとしてREF CURSORが必要か、結果セットを返す関数を作成する必要があります。ただし、どちらの場合も、プロシージャ/関数を呼び出すだけではできません。プロシージャがREF CURSORを返すか、テーブルの代わりに明示的に使用する場合、呼び出し元は結果を何らかの形で消費する必要があります。 select * from table(my_function());
ここに私がまとめたオプションがあります。これは仕事を終わらせ、醜い定型コードを回避します。
with vars as
(
select
1000 v_min,
7 v_mgrID
from dual
)
select *
from employees
where
salary > (select v_min from vars)
and mgrID = (select v_mgrID from vars)
これは最もパフォーマンスの高いコードではないかもしれませんが、理解するのは簡単です。変数の読み書きに関するPL/SQLのドキュメントは非常に貧弱であることがわかりました。私は間違いを証明して喜んでいますが、次のTSQLコードで示されているのと同じ概念を含むPL/SQLコードの簡単な例を見つけることができません。
declare @min_salary int = 1000
declare @mgrID int = 7
select *
from employees
where
salary > @min_salary
and mgrID = @mgrID
このコードを使用すると、カーソル、ループ、コードブロックについて知る必要はありません。