Hallo, ich habe eine Tabelle mit dem Namen CITY in Oracle SQL Developer. Mein Problem ist das Ausführen der Prozedur
-- 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;
Erstellen der Prozedur
CREATE OR REPLACE PACKAGE hotel AS PROCEDURE fill_city(number_city NUMBER) END hotel; / SHOW ERRORS;
und wie wird die Prozedur ausgeführt?
--EXECUTE fill_city(10000) ; Begin fill_city(10000); End;
Ich habe beide versucht, aber mit etwas Glück.
Ich habe den folgenden Fehler erhalten
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
Antwort
Wenn Sie eine Prozedur in einem Paket erstellen, muss der Paketname beim Aufruf der Prozedur angegeben werden.
begin hotel.fill_city(10000); end; /
sollte Ihre Prozedur korrekt aufrufen.
Zweitens haben Sie Probleme mit der Benennung Ihrer lokalen Variablen. Normalerweise würden Sie keine lokalen Variablen wie city
und postal_number
erstellen, die den Namen der Spalten in Tabellen in Ihrer Datenbank entsprechen. Das macht es viel zu einfach, Fehler in Ihren Code einzufügen, wenn Sie auf die lokale Variable verweisen möchten, aber Regeln für die Bereichsauflösung bedeuten, dass Sie sich wirklich auf den Spaltennamen beziehen. Wenn Sie beispielsweise die perfekt gültige Funktion
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;
in Ihre WHERE
-Klausel schreiben, verweisen beide auf deptno
wird in die Spalte in der Tabelle dept
aufgelöst, nicht in den Parameter deptno
. Dies bedeutet, dass die Anweisung SELECT
unabhängig davon, welchen Wert Sie an die Funktion übergeben, jede Zeile aus der Tabelle zurückgibt und somit eine too_many_rows
Fehler. Normalerweise würden Sie eine Konvention zum Benennen von Variablen und Parametern entwickeln, die nicht mit Ihren Namenskonventionen für Tabellen in Konflikt steht. Das Präfixieren von Parametern mit p_
und lokalen Variablen mit l_
ist eine gängige Konvention. Das macht unsere Funktion zu so etwas
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;
Die andere Option wäre, explizite Bereichspräfixe zu verwenden, wenn auf lokale Variablen verwiesen wird (dh get_dname.dname
und get_dname.deptno
), anstatt die Namen Ihrer lokalen Variablen zu ändern.