Hej Jeg har en tabel med navnet CITY i oracle SQL-udvikler, mit problem er, hvordan man kører proceduren
-- 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;
oprettelse af proceduren
CREATE OR REPLACE PACKAGE hotel AS PROCEDURE fill_city(number_city NUMBER) END hotel; / SHOW ERRORS;
og hvordan udføres proceduren nu?
--EXECUTE fill_city(10000) ; Begin fill_city(10000); End;
Jeg prøvede begge, men med held.
Jeg modtog følgende fejl
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
Svar
Hvis du opretter en procedure i en pakke, skal pakkens navn medtages, når du ringer til proceduren.
begin hotel.fill_city(10000); end; /
skal påkalde din procedure korrekt.
For det andet har du problemer med navngivningen af dine lokale variabler. Normalt opretter du ikke lokale variabler som city
og postal_number
, der er de samme som kolonnerne i tabellerne i din database. Det gør det alt for nemt at introducere fejl i din kode, hvor du har til hensigt at henvise til den lokale variabel, men regler for omfangsopløsning betyder, at du virkelig henviser til kolonnenavnet. For eksempel, hvis du skriver den perfekt gyldige 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;
i din WHERE
klausul, begge henvisninger til deptno
løser kolonnen i dept
-tabellen, ikke parameteren deptno
. Det betyder, at uanset hvilken værdi du videregiver til funktionen, vil SELECT
udsagn returnere hver række fra bordet og dermed kaste en too_many_rows
fejl. Normalt vil du komme med en konvention om, hvordan du navngiver variabler og parametre, der ikke er i konflikt med dine tabelnavngivningskonventioner. Forudindstillingsparametre med p_
og lokale variabler med l_
er en almindelig konvention. Det gør vores funktion til noget som dette
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;
Den anden mulighed ville være at bruge eksplicitte scoping-præfikser, når vi henviser til lokale variabler (dvs. get_dname.dname
og get_dname.deptno
) i stedet for at ændre navnene på dine lokale variabler.