do bÁsico ao avanÇado para manipulaÇÃo e … · É possível utilizar sub-consultas em dml...

46
DO BÁSICO AO AVANÇADO PARA MANIPULAÇÃO E OTIMIZAÇÃO DE DADOS Fábio Roberto Octaviano

Upload: trinhliem

Post on 14-Jul-2018

216 views

Category:

Documents


0 download

TRANSCRIPT

DO BÁSICO AO AVANÇADO PARA

MANIPULAÇÃO E OTIMIZAÇÃO DE DADOS

Fábio Roberto Octaviano

Manipulando Grandes Volumes de Dados

Após o término do Capítulo:

Manipular dados utilizando sub-consultas.

Descrever as características de INSERTs em múltiplas tabelas.

Utilizar os tipos de INSERTs em múltiplas tabelas: ◦ INSERT Incondicional.

◦ INSERT Pivotante.

◦ ALL INSERT Condicional.

◦ FIRST INSERT Condicional.

Comando MERGE.

Rastrear as alterações de dados em um período.

É possível utilizar sub-consultas em DML para:

◦ Copiar dados de uma tabela para outra.

◦ Recuperar dados de uma view inline.

◦ Atualizar dados em uma tabela com base em valores de outra tabela.

◦ Remover linhas de uma tabela com base em linhas de outra tabela.

Copiando linhas de outras tabelas:

Inserts com sub-consulta como destino:

INSERT INTO sales_reps(id, name, salary, commission_pct)

SELECT employee_id, last_name, salary, commission_pct

FROM employees

WHERE job_id LIKE '%REP%';

INSERT INTO

(SELECT employee_id, last_name,

email, hire_date, job_id, salary,

department_id

FROM empl3

WHERE department_id = 50)

VALUES (99999, 'Taylor', 'DTAYLOR',

TO_DATE('07-JUN-99', 'DD-MON-RR'),

'ST_CLERK', 5000, 50);

Recuperando dados a partir de uma sub-consulta:

SELECT a.last_name, a.salary,

a.department_id, b.salavg

FROM employees a JOIN(SELECT department_id,

AVG(salary) salavg

FROM employees

GROUP BY department_id) b

ON a.department_id = b.department_id

AND a.salary > b.salavg;

Atualizando diversas colunas com sub-consultas:

UPDATE empl3

SET job_id = (SELECT job_id

FROM employees

WHERE employee_id = 205),

salary = (SELECT salary

FROM employees

WHERE employee_id = 168)

WHERE employee_id = 114;

Removendo linhas utilizando sub-consultas:

DELETE FROM empl3

WHERE department_id =

(SELECT department_id

FROM departments

WHERE department_name

LIKE '%Public%');

1 row deleted.

Utilizando o WITH CHECK OPTION: ◦ Proíbe a alteração de linhas que não fazem parte do

contexto da sub-consulta:

INSERT INTO (SELECT employee_id, last_name, email,

hire_date, job_id, salary

FROM empl3

WHERE department_id = 50

WITH CHECK OPTION)

VALUES (99998, 'Smith', 'JSMITH',

TO_DATE('07-JUN-99', 'DD-MON-RR'),

'ST_CLERK', 5000);

INSERT INTO

*

ERROR at line 1:

ORA-01402: view WITH CHECK OPTION where-clause violation

A palavra-chave DEFAULT pode ser usada explicitamente:

◦ Em comandos INSERT e UPDATE.

◦ Para permitir que o usuário controle onde e quando o valor default deve ser aplicado ao dado.

◦ Para atender ao padrão SQL:1999.

INSERT INTO deptm3

(department_id, department_name, manager_id)

VALUES (300, 'Engineering', DEFAULT);

UPDATE deptm3

SET manager_id = DEFAULT

WHERE department_id = 10;

INSERT ALL

INTO table_a VALUES(…,…,…)

INTO table_b VALUES(…,…,…)

INTO table_c VALUES(…,…,…)

SELECT …

FROM sourcetab

WHERE …;

Table_a

Table_b

Table_c

O comando INSERT...SELECT pode seu usado para inserir linhas em múltiplas tabelas em um único comando DML.

Inserts em Múltiplas Tabelas podem ser usados em Data Warehousing para transferir dados de uma ou mais tabelas para um conjunto de tabelas destino.

Tem aumento significativo de performance sobre:

◦ Múltiplos comandos INSERT...SELECT.

◦ Uma procedure para executar múltiplos inserts por meio de sintaxe IF...THEN.

Tipos de Inserts em Múltiplas Tabelas (Multitable):

◦ INSERT Incondicional

