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.