2013-05-30 2 views
1
CREATE TABLE WORK(
WorkerNo NUMBER(10) NOT NULL, 
TotalSalary NUMBER(10), 
CONSTRAINT WORK_PKEY PRIMARY KEY (WorkerNo), 

INSERT INTO WORK(1, NULL); 
INSERT INTO WORK(2, NULL); 

CREATE TABLE WorkSalary(
City VARCHAR2(30), 
Postal VARCHAR2(30), 
Salary NUMBER(9) NOT NULL, 
CONSTRAINT WorkSalary_PKEY PRIMARY KEY(City,Postal), 

INSERT INTO WorkSalary('New York City', '123456', 5000); 
INSERT INTO WorkSalary('Washington DC', '154876', 4500); 
INSERT INTO WorkSalary('New Jersey', '458741', 3500); 
INSERT INTO WorkSalary('Maryland', '487451', 2000); 

CREATE TABLE WORKDONE(
WorkerNo NUMBER(10)  NOT NULL, 
JobNo NUMBER(2)  NOT NULL, 
City VARCHAR2(30) NOT NULL, 
Postal VARCHAR2(30) NOT NULL, 
CONSTRAINT WORKDONE_PKEY PRIMARY KEY (WorkerNo, JobNo), 
CONSTRAINT WORKDONE_FKEY1 FOREIGN KEY (WorkerNo) 
    REFERENCES WORK(WorkerNo), 
CONSTRAINT WORKDONE_FKEY2 FOREIGN KEY (City) 
    REFERENCES WorkSalary(City), 
CONSTRAINT WORKDONE_FKEY3 FOREIGN KEY (Postal) 
    REFERENCES WorkSalary(Postal)); 

INSERT INTO WORKDONE VALUES(1, 1, 'New York City', '123456'); 
INSERT INTO WORKDONE VALUES(1, 2, 'Maryland', '487451'); 
INSERT INTO WORKDONE VALUES(1, 3, 'New Jersey', '458741'); 
INSERT INTO WORKDONE VALUES(2, 1, 'New Jersey', '458741'); 
INSERT INTO WORKDONE VALUES(2, 2, 'New York City', '123456'); 
INSERT INTO WORKDONE VALUES(2, 3, 'Washington DC', '154876'); 

Мне нужно создать функцию, которая получает сумму всей зарплаты, которую работник сделал на столе. например, workerno 1 выполнил 3 задания, которые показаны на рабочей таблице. мне нужно получить зарплату за каждую выполненную им работу в соответствии с местом, где он работает, ссылаясь на зарплату в таблице. то я добавлю всю свою зарплату, заработанную все вместе, и вложу общую зарплату для этого работника в таблицу, которая имеет итоговый итог столбца.Функция создания PLSQL, которая добавляет все значения из столбца и вставляет сумму в новый столбец

CREATE OR REPLACE FUNCTION SALARYCOUNT (worker_no IN NUMBER) RETURN NUMBER IS 
wcity WORKDONE.City%TYPE; 
wpostal WORKDONE.Postal%TYPE; 
total NUMBER: 
i INTEGER: = 1; 
total_salary NUMBER; 
wsalary NUMBER; 


BEGIN 

SELECT COUNT(*) 
INTO total 
FROM WORKDONE 
WHERE WorkerNo = worker_no; 

WHILE i < total 
LOOP 

SELECT City,Postal INTO wcity,wpostal FROM WORKDONE WHERE WorkerNo = worker_no; 

SELECT Salary INTO wsalary FROM WorkSalary WHERE wcity = City AND wpostal = Postal; 

total_salary: =total_salary+wsalary ; 

UPDATE WORK SET TotalSalary: = total_salary 
WHERE WorkerNo = worker_no; 

i: = i+1; 

END LOOP; 

RETURN(total_salary); 

END SALARYCOUNT ; 
/

функция создана с ошибкой компиляции. Я знаю, что если я могу создать функцию без ошибок, моя логика создания этой функции может быть неверной. пожалуйста, помогите мне с ошибкой и логикой кода. Я очень новичок в этом.

+2

Не используйте функцию для выполнения операторов DML (UPDATE/INSERT и т. Д.). Используйте процедуру. Функция должна вызываться в инструкции SQL, и вы не можете делать инструкции DML при выборе ... – Ben

+0

Мне нужно использовать как функцию – user2351750

+1

Вы используете _cannot_ как функцию, если вы не назначаете возвращаемое значение непосредственно в PL/SQL. Если вы это сделаете, вы можете использовать параметр OUT как [описанный в документации] (http://docs.oracle.com/cd/E11882_01/server.112/e26088/statements_6009.htm#SQLRF01309). – Ben

ответ

2

Во-первых, как я уже сказал в комментариях, не используйте функцию для выполнения операторов DML (UPDATE/INSERT и т. Д.). Используйте процедуру. Функция должна вызываться в инструкции SQL, и вы не можете выполнять инструкции DML при выборе.

Во-вторых внешний ключ на WORKDONE неверен, вы должны добавить как CITY и POSTAL во внешнем ключе же:

CONSTRAINT WORKDONE_FKEY2 FOREIGN KEY (City, Postal) 
    REFERENCES WorkSalary(City, Postal) 

В-третьих, и больше запиской на будущее, ваша установка вашей среды неверно; это полезно, если вы проверите это перед публикацией вопроса.

Наконец, нет абсолютно никакой необходимости использовать функцию для этого. Все это можно сделать в одном заявлении MERGE. Практически всегда более эффективно использовать один оператор SQL, а не PL/SQL.

merge into work m 
using (select wd.workerno, sum(ws.salary) as salary 
      from workdone wd 
      join worksalary ws 
      on wd.city = ws.city 
      and wd.postal = ws.postal 
      group by wd.workerno) u 
    on (m.workerno = u.workerno) 
    when matched then 
update 
    set m.totalsalary = u.salary; 

Для того, чтобы продемонстрировать работу SQL Fiddle.

+0

.... мои требования к hmwork только с помощью функции -.- .... – user2351750

+1

Тот, кто поставил вам домашнее задание, не учит вас очень хорошо, а затем @ user2351750. Однако вы должны легко изменить это, чтобы работать в функции. – Ben