Ciao, ho una tabella denominata CITY nello sviluppatore Oracle SQL, il mio problema è come eseguire la procedura
-- 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;
creare la procedura
CREATE OR REPLACE PACKAGE hotel AS PROCEDURE fill_city(number_city NUMBER) END hotel; / SHOW ERRORS;
e ora come eseguire la procedura?
--EXECUTE fill_city(10000) ; Begin fill_city(10000); End;
Ho provato entrambi ma con fortuna.
Ho ricevuto il seguente errore
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
Risposta
Primo, se stai creando una procedura in un pacchetto, il nome del pacchetto dovrà essere incluso quando chiami la procedura.
begin hotel.fill_city(10000); end; /
dovrebbe richiamare correttamente la tua procedura.
Secondo, hai problemi con la denominazione delle tue variabili locali. Normalmente, non creeresti variabili locali come city
e postal_number
che sono gli stessi dei nomi delle colonne nelle tabelle del tuo database. Ciò rende fin troppo facile introdurre errori nel codice in cui si intende fare riferimento alla variabile locale, ma le regole di risoluzione dellambito indicano che ci si riferisce realmente al nome della colonna. Ad esempio, se scrivi la funzione perfettamente valida
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;
nella tua clausola WHERE
, entrambi i riferimenti a deptno
verrà risolto nella colonna nella tabella dept
, non nel parametro deptno
. Ciò significa che indipendentemente dal valore che passi alla funzione, listruzione SELECT
restituirà ogni riga della tabella e, quindi, genererà un too_many_rows
errore. Normalmente, si creerebbe una convenzione su come denominare variabili e parametri che non sarebbero in conflitto con le convenzioni di denominazione delle tabelle. Una convenzione comune è anteporre ai parametri p_
e alle variabili locali l_
. Questo trasforma la nostra funzione in qualcosa del genere
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;
Laltra opzione sarebbe quella di utilizzare prefissi di scoping espliciti quando ci si riferisce a variabili locali (ad esempio get_dname.dname
e get_dname.deptno
) invece di alterare i nomi delle variabili locali.