◦ ALL INSERT Condicional

◦ FISRT INSERT Condicional

◦ INSERT Pivotante

Sintaxe:

◦ conditional_insert_clause:

INSERT [ALL] [conditional_insert_clause]

[insert_into_clause values_clause] (subquery)

[ALL] [FIRST]

[WHEN condition THEN] [insert_into_clause values_clause]

[ELSE] [insert_into_clause values_clause]

Selecione o EMPLOYEE_ID, HIRE_DATE, SALARY e MANAGER_ID da tabela EMPLOYEES para os empregados cujos Ids sejam superiores a 200.

Insira esses valores nas tabelas SAL_HISTORY e MGR_HISTORY.

INSERT ALL

INTO sal_history VALUES(EMPID,HIREDATE,SAL)

INTO mgr_history VALUES(EMPID,MGR,SAL)

SELECT employee_id EMPID, hire_date HIREDATE,

salary SAL, manager_id MGR

FROM employees

WHERE employee_id > 200;

12 rows created.

Selecione o EMPLOYEE_ID, HIRE_DATE, SALARY e MANAGER_ID da tabela EMPLOYEES para os empregados cujos Ids sejam superiores a 200.

Se o salário for superior a $10,000, insira esses valores na tabela SAL_HISTORY.

Se o manager_id for superior a 200, insira esses valores na tabela MGR_HISTORY.

INSERT ALL

WHEN SAL > 10000 THEN

INTO sal_history VALUES(EMPID,HIREDATE,SAL)

WHEN MGR > 200 THEN

INTO mgr_history VALUES(EMPID,MGR,SAL)

SELECT employee_id EMPID,hire_date HIREDATE,

salary SAL, manager_id MGR

FROM employees

WHERE employee_id > 200;

4 rows created.

Selecione o DEPARTMENT_ID, SUM(SALARY) e MAX(HIRE_DATE) da tabela DEPARTMENTS.

Se a soma do salário for superior a $25,000, então insira o valor na tabela SPECIAL_SAL.

Se a primeira condição WHEN for verdadeira, então os WHEN subseqüentes nem são avaliados.

Para as linhas que não satisfizerem a primeira condição WHEN, insira as linhas nas tabelas HIREDATE_HISTORY_00 a HIREDATE_HISTORY_99, com base em sua HIRE_DATE.

Não satisfazendo a nenhuma condição, insira na tabela HIREDATE_HISTORY.

INSERT FIRST

WHEN SAL > 25000 THEN

INTO special_sal VALUES(DEPTID, SAL)

WHEN HIREDATE like ('%00%') THEN

INTO hiredate_history_00 VALUES(DEPTID,HIREDATE)

WHEN HIREDATE like ('%99%') THEN

INTO hiredate_history_99 VALUES(DEPTID, HIREDATE) ELSE

INTO hiredate_history VALUES(DEPTID, HIREDATE)

SELECT department_id DEPTID, SUM(salary) SAL,

MAX(hire_date) HIREDATE

FROM employees

GROUP BY department_id;

12 rows created.

Suponha que você receba um conjunto de registros de vendas de uma tabela não-relacional chamada SALES_SOURCE_DATA no seguinte formato: ◦ EMPLOYEE_ID, WEEK_ID, SALES_MON, SALES_TUE,

SALES_WED, SALES_THUR, SALES_FRI

Você quer armazenar esses registros na tabela SALES_INFO em formato relacional: ◦ EMPLOYEE_ID, WEEK, SALES

Para tanto, a utilização de um comando Insert Pivotante é bastante útil!

INSERT ALL

INTO sales_info VALUES (employee_id,week_id,sales_MON)

INTO sales_info VALUES (employee_id,week_id,sales_TUE)

INTO sales_info VALUES (employee_id,week_id,sales_WED)

INTO sales_info VALUES (employee_id,week_id,sales_THUR)

INTO sales_info VALUES (employee_id,week_id, sales_FRI)

SELECT EMPLOYEE_ID, week_id, sales_MON, sales_TUE,

sales_WED, sales_THUR,sales_FRI

FROM sales_source_data;

5 rows created.

É possível inserir ou atualizar registros em uma tabela condicionalmente por meio do comando MERGE.

Sintaxe:

MERGE INTO table_name table_alias

USING (table|view|sub_query) alias

ON (join condition)

WHEN MATCHED THEN

UPDATE SET

col1 = col_val1,

col2 = col2_val

WHEN NOT MATCHED THEN

INSERT (column_list)

VALUES (column_values);

Insira ou atualize linhas na tabela EMPL3 de acordo com a tabela EMPLOYEES.

