Já notou que tem algumas coisas que são diferentes de um banco de dados para outro…

Ex: Um UpperCase se escreve diferente dependendo do banco de dados que você irá utilizar;

Esquece…  o FireDAC resolve quase tudo para você…..

 

Escreve:

Select   {uCase(Nome)} from clientes     ///o FireDAC irá converter para UpperCase o nome do cliente;

Select   {LCase(Nome)} from clientes     ///o FireDAC irá converter para LowerCase o nome do cliente;

 

Ver no manual do FireDAC: Preprocessing Macros

Em outro “post” escrevi sobre obter o código do cliente gerado automático pelo banco e como retornar o seu valor usando “returning”.

Há situações que é necessário confirmar se uma operação foi aceita pelo banco (sem erro), e que de fator a linha foi inserida, alterada ou excluída do banco de dados.

Depois de submeter um comando de Insert, Update ou Delete para o banco pode-se adotar algumas estratégias para saber se houve sucesso:

  1. usar um Try/Exception para capturar uma exceção. Se o comando retornou uma exceção significa que o banco de dados criticou o comando. De outro lado há comandos que mesmo não retornando nenhum exceção NÃO garante que  conseguiu fazer… ex: envia um update e não encontra o registro – não gera exceção, mas também não fez;
  2. usar a propriedade  RowsAffected  para ler quantas linhas foram afetadas pelo último comando executado.

RowsAffected = 0    ->  não efetuou nenhuma alteração;

RowsAffected = -1   -> quando a operação não suporta ou o banco de dados não suporta obter retorno;

RowsAffected > 0     -> número de linhas que foram alteradas;

 

Exceção:   No MS-SQLServer há situações que o retorno é -1  em decorrência deste recurso ser desligado em triggers ou procedure quando omite o comando:  SET NOCOUNT ON

 

Exemplo:

Query1.sql.text := ‘update clientes set fone = ‘xxxx-xxxx’ where codigo=1′;

Query1.execSql;

if Query1.RowsAffected>0 then

showMessage(‘Sucesso’);

 

Algumas vezes pode ser útil acrescentar uma coluna calculada a uma tabela para evitar o uso de disco para informações que não são necessário armazenamento no disco.
Acrescentar um coluna calculada é bem simples como segue.

Criando uma tabela com coluna calcula:

CREATE TABLE FB_VENDAS_ITENS (
    CODIGO  VARCHAR(18),
    QTDE    DOUBLE PRECISION,
    PRECO   DOUBLE PRECISION,
    TOTAL   COMPUTED BY (qtde * preco)
);

Se a tabela já existe e deseja incluir um coluna calculada:

ALTER TABLE FB_VENDAS_ITENS
ADD TOTAL COMPUTED BY (qtde * preco)

Uma coluna calculada não deve fazer parte de INSERT ou UPDATE (rs), ela é calculada automático quando vai extrair o dado do banco de dados.

Quando faz SELECT de uma conjunto da colunas/linhas o Firebird permite que o resultado seja inserido em uma tabela existente.

  insert into temp_clientes (codigo,nome,cidade,estado)
     select  codigo,nome,cidade,estado 
     from clientes 
     where codigo between 1 and 1000

Ao fazer o insert o resulado do select é inserido a tabela acrescentando aos registros já existentes na tabela de destino, ou seja, não apaga os dados que já estavam lá.

Este processo pode ser executado inserindo em uma tabela física do banco ou um tabela temporária.

 

Tabela temporária no Firebird é mantido na memória no espaço de catálogo de tabelas sem fazer persistência no disco.

A existência dos dados na tabela temporária pode ser até o COMMIT dos dados “ON COMMIT DELETE ROWS” ou mantido até que a conexão seja fechada “ON COMMIT PRESERVE ROWS”.

Uma tabela temporária pode ser associada a um índice e seus dados é visível somente para a conexão que a criou,  não acessível para outras conexões.

Uma vez criada a tabela temporária a estrutura da tabela é mantida no metadata – quando os dados são apagados da tabela (como se fizesse um DROP TABLE) apaga somente dados e o metadata é mantido.

CREATE GLOBAL TEMPORARY TABLE  temp_Clientes
( codigo integer,
nome varchar(50),
cidade varchar(32),
estado varchar(5)
)
ON COMMIT PRESERVE ROWS;

aceita associar índices:

create index  temp_Clientes_Codigo on temp_Clientes(codigo)

 

Até a versão 2.5 do Firebird não existe a figura da coluna Auto-Incremento que existe em outros banco de dados.

No Firebird, você deve criar um GENERATOR que ira cuidar de gerar a sequência e associar uma Trigger para incluir o sequencial na tabela.

Exemplo para criar uma tabela de cliente com código Auto-Incremento:
[code]
// criar o recurso para armazenar o auto-incremento
CREATE GENERATOR CODIGO_CLIENTE; (formato mais antigo)
ou
CREATE SEQUENCE CODIGO_CLIENTE; (formato novo)

