Fala Pessoal,
Acabei de ler um post muito interessante sobre o suposto “apagão de talentos”, tenho visto cada vez mais esse suposto apagão se referir a area de banco de dados e eu discordo muito disso, esse post excelente do Fabio Luiz retrata perfeitamente a minha visão sobre o assunto, vale a pena dar uma lida.
http://blog.jumping.com.br/2012/05/o-mito-do-apagao-de-talentos/?goback=%2Egde_148535_member_117679150
Abraços !
quarta-feira, 23 de maio de 2012
segunda-feira, 21 de maio de 2012
Muitos Índices em uma Tabela
Fala pessoal vou falar de um assunto
que sempre gera alguma discussão nos ambientes em que esse assunto foi
levantado
Ultimamente tenho percebido certo
padrão dizendo que nenhuma tabela pode ter mais de seis índices ou sete índices
em alguns clientes. Então algumas instruções SQL podem executar bem, mas algumas podem
não executar tão bem assim e se precisarmos de mais índices não podemos
adicionar porque já existem 6 índices então algum teria que morrer para criar
mais.
Entendendo que muitas vezes alguns
índices podem ser redundantes, podemos pensar no índice IDX_OMT_NAME_ID_01 em
(COL1, COL2), IDX_OMT_NAME_ID_02 em (COL1, COL2,COL3), e IDX_OMT_NAME_ID_03 em (COL1,
COL2,COL3,COL4).
Nesses casos é comum que alguns DBAs pensem em dropar os primeiros dois índices porque eles são redundantes, ou seja, eles têm as mesmas colunas principais e na mesma ordem, como IDX_OMT_NAME_ID_03.
Mas dropar índices redundantes pode causar problemas com a seleção de uma tabela de condução de um join. (No post sobre métodos de join eu falo sobre tabelas de condução ou driving tables).
Quando temos muitos índices em uma
tabela, não vamos obter um impacto grande em questões de desempenho isso se
estamos falando de sistemas OLTP, porque apenas algumas linhas são processadas uma única transação, e o impacto de vários índices de em
uma atualização geralmente não é tão grande se comparado a ao desempenho de uma
consulta.
Agora um número alto de índices em
uma tabela pode ser extremamente prejudicial para ambientes com grande número
de processos batch de atualização, ou seja com um número alto de insets,
updates e deletes.
Veja um leve comparativo:
Quantidade Linhas
|
Quantidade de Índices
|
Tempo
|
1000
|
0
|
00:00:00.41
|
10000
|
0
|
00:00:02.99
|
10000
|
1
|
00:00:05.88
|
10000
|
3
|
00:00:07.82
|
20000
|
5
|
00:00:59.69
|
Da para imaginar o problema quando
temos uns 8 índices de uma tabela com alguns GB de tamanho, e inserindo mais
alguns GB em um processo batch.
Um workaround para esse problema é
dropar on índices antes da execução da batch e recriar os mesmos após a
execução . Com opções como NOLOGGING e PARALLEL é possível reconstruir
um índice com mais velocidade, porém mesmo com esses recursos o trabalho de
reconstruir um índice pode demorar as vezes mais que o próprio processo batch
se for o caso.
Minha experiência me diz que o melhor
é não criar regras em relação a um número especifico de índices que uma tabela
possa ter, porque literalmente cada caso é um caso.O melhor é sempre analisar a
relação de custo e beneficio de um novo índice e o Oracle nos ajuda bastante
porque podemos usar recursos como o ALTER INDEX MONITORING USAGE para monitorar
e verificar a eficiência e uso dos índices.
sexta-feira, 11 de maio de 2012
Como converter Oracle DB para MongoDB
Fala Pessoal,
Tenho pesquisado e estudado bastante as soluções NoSQL depois que grandes empresas passaram a integrar essa tecnologia como solução de escalabilidade para seus problemas. Discordo totalmente da visão de alguns profissionais os quais acreditam na total substituição dos bancos relacionais pelos NoSQL, isso para mim é sonho de programador que nunca soube escreve uma linha em SQL.
Mas acredito que é uma grande solução que pode ser integrada em quase todos os negócios junto com um banco relacional e outras soluções de cache e motor de busca, gerando assim escalabilidade, exemplos de arquitetura que integram as duas tecnologias como facebook e twitter mostram isso claramente.
Usando como base a idéia do Jean Nascimento que criou um conversor de MySQL para MongoDB.
que esta disponivel no link :
http://imasters.com.br/artigo/17078/mongodb/como-converter-mysql-para-mongodb
Tive a idéia de criar um conversor de Oracle para MongoDb utilizando o PHP.
O MongoDB é uma aplicação de código aberto, de alta performance, sem esquemas, orientado a documentos. Foi escrito na linguagem de programaçãoC++. Além de orientado a documentos, é formado por um conjunto de documentosJSON. Muitas aplicações podem, dessa forma, modelar informações de modo muito mais natural, pois os dados podem ser aninhados em complexas hierarquias e continuar a ser indexáveis e fáceis de buscar. (Font Wikipedia)
Eu já vinha testando o MongoDB ha algum tempo e realmente é rápido e simples, não vejo sentido em benchmarks com um bancos relacionais pois acredito que em focos diferenciados. Acredito que o MongoDB é excelente para tudo o que não precisa ser relacional.
No link do Jean Nascimento acima tem a explicação para quem deseja instalar o MongoDB.
Segue o Link do conversor:
http://code.google.com/p/sql-hudson/downloads/list
Tenho pesquisado e estudado bastante as soluções NoSQL depois que grandes empresas passaram a integrar essa tecnologia como solução de escalabilidade para seus problemas. Discordo totalmente da visão de alguns profissionais os quais acreditam na total substituição dos bancos relacionais pelos NoSQL, isso para mim é sonho de programador que nunca soube escreve uma linha em SQL.
Mas acredito que é uma grande solução que pode ser integrada em quase todos os negócios junto com um banco relacional e outras soluções de cache e motor de busca, gerando assim escalabilidade, exemplos de arquitetura que integram as duas tecnologias como facebook e twitter mostram isso claramente.
Usando como base a idéia do Jean Nascimento que criou um conversor de MySQL para MongoDB.
que esta disponivel no link :
http://imasters.com.br/artigo/17078/mongodb/como-converter-mysql-para-mongodb
Tive a idéia de criar um conversor de Oracle para MongoDb utilizando o PHP.
O MongoDB é uma aplicação de código aberto, de alta performance, sem esquemas, orientado a documentos. Foi escrito na linguagem de programaçãoC++. Além de orientado a documentos, é formado por um conjunto de documentosJSON. Muitas aplicações podem, dessa forma, modelar informações de modo muito mais natural, pois os dados podem ser aninhados em complexas hierarquias e continuar a ser indexáveis e fáceis de buscar. (Font Wikipedia)
Eu já vinha testando o MongoDB ha algum tempo e realmente é rápido e simples, não vejo sentido em benchmarks com um bancos relacionais pois acredito que em focos diferenciados. Acredito que o MongoDB é excelente para tudo o que não precisa ser relacional.
No link do Jean Nascimento acima tem a explicação para quem deseja instalar o MongoDB.
Segue o Link do conversor:
http://code.google.com/p/sql-hudson/downloads/list
Marcadores:
convert_oracle_mongodb,
converter,
converter_oracle_mongodb,
migrate oracle to mongodb,
mongodb,
mysql,
nosql,
oracle,
oracle for mongodb,
php,
sql
quarta-feira, 29 de fevereiro de 2012
Monitorar SQLs que geram Locks no Oracle
Essa semana eu precisei monitorar alguns locks que estavam ocorrendo em uma base de produção.
Só que os locks eram esporádicos, não dava para ficar na frente de uma tela de OEM esperando acontecer, além disso eu precisava descobrir o SQL que estava bloqueando algum recurso e o SQL que estava esperando pelo recurso.
Eu criei um job que roda de 2 em 2 minutos , ele verifica se existe alguma sessão com evento de espera tipo o : enq: TX - row lock contention.
Caso exista e o tempo de espera seja maior que X ele loga os SQLSs que estao bloqueando e esperando por um recurso,o SID das sessões,a data e o tempo de espera da sessão em uma tabela que criei para isso.
O Mais legal nisso foi que descobri a coluna Prev_sql_id da V$SESSION, com ela conseguimos saber o SQL que esta bloqueando algum recurso.
Abaixo segue o comando de criação do JOB e da Tabela para logar.
UPDATE:
Legal olhar um post de quase 4 anos atrás, vendo agora não gosto muito desse código, então decide realizar algumas pequenas modificações , graças ao comentário do Mauro rafael, modifiquei na hora mesmo, só por capricho,rs.
Tabela:
CREATE TABLE LOG_LOCK (SQL_BLOCKER VARCHAR2(1000),
SID_BLOCKER INT, SQL_BLOCKED VARCHAR2(1000),
SID_BLOCKED INT,DATA_LOG DATE,WAIT INT);
Job:
BEGIN
DBMS_SCHEDULER.create_job (
job_name => 'Monitor_Lock',
job_type => 'PLSQL_BLOCK',
job_action => '
DECLARE
V_BLOCKER INT;
V_BLOCKED INT;
V_SQL VARCHAR2(1000);
V_SQL2 VARCHAR2(1000);
V_TIME INT;
V_CTR INT;
BEGIN
SELECT COUNT(*) INTO V_CTR
FROM v$session s
WHERE event LIKE ''enq: %'';
FOR CRS IN (select s1.sid BLOCKER, s2.sid BLOCKED
from v$lock l1, v$session s1, v$lock l2, v$session s2
where s1.sid=l1.sid and s2.sid=l2.sid
and l1.BLOCK=1 and l2.request > 0
and l1.id1 = l2.id1
and l2.id2 = l2.id2)
LOOP
IF V_CTR >= 1 THEN
V_BLOCKED:=CRS.BLOCKED;
V_BLOCKER:=CRS.BLOCKER;
SELECT SQL_TEXT INTO V_SQL FROM V$SQL S
INNER JOIN V$SESSION V ON (V.Prev_sql_id=S.SQL_ID)
WHERE V.SID=V_BLOCKER;
SELECT SQL_TEXT ,V.SECONDS_IN_WAIT INTO V_SQL2,V_TIME FROM V$SQL S
INNER JOIN V$SESSION V ON (V.sql_id=S.SQL_ID)
WHERE V.SID=V_BLOCKED;
IF V_TIME > 30 THEN
INSERT INTO LOG_LOCK (SID_BLOCKER,SQL_BLOCKER,SID_BLOCKED,SQL_BLOCKED,DATA_LOG,WAIT) VALUES
(V_BLOCKER,V_SQL,V_BLOCKED,V_SQL2,SYSDATE,V_TIME);
COMMIT;
END IF;
END IF;
END LOOP;
END;
',
start_date => trunc(sysdate)+18/24,
repeat_interval => 'FREQ=MINUTELY;INTERVAL=2',
end_date => NULL,
enabled => TRUE,
comments => 'Job defined entirely by the CREATE JOB procedure.');
END;
/
Só que os locks eram esporádicos, não dava para ficar na frente de uma tela de OEM esperando acontecer, além disso eu precisava descobrir o SQL que estava bloqueando algum recurso e o SQL que estava esperando pelo recurso.
Eu criei um job que roda de 2 em 2 minutos , ele verifica se existe alguma sessão com evento de espera tipo o : enq: TX - row lock contention.
Caso exista e o tempo de espera seja maior que X ele loga os SQLSs que estao bloqueando e esperando por um recurso,o SID das sessões,a data e o tempo de espera da sessão em uma tabela que criei para isso.
O Mais legal nisso foi que descobri a coluna Prev_sql_id da V$SESSION, com ela conseguimos saber o SQL que esta bloqueando algum recurso.
Abaixo segue o comando de criação do JOB e da Tabela para logar.
UPDATE:
Legal olhar um post de quase 4 anos atrás, vendo agora não gosto muito desse código, então decide realizar algumas pequenas modificações , graças ao comentário do Mauro rafael, modifiquei na hora mesmo, só por capricho,rs.
Tabela:
CREATE TABLE LOG_LOCK (SQL_BLOCKER VARCHAR2(1000),
SID_BLOCKER INT, SQL_BLOCKED VARCHAR2(1000),
SID_BLOCKED INT,DATA_LOG DATE,WAIT INT);
Job:
BEGIN
DBMS_SCHEDULER.create_job (
job_name => 'Monitor_Lock',
job_type => 'PLSQL_BLOCK',
job_action => '
DECLARE
V_BLOCKER INT;
V_BLOCKED INT;
V_SQL VARCHAR2(1000);
V_SQL2 VARCHAR2(1000);
V_TIME INT;
V_CTR INT;
BEGIN
SELECT COUNT(*) INTO V_CTR
FROM v$session s
WHERE event LIKE ''enq: %'';
FOR CRS IN (select s1.sid BLOCKER, s2.sid BLOCKED
from v$lock l1, v$session s1, v$lock l2, v$session s2
where s1.sid=l1.sid and s2.sid=l2.sid
and l1.BLOCK=1 and l2.request > 0
and l1.id1 = l2.id1
and l2.id2 = l2.id2)
LOOP
IF V_CTR >= 1 THEN
V_BLOCKED:=CRS.BLOCKED;
V_BLOCKER:=CRS.BLOCKER;
SELECT SQL_TEXT INTO V_SQL FROM V$SQL S
INNER JOIN V$SESSION V ON (V.Prev_sql_id=S.SQL_ID)
WHERE V.SID=V_BLOCKER;
SELECT SQL_TEXT ,V.SECONDS_IN_WAIT INTO V_SQL2,V_TIME FROM V$SQL S
INNER JOIN V$SESSION V ON (V.sql_id=S.SQL_ID)
WHERE V.SID=V_BLOCKED;
IF V_TIME > 30 THEN
INSERT INTO LOG_LOCK (SID_BLOCKER,SQL_BLOCKER,SID_BLOCKED,SQL_BLOCKED,DATA_LOG,WAIT) VALUES
(V_BLOCKER,V_SQL,V_BLOCKED,V_SQL2,SYSDATE,V_TIME);
COMMIT;
END IF;
END IF;
END LOOP;
END;
',
start_date => trunc(sysdate)+18/24,
repeat_interval => 'FREQ=MINUTELY;INTERVAL=2',
end_date => NULL,
enabled => TRUE,
comments => 'Job defined entirely by the CREATE JOB procedure.');
END;
/
Marcadores:
COMMIT,
CONCORRÊNCIA,
CONCORRÊNCIA DE DADOS,
DADOS,
DEADLOCK,
job,
job oracle,
LOCK,
lock oracle,
LOCKS,
Monitorar Locks,
monitoring locks,
prev_sql_id,
ROLLBACK,
TRANSAÇÃO,
v$session
quarta-feira, 23 de novembro de 2011
Tuning na Instruçao SQL LIKE no Oracle
Fala pessoal, vou postar aqui um dica simples, que é quando se precisa de um tunning rápido nas declarações "LIKE" que o CBO naturalmente ignora os índices existentes nas colunas utilizadas pelo LIKE para uso de um FTS. Quando ocorre isso temos o recurso de utilizar um hint forçando a utilização do índice.
No Blog do Laurent Schneider tem um demo bem legal.
Abaixo a demonstração.
CREATE TABLE lsc_t AS
SELECT
ROWNUM ID,
SUBSTR(DBMS_RANDOM.STRING ('n', DBMS_RANDOM.VALUE (2, 8))
|| ' '
|| DBMS_RANDOM.STRING ('n', DBMS_RANDOM.VALUE (2, 8))
,1,17) NAME,
TRUNC(SYSDATE-ABS(10000*DBMS_RANDOM.NORMAL)) birthdate,
LPAD('X',4000,'X') address
FROM DUAL
CONNECT BY LEVEL <= 1e5;
ALTER TABLE lsc_t ADD PRIMARY KEY(ID);
CREATE INDEX lsc_i ON lsc_t(NAME);
EXEC dbms_stats.gather_table_stats(user,'LSC_T',cascade=>true);
SQL> SELECT ID, NAME, birthdate
FROM lsc_t WHERE NAME LIKE '%ABC%'; 2
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5044 | 123K| 22123 (1)| 00:04:26 |
|* 1 | TABLE ACCESS FULL| LSC_T | 5044 | 123K| 22123 (1)| 00:04:26 |
---------------------------------------------------------------------------
Statistics
----------------------------------------------------------
379 recursive calls
0 db block gets
100090 consistent gets
100016 physical reads
0 redo size
2066 bytes sent via SQL*Net to client
491 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
5 sorts (memory)
0 sorts (disk)
35 rows processed
SWLQL> SELECT /*+INDEX(LSC_T,LSC_I)*/ ID, NAME, birthdate
FROM lsc_t WHERE NAME LIKE '%ABC%'; 2
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5044 | 123K| 3574 (1)| 00:00:43 |
| 1 | TABLE ACCESS BY INDEX ROWID| LSC_T | 5044 | 123K| 3574 (1)| 00:00:43 |
|* 2 | INDEX FULL SCAN | LSC_I | 5000 | | 220 (2)| 00:00:03 |
-------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
360 consistent gets
322 physical reads
0 redo size
142849 bytes sent via SQL*Net to client
491 bytes received via SQL*Net from client
4 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
35 rows processed
Marcadores:
cbo.,
like,
oracle tuning,
sql tuning,
tuning,
tuning like oracle
segunda-feira, 21 de novembro de 2011
Habilitar DDL no alert.log Oracle
Fala pessoal, o 11g tem um recurso interessante que é habilitar o log de comandos DDLs no alert.log, para habilitar é bem simples basta alterar o parâmetro ENABLE_DDL_LOGGING para true, segue abaixo um pequeno step by step que altera o parâmetro e cria alguns objetos para teste.
[oracle@rjhud trace]$ tail -f alert_centro.log
Mon Nov 21 15:58:43 2011
SMCO started with pid=31, OS id=5981
Mon Nov 21 16:08:37 2011
ALTER SYSTEM SET enable_ddl_logging=TRUE SCOPE=SPFILE;
ALTER SYSTEM SET enable_ddl_logging=TRUE SCOPE=BOTH;
Mon Nov 21 16:09:41 2011
create table t_hudson as select * from user_tables
Mon Nov 21 16:10:09 2011
alter table t_hudson read only
drop table t_hudson
Para maiores informações sobre o parâmetro é só consultar o link:
http://download.oracle.com/docs/cd/E14072_01/server.112/e10820/initparams078.htm
COLUMN DESCRIPTION FORMAT A30 COLUMN VALUE FORMAT A30 SET LINESIZE 120 SQL> select value,isdefault,isses_modifiable, issys_modifiable,isbasic,description from v$parameter where name='enable_ddl_logging'; VALUE ISDEFAULT ISSES ISSYS_MOD ISBAS DESCRIPTION ------ --------- ----- --------- ----- ------------------- FALSE TRUE TRUE IMMEDIATE FALSE enable ddl logging SQL> alter system set ENABLE_DDL_LOGGING=true ; System altered. SQL> conn hudson/c402d92 Connected SQL> create table t_hudson as select * from user_tables; Table created. SQL> grant select on t_hudson to public; Grant succeeded. SQL> alter table t_hudson read only; Table altered. SQL> drop table t_hudson ; Table dropped.Após a alteração do parâmetro vamos verificar se foi gerado o log no alert.log:
[oracle@rjhud trace]$ tail -f alert_centro.log
Mon Nov 21 15:58:43 2011
SMCO started with pid=31, OS id=5981
Mon Nov 21 16:08:37 2011
ALTER SYSTEM SET enable_ddl_logging=TRUE SCOPE=SPFILE;
ALTER SYSTEM SET enable_ddl_logging=TRUE SCOPE=BOTH;
Mon Nov 21 16:09:41 2011
create table t_hudson as select * from user_tables
Mon Nov 21 16:10:09 2011
alter table t_hudson read only
drop table t_hudson
Para maiores informações sobre o parâmetro é só consultar o link:
http://download.oracle.com/docs/cd/E14072_01/server.112/e10820/initparams078.htm
sexta-feira, 18 de novembro de 2011
Exportar linhas sem dump ou backup no Oracle
Muitas vezes é necessário obter um número pequenos de linhas de algumas ou todas tabelas de um ambiente de produção, mas nem sempre um dump ou um backup esta disponível ou ainda o tempo de demora pode atrasar muito uma atuação, quem trabalha em consultorias, fabricas e qualquer lugar onde ambiente de produção é um lugar onde você não pode entrar em 1000 seguranças do seu lado sabe do que eu estou falando.
Então um meio muito utilizado é gerar "Inserts" concatenando via selects os famosos :
Pensando nisso eu fiz uma package que gera esses selects dinamicamente , recebendo como argumentos o nome de uma tabela com o número de linhas que deseja, ou passando diretamente um onwer e as linhas que precisa.
Óbvio que esse método só é útil quando precisa de um número pequeno de linhas e não tem em mãos outras ferramentas.
Abaixo o código de criação das packages :
Então um meio muito utilizado é gerar "Inserts" concatenando via selects os famosos :
SELECT 'INSER INTO ..... ' || COLUMNS .....Dessa forma é possível obter os dados da tabela de uma forma simples e rápida, o problema é o tempo gasto na hora de gerar esses selects, principalmente se estamos falando de uma tabela com muitas colunas, ou se você precisa de muitas tabelas.
Pensando nisso eu fiz uma package que gera esses selects dinamicamente , recebendo como argumentos o nome de uma tabela com o número de linhas que deseja, ou passando diretamente um onwer e as linhas que precisa.
Óbvio que esse método só é útil quando precisa de um número pequeno de linhas e não tem em mãos outras ferramentas.
Abaixo o código de criação das packages :
CREATE OR REPLACE PACKAGE PKG_DUMP AS
PROCEDURE P_DUMP(V_OWNER VARCHAR2,V_ROWS INT);
FUNCTION V_DUMP(v_table_name VARCHAR2,V_ROWS INT) RETURN VARCHAR2;
END;
/
CREATE OR REPLACE PACKAGE BODY PKG_DUMP AS
PROCEDURE P_DUMP(V_OWNER VARCHAR2,V_ROWS INT)
IS
V_SMT VARCHAR2(3000);
V_TABLE_NAME VARCHAR2(100);
CURSOR trip_cursor IS SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER=V_OWNER AND TABLE_NAME IN
('ACTION','ROLE','ROLE_ACTION','URL','MENU');
BEGIN
FOR trip_record IN trip_cursor LOOP
SELECT V_DUMP(trip_record.TABLE_NAME,V_ROWS) INTO V_SMT FROM DUAL;
V_TABLE_NAME := trip_record.TABLE_NAME;
dbms_output.new_line();
dbms_output.new_line();
DBMS_OUTPUT.PUT_LINE('/************* ' || V_TABLE_NAME || '***************/');
dbms_output.new_line();
DBMS_OUTPUT.PUT_LINE(V_SMT);
END LOOP;
--EXECUTE IMMEDIATE V_SMT ;
EXCEPTION
WHEN OTHERS THEN
PKG_ERR.PRC_HANDLE(-20001, 'Problems in P_DUMP ' || V_TABLE_NAME );
END P_DUMP;
FUNCTION V_DUMP(v_table_name VARCHAR2,V_ROWS INT)
RETURN VARCHAR2
IS
v_column_name VARCHAR2(5000);
v_column_name2 VARCHAR2(5000);
v_column_name3 VARCHAR2(5000);
v_column_name4 VARCHAR2(5000);
v_column_name5 VARCHAR2(5000);
V_SMT VARCHAR2(5000);
CURSOR trip_cursor IS SELECT COLUMN_NAME FROM USER_TAB_COLUMNS WHERE TABLE_NAME=v_table_name ORDER BY COLUMN_ID;
BEGIN
FOR trip_record IN trip_cursor LOOP
v_column_name2 := trip_record.column_name ;
v_column_name := v_column_name || ',' || v_column_name2;
END LOOP;
SELECT REGEXP_REPLACE(v_column_name, ',' , '' ,1,1) into v_column_name3 FROM DUAL;
--SELECT REGEXP_REPLACE(v_column_name, ',' , '|| '',''||' ,2) into v_column_name4 FROM DUAL;
SELECT REGEXP_REPLACE(v_column_name, ',' , '|| '''''''' || '',''||'''''''' ||' ,2) into v_column_name4 FROM DUAL;
SELECT REGEXP_REPLACE(v_column_name4, ',' , ',''''||''''''''||' ,1,1) into v_column_name5 FROM DUAL;
--DBMS_OUTPUT.PUT_LINE(v_column_name);
V_SMT:= ' SELECT ''INSERT INTO ' || v_table_name || ' ( ' || v_column_name3 || ' ) VALUES (''' || v_column_name5
|| '||'''''''' ||'');'' FROM ' || v_table_name || ' WHERE ROWNUM < ' || V_ROWS || ';';
--EXECUTE IMMEDIATE V_SMT ;
--DBMS_OUTPUT.PUT_LINE(V_SMT);
RETURN V_SMT;
EXCEPTION
WHEN OTHERS THEN
PKG_ERR.PRC_HANDLE(-20001, 'Problems in V_DUMP ' || v_table_name );
END V_DUMP;
END PKG_DUMP;
/
Agora as formas de Utilizar a package, a primeira forma é gerar o insert de apenas uma tabela.
Primeiro executando a function PKG_DUMP.V_DUMP passando o nome da tabela e depois o número de linhas.
new@ORACLE> SELECT PKG_DUMP.V_DUMP('TESTE',29) FROM DUAL;
SELECT 'INSERT INTO TESTE ( X,C,H,G,HG ) VALUES (',''||''''||X|| '''' || ','||'''' ||C|| '''' || ','||'''' ||H|| '''' || ','||'''' ||G|| '''' || ','||'''' ||HG||'''' ||');' FROM TESTE WHERE ROWNUM <
29;
Após o resultado executa o select gerado e já se tem o insert pronto.
new@ORACLE> SELECT 'INSERT INTO TESTE ( X,C,H,G,HG ) VALUES (',''||''''||X|| '''' || ','||'''' ||C|| '''' || ','||'''' ||H|| '''' || ','||'''' ||G|| '''' || ','||'''' ||HG||'''' ||');' FROM TESTE WHERE ROWNUM <
29; 2
INSERT INTO TESTE ( X,C,H,G,HG ) VALUES (
'1','2','1','1','A');
INSERT INTO TESTE ( X,C,H,G,HG ) VALUES (
'4','5','1','1','A');
INSERT INTO TESTE ( X,C,H,G,HG ) VALUES (
'4','5','1','1','A');
A outra forma é tendo todas as tabelas, executando a procedure PKG_DUMP.P_DUMP passando o owner
e o número de linhas:
new@ORACLE> set pagesize 0
set long 90000
set linesize 200
set trimspool ON
set feedback off
set echo off
new@ORACLE>EXECUTE PKG_DUMP.P_DUMP('NEW',100);
Ele vai gerar o output de todos os selects para geraçao de inserts de todas as tabelas que esse
owner possui, é aconselhável utilizar um spool para receber esse conteúdo.
That's all folks
Assinar:
Postagens (Atom)