Hej Jag har en tabell med namnet CITY i Oracle SQL-utvecklare, mitt problem är hur man kör 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;
skapa proceduren
CREATE OR REPLACE PACKAGE hotel AS PROCEDURE fill_city(number_city NUMBER) END hotel; / SHOW ERRORS;
och hur ska man nu utföra proceduren?
--EXECUTE fill_city(10000) ; Begin fill_city(10000); End;
Jag försökte båda men med tur.
Jag fick följande fel
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
Först, om du skapar en procedur i ett paket, måste paketnamnet inkluderas när du ringer till proceduren.
begin hotel.fill_city(10000); end; /
bör anropa din procedur korrekt.
För det andra har du problem med namnet på dina lokala variabler. Normalt skulle du inte skapa lokala variabler som city
och postal_number
som är samma som namnen på kolumner i tabeller i din databas. Det gör det alldeles för lätt att införa fel i din kod där du tänker hänvisa till den lokala variabeln men regler för omfattningsupplösning betyder att du verkligen hänvisar till kolumnnamnet. Om du till exempel skriver den perfekt giltiga funktionen
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
-sats, båda hänvisningarna till deptno
löser sig till kolumnen i dept
tabellen, inte till parametern deptno
. Det betyder att oavsett vilket värde du skickar in till funktionen kommer SELECT
-uttrycket att returneras varje rad från bordet och därmed kasta ett too_many_rows
fel. Normalt skulle du komma med en konvention om hur du namnge variabler och parametrar som inte skulle strida mot dina tabellnamnkonventioner. Prefixing av parametrar med p_
och lokala variabler med l_
är en vanlig konvention. Det gör vår funktion till något liknande
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;
Det andra alternativet skulle vara att använda explicita scope-prefix när man hänvisar till lokala variabler (dvs. get_dname.dname
och get_dname.deptno
) snarare än att ändra namnen på dina lokala variabler.