View Full Version : PL/SQL Gerar Row ID


PMorgado
11-06-2007, 17:22
Boas,

Tenho um script que insere um novo registo numa tabela.
O campo do row_id é calculado com uma subquery.
Não posso automatizar este processo pois não me é possivel alterar o tipo de campo row_id que é varchar.

O problema é que muitas vezes este script é despoletado exactamente ao mesmo tempo mais do que uma vez.
O que provoca que o resultado da subquery para saber o row_id devolva o mesmo valor para dois ou mais inserts, o que viola a chave e um ou mais registos não são inseridos.

A query é esta:

BEGIN
INSERT INTO CX_EIM_LOG
(ROW_ID, CREATED_BY, LAST_UPD_BY, EIM_TABLE, H_INICIO,CONCEITO, N_CADEIA)
VALUES ((SELECT MAX(TO_NUMBER(ROW_ID)) FROM CX_EIM_LOG) + 1, (SELECT ROW_ID FROM S_USER WHERE LOGIN ='&3'), (SELECT ROW_ID FROM S_USER WHERE LOGIN ='&3'), '&1',SYSDATE,'&2',(SELECT MAX(N_CADEIA) FROM CX_EIM_LOG WHERE CONCEITO ='&2')+1);
END;
/
COMMIT;
QUIT

alguma sugestão de forma a que esta query não seja executada mais do que uma vez ao mesmo tempo?

tks
cpts
PM

selipequenote
11-06-2007, 19:03
Qual é o SGBD? Se puderes usa transacções...

Karski
12-06-2007, 00:21
Não uses esse select com o max, até porque quando tiveres milhares de registos nessa tabela ias estar a fazer um full À mesma cada vez que quisesses inserir lá um novo registo.

Não sei se o SGBD que estás a usar permite usares sequências, mas se sim crias uma sequência para isso e vais buscar o novo registo à respectiva sequência.

Se não tiveres essa possibilidade podes sempre criar uma solução mais "martelada" tipo criares uma tabela com 2 colunas. A 1ª coluna é o nome da tua tabela e a 2ª coluna é o próximo registo que vais ter quando inserires algo (do género de uma numeração). Assim quando quiseres um novo registo fazes um select campo for update (assim reservas o registo) e fazes o insert na tua tabela e logo de seguida incrementas a tabela das numerações libertando nesse momento o registo.

Espero ter ajudado. Com certeza que se pensares um bocado consegues arranjar outras soluções também

PMorgado
12-06-2007, 11:24
O SGBD é o ORACLE

Obrigado pela dica da sequencialização.

Aproveitando a ideia de usar transacção, posso colocar:

set transaction isolation level serializable;

E de seguida o INSERT?