[firebase-br] RES: RES: Auto Imcremento no FireBird e DB Express
Reuber
jubrovolski em yahoo.com.br
Qua Set 12 11:47:53 -03 2007
Olá Vinícius
Não me lembro o autor dessa rotina, mas sei que é uma mão na roda pra
mim. Nunca mais tive que me preocupar com autoincremento no firebird.
Fiz algumas adaptações, para me atender. Se achar válido, o Cantú
poderia colocar no site da firebase. Vamos lá:
Crie 2 tabelas, eis as estruturas.
***[ TABELA 1 ]*************************************************
CREATE TABLE USERS_SEQUENCIA (
SEQUENCIA_TABELA CHAR(100) NOT NULL,
SEQUENCIA_CAMPO CHAR(30) NOT NULL,
SEQUENCIA_VALOR INTEGER
);
ALTER TABLE USERS_SEQUENCIA ADD CONSTRAINT PK_USERS_SEQUENCIA PRIMARY
KEY (SEQUENCIA_TABELA, SEQUENCIA_CAMPO);
COMMENT ON TABLE USERS_SEQUENCIA IS
'Sequência de AutoNumeração de Campos';
***[ TABELA 2 ]*************************************************
CREATE TABLE USERS_SEQPEND (
SEQUENCIA_TABELA CHAR(100) NOT NULL,
SEQUENCIA_CAMPO CHAR(30) NOT NULL,
PENDENCIA_VALOR INTEGER NOT NULL
);
ALTER TABLE USERS_SEQPEND ADD CONSTRAINT PK_USERS_SEQPEND PRIMARY KEY
(SEQUENCIA_TABELA, SEQUENCIA_CAMPO, PENDENCIA_VALOR);
ALTER TABLE USERS_SEQPEND ADD CONSTRAINT FK_USERS_SEQPEND_2 FOREIGN KEY
(SEQUENCIA_TABELA, SEQUENCIA_CAMPO) REFERENCES USERS_SEQUENCIA
(SEQUENCIA_TABELA, SEQUENCIA_CAMPO) ON DELETE CASCADE;
COMMENT ON TABLE USERS_SEQPEND IS
'Sequência Perdida de AutoNumeração de Campos';
/******************************************************************************/
Agora Crie a procedure:
SET TERM ^ ;
CREATE PROCEDURE USERS_PSEQUENCIA (
TABELA VARCHAR(50),
CAMPO VARCHAR(20),
PENDENCIA INTEGER,
VALORATUAL CHAR(10))
RETURNS (
ID_RETORNO INTEGER)
AS
DECLARE VARIABLE MAXID INTEGER;
DECLARE VARIABLE ID_SEQUENCIA INTEGER;
BEGIN
ID_SEQUENCIA = 0;
MAXID = 0;
/* Inclui uma Nova Pendencia na Tabela de Pendencias */
if (PENDENCIA = 1) then
begin
if (not(exists(SELECT SEQUENCIA_VALOR
FROM USERS_SEQUENCIA
WHERE SEQUENCIA_TABELA = :TABELA
AND SEQUENCIA_CAMPO = :CAMPO))) then
begin
EXECUTE STATEMENT 'SELECT COALESCE(MAX('||CAMPO||'),1) from
'|| tabela into :maxid;
if (maxid <> 0) then
begin
INSERT INTO USERS_SEQUENCIA VALUES(:TABELA , :CAMPO ,
:maxid+2);
end
else
begin
INSERT INTO USERS_SEQUENCIA VALUES(:TABELA , :CAMPO , 2);
end
end
INSERT INTO USERS_SEQPEND
VALUES(:TABELA ,:CAMPO ,:VALORATUAL);
SUSPEND;
exit;
end
if (exists(SELECT PENDENCIA_VALOR
FROM USERS_SEQPEND
WHERE SEQUENCIA_TABELA = :TABELA
AND SEQUENCIA_CAMPO = :CAMPO)) then
begin
FOR SELECT PENDENCIA_VALOR
FROM USERS_SEQPEND
WHERE SEQUENCIA_TABELA = :TABELA
AND SEQUENCIA_CAMPO = :CAMPO
ORDER BY PENDENCIA_VALOR DESC
INTO :ID_SEQUENCIA DO
BEGIN
ID_RETORNO = :ID_SEQUENCIA;
END
end
else
ID_SEQUENCIA = 0;
if (ID_SEQUENCIA <> 0) then
begin
ID_RETORNO = :ID_SEQUENCIA;
DELETE FROM USERS_SEQPEND
WHERE SEQUENCIA_TABELA = :TABELA
AND SEQUENCIA_CAMPO = :CAMPO
AND PENDENCIA_VALOR = :ID_SEQUENCIA;
SUSPEND;
exit;
end
else
begin
if (not(exists(SELECT SEQUENCIA_VALOR
FROM USERS_SEQUENCIA
WHERE SEQUENCIA_TABELA = :TABELA
AND SEQUENCIA_CAMPO = :CAMPO))) then
begin
EXECUTE STATEMENT 'SELECT MAX('||CAMPO||') from '|| tabela
into :maxid;
if (maxid <> 0) then
begin
INSERT INTO USERS_SEQUENCIA VALUES(:TABELA , :CAMPO ,
:maxid+2);
ID_RETORNO = :maxid+1;
end
else
begin
INSERT INTO USERS_SEQUENCIA VALUES(:TABELA , :CAMPO , 2);
ID_RETORNO = 1;
end
end
else
begin
SELECT SEQUENCIA_VALOR
FROM USERS_SEQUENCIA
WHERE SEQUENCIA_TABELA = :TABELA
AND SEQUENCIA_CAMPO = :CAMPO
INTO :ID_SEQUENCIA;
UPDATE USERS_SEQUENCIA
SET SEQUENCIA_VALOR = SEQUENCIA_VALOR + 1
WHERE SEQUENCIA_TABELA = :TABELA
AND SEQUENCIA_CAMPO = :CAMPO;
ID_RETORNO = :ID_SEQUENCIA;
end
end
SUSPEND;
END^
SET TERM ; ^
*********************************************************
// usando um componente TSQLStoreProcedure no delphi
function idSimples(const tabela: String; const campo: String; const
pendencia: Integer; const valoratual: String): String;
begin
with stpidsimples do begin
Parambyname('TABELA').asstring := UPPERCASE(TABELA);
Parambyname('CAMPO').asstring := UPPERCASE(CAMPO);
Parambyname('PENDENCIA').asinteger := Pendencia;
Parambyname('VALORATUAL').asstring := ValorAtual;
ExecProc;
Result := Parambyname('ID_RETORNO').asstring;
end;
end;
// para pegar o autoincremento
clientdataset1.FieldByName(campo).value :=
idsimples(tabelanobd,camponobd, 0,'');
// quando deletar um regitro e quiser "guardar" a chave
vvalorcampo:=clientdataset1.fieldbyname(campochave).value;
clientdataset1.delete;
clientdataset1.ApplyUpdates(0);
idsimples(tabelanobd , camponobd, 1,vvalorcampo);
// após o cancelamento do registro se não for alteração.
if (clientdataset1.State in [dsinsert]) and
(clientdataset1.fieldbyname(campochave).AsString <> '') then
idsimples(tabelanobd , camponodb, 1,
clientdataset1.FieldByname(campo).asstring);
clientdataset1.cancel;
**********************
Espero que ajude
Reuber
.::Vinícius Mesquita:@smtp.bol.com.br:. escreveu:
> Amigos alguém teria o código do super seqüenciador?
>
> Grato!
Mais detalhes sobre a lista de discussão lista