Considering the following function: Which of the following code will work fine?
Questão
Considering the following function: Which of the following code will work fine?
CREATE OR REPLACE FUNCTION get_avg_sal (p_dept_id number) RETURN number AS
v_avg_sal number;
BEGIN
SELECT avg(salary) INTO v_avg_sal FROM employees WHERE department_id = p_dept_id;
UPDATE func_usages SET number_of_usage = number_of_usage+1;
RETURN v_avg_sal;
END get_avg_sal;
Alternativas
SELECT get_avg_sal(50) FROM dual;
SELECT get_avg_sal('50') FROM dual;
SELECT get_avg_sal(sysdate-hire_date) FROM employees WHERE employee_id = 100;
None of them will work
Explicação
A função get_avg_sal(p_dept_id NUMBER) faz duas coisas: (1) consulta a média de salário e (2) executa um UPDATE em func_usages.
Em Oracle, uma função chamada dentro de um SELECT (SQL) deve ser “SQL-safe” (não pode ter efeitos colaterais), isto é, não pode executar DML (INSERT/UPDATE/DELETE/MERGE) diretamente. Caso contrário, ao executar algo como SELECT get_avg_sal(...) FROM dual;, ocorrerá erro (tipicamente do tipo ORA-14551: cannot perform a DML operation inside a query).
Analisando as opções:
SELECT get_avg_sal(50) FROM dual;
- O parâmetro está correto (número), mas a função faz
UPDATE→ não pode ser usada emSELECT.
SELECT get_avg_sal('50') FROM dual;
- Além do mesmo problema do
UPDATE, o literal'50'éVARCHAR2, mas o Oracle normalmente faria conversão implícita paraNUMBER. Mesmo assim, continua inválida noSELECTpor causa do DML.
SELECT get_avg_sal(sysdate-hire_date) FROM employees WHERE employee_id = 100;
sysdate - hire_dateresulta em um NUMBER (diferença em dias), então o tipo até “casa” com o parâmetro. Porém, continua o mesmo problema: a função executaUPDATEe não pode ser chamada em consulta SQL.
Logo, nenhuma das alternativas com SELECT funciona com essa implementação da função.
Alternativa correta: (d).