// criar a tabela
CREATE TABLE FB_CLIENTE (
CODIGO INTEGER NOT NULL,
NOME VARCHAR(50),
ENDERECO VARCHAR(128),
CIDADE VARCHAR(32),
ESTADO VARCHAR(5)
);

// para marcar o valor inicial (é opcional)
ALTER SEQUENCE CODIGO_CLIENTE RESTART WITH 0;

// Trigger para gerar o próximo código
SET TERM ^ ;
CREATE OR ALTER TRIGGER FB_CLIENTE_GERAR_CODIGO FOR FB_CLIENTE
ACTIVE BEFORE INSERT POSITION 0
AS
begin
  new.codigo =  gen_id(CODIGO_CLIENTE,1);
end
^
SET TERM ; ^
[/code]

Usando insert para retornar o valor o código inserido:
[code]
insert into fb_cliente
(nome,endereco,cidade,estado)
values( :nome,:endereço,:cidade,:estado)
returning codigo into :codigo_cliente
[/code]
 

Com FireDAC, utilizar o método FDQuery1.OPEN e irá retornar o parâmetro INTO como na lista de FIELDS (código cliente);

Sabe aquele cadastro de cliente que você vai inserir um novo cliente e lá o código do cliente é uma coluna gerada com GENERATOR – (auto-incremento), pode ser uma grande dor de cabeça se não estiver seguro sobre o código inserido na tabela.
Muitas vezes precisa deste ID para utiliza-lo em outro lugar. Se errar o ID o registro final irá ficar errado, associando ao cliente errado…
Outra situação é, se demorar algum tempo para descobrir o ID e outro usuário inserir um outro cliente enquanto o app fazia alguma coisa…. vai dar confusão. É preciso garantir com precisão o ID que foi inserido no momento que o banco postou na tabela.

Para resolver estas situações o Firebird permite obter valores de retorno de um INSERT.

Exemplo:

   insert into cliente( nome, endereco, ...) values( :nome,:endereco,...)
   returning id_cliente into :id

Ao executar o comando de INSERT, o banco irá retornar no parâmetro o valor inserido pelo GENERATOR no parâmetro ID.

Firebird utiliza “Autonomous Transaction”  para isolar o controle de transação podendo usar internamente em procedimentos, funções ou blocos de execução.

Recurso muito útil quando se deseja garantir rapidez na transação em pontos específicos da aplicação.

Um exemplo interessante é quanto precisa obter um contador grava em tabela e não pode deixar pendente de fazer commit no banco para não correr o risco do outro usuário pegar o mesmo número. Para estes casos tornar permanente o contador é fundamental.

Como usar:

in autonomous transaction do
begin
    ...... código a tornar persistente.
    update .... .....
end

Relevante: se o seu contador possui uma busca muito frequente com muita concorrência, avalie trocar o contador em tabela para um contador com GENERATOR;

 

Precisa calcular a idade de uma pessoa ou calcular o número de semanas entre duas datas, então olhas
estas procedures:

IDADE_SEMANAS( data_inicio, data_fim) -> retorna uma string: Anos Semanas Dias
IDADE_MESES( data_inicio, data_fim ) -> retorna uma string: Anos Meses Dias

Exemplo Idade do funcionário:

Se tem um funcionário que nasceu em: 01/01/1990 e quer saber a idade dele HOJE

select result from idade_meses( ’01/01/1990′, ‘today’)

Exemplo Tempo de Gravidez (semanas):

select result from idade_semanas( ’01/01/2016′, ’06/15/2016′)

Fonte: https://github.com/amarildolacerda/firebird/blob/master/firebird_procedures_idade.sql

Uma tabela com um único índice já monta uma estatística que indica qual a distribuição
espacial dos dados organizados pelo índice. Se a tabela possui vários índices o firebird utiliza
as estatísticas para escolher os melhores índices para responder a solicitação do usuário.
Sempre que é feito INSERT, UPDATE em uma coluna que pertence a um índice, o índice é
atualizado, mas sua estatítica não segue a mesma mecânica (ocorre uma espécie de
fragmentação do índice).
Se o firebird decide com base na estatítica do índice, não é difícil imaginar que com a
fragmentação o que deveria ser um benefício passa a ser um problema.
Então o firebird recomenda que depois de algum tempo – as estatísticas do banco de dados
sejam refeitas para refletir com melhor precisão a situação do índice.
Para facilitar este trabalho, segue uma procedure que força a atualização dos índice de todas
as suas tabelas.

SET TERM ^ ;
CREATE OR ALTER PROCEDURE REINDEX
as
declare variable sql varchar(255);
begin
   for
     select rdb$index_name from rdb$indices
     into :sql
   do
   begin
      sql = 'SET STATISTICS INDEX ' || sql;
      execute statement :sql;
   end
end^
SET TERM ; ^
GRANT EXECUTE ON PROCEDURE REINDEX TO SYSDBA;