MERGE INTO empl3 c

USING employees e

ON (c.employee_id = e.employee_id)

WHEN MATCHED THEN

UPDATE SET

c.first_name = e.first_name,

c.last_name = e.last_name,

...

c.department_id = e.department_id

WHEN NOT MATCHED THEN

INSERT VALUES(e.employee_id, e.first_name, e.last_name,

e.email, e.phone_number, e.hire_date, e.job_id,

e.salary, e.commission_pct, e.manager_id,

e.department_id);

MERGE INTO empl3 c

USING employees e

ON (c.employee_id = e.employee_id)

WHEN MATCHED THEN

UPDATE SET

...

WHEN NOT MATCHED THEN

INSERT VALUES...;

TRUNCATE TABLE empl3;

SELECT *

FROM empl3;

no rows selected

SELECT *

FROM empl3;

107 rows selected.

Versões de Linhas Recuperadas

SELECT …

SELECT salary FROM employees3

WHERE employee_id = 107;

UPDATE employees3 SET salary = salary * 1.30

WHERE employee_id = 107;

COMMIT;

SELECT salary FROM employees3

VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE

WHERE employee_id = 107;

1

2

3

SELECT versions_starttime "START_DATE",

versions_endtime "END_DATE",

salary

FROM employees

VERSIONS BETWEEN SCN MINVALUE

AND MAXVALUE

WHERE last_name = 'Lorentz';

A Cláusula VERSIONS BETWEEN:

Objetivos:

◦ Executar Inserts em Múltiplas Tabelas.

◦ Executar operações de MERGE.

◦ Rastrear versões de linhas de tebelas.

Crie a tabela SAL_HISTORY que possuirá o histórico salarial dos empregados:

DROP TABLE SAL_HISTORY;

CREATE table SAL_HISTORY

(EMPLOYEE_ID NUMBER(6),

HIRE_DATE DATE,

SALARY NUMBER(8,2));

Depois de criada, descreva sua estrutura e confirme.

Crie a tabela MGR_HISTORY que possuirá o histórico de gerentes e salários dos empregados:

DROP TABLE MGR_HISTORY;

CREATE table MGR_HISTORY

(EMPLOYEE_ID NUMBER(6),

MANAGER_ID NUMBER(6),

SALARY NUMBER(8,2));

Depois de criada, descreva sua estrutura e confirme.

Crie a tabela SPECIAL_SAL que possuirá o ID e salário dos empregados que possuem salários especiais:

DROP TABLE SPECIAL_SAL;

CREATE table SPECIAL_SAL

(EMPLOYEE_ID NUMBER(6),

SALARY NUMBER(8,2));

Depois de criada, descreva sua estrutura e confirme.

1. Escreva uma consulta que:

₋ Recupere o ID, Data de Contratação, Salário e ID do Gerente de todos os empregados cujos Ids sejam menor que 125.

₋ Se o salário for maior que $20.000, insira o ID do empregado e seu salário na tabela SPECIAL_SAL.

₋ Insira o ID do empregado, sua data de contratação e seu salário na tabela SAL_HISTORY.

₋ Insira o ID do empregado, o ID de seu gerente e seu salário na tabela MGR_HISTORY.

Liste os registros das 3 tabelas e analise os resultados.

1. Solução:

INSERT ALL

WHEN SAL > 20000 THEN

INTO special_sal VALUES (EMPID, SAL)

ELSE

INTO sal_history VALUES(EMPID, HIREDATE, SAL)

INTO mgr_history VALUES(EMPID, MGR, SAL)

SELECT employee_id EMPID, hire_date HIREDATE,

salary SAL, manager_id MGR

FROM employees

WHERE employee_id < 125;

Crie a tabela SALES_SOURCE_DATA com informações do ID do empregado e vendas dos dias da semana:

DROP TABLE SALES_SOURCE_DATA;

CREATE TABLE SALES_SOURCE_DATA

(employee_id NUMBER(6),

WEEK_ID NUMBER(2),

SALES_MON NUMBER(8,2),

SALES_TUE NUMBER(8,2),

SALES_WED NUMBER(8,2),

SALES_THUR NUMBER(8,2),

SALES_FRI NUMBER(8,2));

Depois de criada, descreva sua estrutura e confirme.

Insira na tabela SALES_SOURCE_DATA o seguinte registro:

INSERT INTO SALES_SOURCE_DATA

VALUES (178, 6, 1750, 2200, 1500, 1500, 3000);

commit;

Faça um select na tabela SALES_SOURCE_DATA e confirme que o registro foi inserido corretamente.

