Usando Stored Procedures para Inserção e Atualização

 

Quando trabalhamos com a tecnologia dbExpress, muitos desenvolvedores acham cansativo usar três componentes (SQLDataSet  ou SQLQuery+DataSetProvider+ClientDataSet), para manipular os dados de uma tabela (ou mais). Podemos resolver isso, utilizando uma única Stored Procedure (SP), para atualizar e inserir dados.

Utilizo bastante essa técnica, pois da mais produtividade (uso somente o SQLStoredProc) e a performance da aplicação melhora, pois SP são mais otimizadas.

Nota: Utilizo essa técnica para tabelas pequenas, com no máximo 5 campos. Em tabelas com muitos campos, não ganhamos performance, por que ao alterar somente um registro, temos que passar todos os campos como parâmetro, tendo tráfego desnecessário na rede.

Exemplo

Tomando por base que temos uma tabela com a seguinte estrutura:

Clientes

ID           INTEGER NOT NULL PRIMARY KEY,

NOME         VARCHAR(50),

NASCIMENTO   DATE,

SEXO         CHAR(1),

 

Vamos criar a nossa SP com o seguinte código:

 

CREATE PROCEDURE UPD_INS_CLIENTES (

  ID   INTEGER,

  NOME VARCHAR(50),

  NASCIMENTO DATE,

  SEXO CHAR(1))

AS

BEGIN

  IF (EXISTS(SELECT ID FROM CLIENTES WHERE (ID = :ID))) THEN

    UPDATE CLIENTES

    SET NOME = :NOME,

        NASCIMENTO = :NASCIMENTO,

        SEXO = :SEXO

    WHERE (ID = :ID);

  ELSE

    INSERT INTO CLIENTES (

        ID,

        NOME,

        NASCIMENTO,

        SEXO)

    VALUES (

        :ID,

        :NOME,

        :NASCIMENTO,

        :SEXO);

END

 

A linha chave da SP é no If. Através do comando Exists, verificamos se o valor do parâmetro ID já existe na tabela, assim, se for verdadeiro, estamos obviamente trabalhando com uma atualização (Update). Senão, estamos adicionando os respectivos valores dos parâmetros na tabela.

Delphi

No Delphi, precisamos agora configurar a SP em um componentes SQLStoredProc. Faça a ligação com o banco de dados, através do SQLConnection, adicione um SQLStoredProc ao formulário e faça a ligação ao componente de conexão através da propriedade SQLConnection.

Escolha a SP na propriedade StoredProcName. A propriedade Params do componente, será preenchida com os parâmetros criados na SP (Figura 1).

 

Figura 1. Parâmetros da Stored Procedure

Uma técnica que poucos utilizam, é a de dar ao ClientDataSet, a possibilidade de executar comandos SQL, através da propriedade CommandText. Para isso, basta alterar para True a propriedade Options|poAllowCommandText do DataSetProvider.

Com isso, precisamos apenas de um SQLDataSet, um DataSetProvider e quantos ClientDataSets forem necessários, pois temos, os comandos SQL no ClientDataSet. Adicione os componentes no formulário, faça a ligação entre os mesmos e selecione os dados da tabela que estamos trabalhando, através do ClientDataSet.

Adicione um DBGrid e um DataSource ao formulário. Faça a ligação dos componentes para exibir os dados do ClientDataSet. No evento AfterPost do ClientDataSet, vamos passar os parâmetros para a nossa SP, conforme o seguinte código (adicione os campos, TFields, no ClientDataSet):

 

with SQLStoredProc1 do

begin

  Params[0].AsInteger := ClientDataSet1ID.AsInteger;

  Params[1].AsString := ClientDataSet1NOME.AsString;

  Params[2].AsDate := ClientDataSet1NASCIMENTO.AsDateTime;

  Params[3].AsString := ClientDataSet1SEXO.AsString;

  ExecProc;

end;

 

Mas como saberemos o valor do campo ID, quando for uma inserção? Para isso, criaremos um método que verifique o último valor do campo e retorne o novo valor para o ClientDataSet. Chamaremos a função no evento OnNewRecord do ClientDataSet. Implemente a função com o seguinte código:

 

procedure TForm1.IncPK(TableName: string; PrimaryKey: TField;

  Connection: TSQLConnection);

var

  Qry: TSQLQuery;

begin

  if PrimaryKey.DataSet.State <> dsInsert then

    Exit;

  Qry := TSQLQuery.Create(nil);

  try

    Qry.SQLConnection := Connection;

    Qry.SQL.Add('SELECT MAX('+PrimaryKey.FieldName+')FROM '+ TableName);

    Qry.Open;

    if Qry.Fields[0].IsNull then

      PrimaryKey.AsInteger := 1

    else

      PrimaryKey.AsInteger := Qry.Fields[0].AsInteger+1;

  finally

    FreeAndNil(Qry);

  end;

end;

 

Para testar, execute a aplicação e adicione alguns registros (Figura 2).

 

Figura 2. Testando a aplicação

Ao rolar o cursor no DBGrid, o método Post é executado, realizando assim a inserção, através do nosso código. O mesmo ocorre ao alterar um registro. Caso queira, adicione botões para chamar os métodos ou ainda utilize o DBNavigator.

Utilizei no projeto o driver dbExpress da UIB para o Firebird. Para mais informações veja o artigo publicado, ensinando como instalar e utilizar o driver, cliquando aqui.