web-dev-qa-db-ja.com

Oracle SQL開発者でプロシージャを実行する方法

こんにちは、Oracle SQL開発者にCITYという名前のテーブルがあります。私の問題は、プロシージャの実行方法です。

-- start the script

SET SERVEROUTPUT ON
SET LINESIZE 400
SET TIMING ON

CREATE OR REPLACE PACKAGE BODY hotel AS

    -- -----------------------------------------------------
    -- Table city
    -- -----------------------------------------------------
    PROCEDURE fill_city(number_city NUMBER) IS
        city VARCHAR2(100);
        postna_st VARCHAR2(4);

    BEGIN
        FOR st IN 1..number_city LOOP
            city:= dbms_random.string('a',100);
            postal_number:= dbms_random.value(1000,9000);
            INSERT INTO CITY(city, postal_number) VALUES (city, postal_number);
        END LOOP;
    END;

BEGIN 
    NULL;
END hotel;
/

SHOW ERRORS;

プロシージャの作成

CREATE OR REPLACE PACKAGE hotel AS
    PROCEDURE fill_city(number_city NUMBER)
END hotel;
/

SHOW ERRORS;

そして今どのように手順を実行するのですか?

--EXECUTE fill_city(10000) ;
Begin 
 fill_city(10000);
End;

私は両方を試しましたが、運が良かったです。

次のエラーを受け取りました

 Error report:
ORA-06550: line 2, column 2:
PLS-00201: identifier 'fill_city' must be declared
ORA-06550: line 2, column 2:
PL/SQL: Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:
Elapsed: 00:00:00.018
6
Andrej

まず、パッケージにプロシージャを作成する場合は、プロシージャを呼び出すときにパッケージ名を含める必要があります。

begin
  hotel.fill_city(10000);
end;
/

プロシージャを正しく呼び出す必要があります。

次に、ローカル変数の命名に問題があります。通常、citypostal_numberなどのローカル変数は、データベース内のテーブルの列の名前と同じには作成しません。これにより、ローカル変数を参照しようとするコードでエラーが発生しやすくなりますが、スコープ解決ルールでは、実際に列名を参照していることになります。たとえば、完全に有効な関数を記述した場合

CREATE OR REPLACE FUNCTION get_dname( deptno IN NUMBER )
  RETURN VARCHAR2
IS
  dname VARCHAR2(30);
BEGIN
  SELECT dname
    INTO dname
    FROM dept
   WHERE deptno = deptno;
  RETURN dname;
END;

WHERE句では、deptnoへの参照は両方とも、パラメータdeptではなく、deptnoテーブルの列に解決されます。つまり、関数に渡す値に関係なく、SELECTステートメントはテーブルのすべての行を返すため、too_many_rowsエラーがスローされます。通常、テーブルの命名規則と競合しない変数とパラメーターの命名方法についての規則が考えられます。パラメータの前にp_を付け、ローカル変数にl_を付けます。それは私たちの機能をこのようなものに変えます

CREATE OR REPLACE FUNCTION get_dname( p_deptno IN NUMBER )
  RETURN VARCHAR2
IS
  l_dname VARCHAR2(30);
BEGIN
  SELECT dname
    INTO l_dname
    FROM dept
   WHERE deptno = p_deptno;
  RETURN l_dname;
END;

他のオプションは、ローカル変数の名前を変更するのではなく、ローカル変数(つまりget_dname.dnameおよびget_dname.deptno)を参照するときに明示的なスコーププレフィックスを使用することです。

10
Justin Cave