Crie a tabela SALES_INFO com a instrução a seguir:

DROP TABLE SALES_INFO;

CREATE TABLE SALES_INFO

(employee_id NUMBER(6),

WEEK NUMBER(2),

SALES NUMBER(8,2));

Descreva a estrutura da tabela e confirme.

2. Escreva uma consulta que:

₋ Recupere o ID do empregado, ID da semana e vendas para cada um dos dias da semana da tabela SALES_SOURCE_DATA.

₋ Crie uma transformação de tal modo que cada registro recuperado da SALES_SOURCE_DATA seja convertido em múltiplos registros na tabela SALES_INFO.

₋ Dica: Use Insert Pivotante!

Liste os registros das 2 tabelas e analise os resultados.

2. Solução:

INSERT ALL

INTO sales_info VALUES (employee_id, week_id, sales_MON)

INTO sales_info VALUES (employee_id, week_id, sales_TUE)

INTO sales_info VALUES (employee_id, week_id, sales_WED)

INTO sales_info VALUES (employee_id, week_id, sales_THUR)

INTO sales_info VALUES (employee_id, week_id, sales_FRI)

SELECT employee_id, week_id, sales_MON, sales_TUE, sales_WED, sales_THUR, sales_FRI

FROM sales_source_data;

Crie a tabela SALES_INFO com a instrução a seguir:

DROP TABLE SALES_INFO;

CREATE TABLE SALES_INFO

(employee_id NUMBER(6),

WEEK NUMBER(2),

SALES NUMBER(8,2));

Descreva a estrutura da tabela e confirme.

3. Você tem os dados antigos de empregados armazenados em um arquivo texto chamado emp.dat. Você deseja armazenar os nomes (primeiro e sobrenome) e e-mails dos empregados antigos e atuais em uma única tabela chamada EMP_DATA.

Para tanto, é preciso criar uma tabela externa usando o arquivo emp.dat como origem:

CREATE TABLE emp_data

(first_name VARCHAR2(20)

,last_name VARCHAR2(20)

, email VARCHAR2(45))

ORGANIZATION EXTERNAL

( TYPE oracle_loader

DEFAULT DIRECTORY emp_dir

ACCESS PARAMETERS

(RECORDS DELIMITED BY NEWLINE CHARACTERSET US7ASCII

NOBADFILE

NOLOGFILE

FIELDS

( first_name POSITION ( 1:20) CHAR

, last_name POSITION (22:41) CHAR

, email POSITION (43:72) CHAR ))

LOCATION ('emp.dat‘)) ;

Crie a tabela EMP_HIST com a instrução a seguir:

DROP TABLE emp_hist;

CREATE TABLE emp_hist AS

SELECT first_name, last_name, email

FROM employees;

Descreva a estrutura da tabela EMP_HIST e confirme.

3. Faça um MERGE dos dados da tabela EMP_DATA criada a partir do arquivo texto na tabela EMP_HIST criada a partir da tabela EMPLOYEES. Assuma que os dados na tabela EMP_DATA estejam atualizados. Assim, se um registro existir na EMP_HIST, apenas atualize o e-mail. Caso o registro ainda não exista em EMP_HIST, insira-o. Para saber se um registro existe ou não na tabela EMP_HIST, utilize o primeiro nome e sobrenome para comparar os registros.

Depois, liste os registros da tabela EMP_HIST e analise os resultados.

3. Solução:

MERGE INTO EMP_HIST f USING EMP_DATA h

ON (f.first_name = h.first_name

AND f.last_name = h.last_name)

WHEN MATCHED THEN

UPDATE SET f.email = h.email

WHEN NOT MATCHED THEN

INSERT ( f.first_name,

f.last_name,

f.email)

VALUES (h.first_name,

h.last_name,

h.email);

Crie a tabela EMP3 com a instrução a seguir:

DROP TABLE emp3;

CREATE TABLE emp3 AS

SELECT * FROM employees;

Descreva a estrutura da tabela EMP3 e confirme.

4. Na tabela EMP3, altere o departamento do empregado de sobrenome Kochhar para 60 e faça o commit. Então, altere novamente o departamento para 50 e faça o commit. Por fim, rastreie as alterações feitas ao empregado Kochhar utilizando a feature de ROW VERSIONS.

4. Solução:

update emp3 set department_id =60

where last_name ='Kochhar';

commit;

update emp3 set department_id =50

where last_name ='Kochhar';

commit;

select versions_starttime "START_DATE",

versions_endtime "END_DATE“, department_id

from emp3 versions between scn minvalue and maxvalue

where last_name ='Kochhar';