Criação e uso de Busca Fonetizada em Base de Dados Relacionais, em Português – Parte 03

Finalizando o artigo sobre criação e uso de busca fonetizada em base de bados relacionais.

Criação e uso de Busca Fonetizada em Base de Dados  Relacionais, em Português – Parte 03

Neste ponto podemos criar um aplicativo que realize a busca de modo a trazer, por exemplo, a palavra Edson e seu similar “fonético” em qualquer parte do nome, Edson Nascimento Fernades, Paulo Edison Do Nascimento, Jose Paulo edhison, etc...

Para ilustrar vou usar um exemplo de aplicativo, desenvolvido pelo meu amigo Cristiano Wilson Cruge, que pode ser facilmente adaptado para outras linguagens e usos.

O aplicativo é o seguinte, feito em Delphi7:


O código fonte se encontra nos anexos, no final do artigo, para exemplificar vamos procurar “Rafael”, na base, obtemos o seguinte retorno:


Dessa forma podemos implementar uma busca fonética mais eficiente para bases de dados maiores, implementando o uso de índices. Podemos inclusive potencializar a utilização desse tipo de busca com melhorias nos índices e uso de recursos textuais e de expressões regulares em bancos de dados.  

 

III - Anexos

 

-- Script 1

 

CREATE TABLE CLIENTE(

  CODIGO CHAR (08)  NOT NULL,

  NOME  VARCHAR2 (80)  NOT NULL,

  CONSTRAINT PK_CODIGO_CLIENTE

  PRIMARY KEY ( CODIGO )

   );

 

--Script 2

 

 --Carga da Tabela

 

 

INSERT INTO CLIENTE (CODIGO,NOME) VALUES('31701023','ACUCENA RAFHAEL');

INSERT INTO CLIENTE (CODIGO,NOME) VALUES('31701024','ADALTO PEREIRIA BARBOSA');

INSERT INTO CLIENTE (CODIGO,NOME) VALUES('31701025','ADRIANA LUIS DOS SANTOS');

INSERT INTO CLIENTE (CODIGO,NOME) VALUES('31701026','BENEDITO RUI BARBOSA');

INSERT INTO CLIENTE (CODIGO,NOME) VALUES('31701027','BARTOLOMEU DIAS');

INSERT INTO CLIENTE (CODIGO,NOME) VALUES('31701028','CAMILA PITANGA NASCIMENTO DIAS');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701029','CAMILA PARKSON');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701030','CARLOS MAGNO RAFAEL');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701031','CARLOS LUIZ  AUGUSTO');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701032','CHRISTIANA DE OLIVEIRA BARBOZA');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701033','CRISTINA MARTINS FONSECA');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701034','DANIEL BOOM');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701035','DANIELA BOOM NASCIMENTO');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701036','DANIELLA BAUER');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701037','DAVI CARDOSO');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701038','DAVID JACK NACIMENTO');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701039','EDNA LUIZ GRANDE');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701040','EDINA CONCEIÇÃO DE ALMEIDA');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701041','EDSON ARANTES DO NASCIMENTO');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701042','EDISON NASCIMENTO BARBOSA');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701043','FÁBIO MITSUAKI ISHIKAWA');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701044','FABIO NOGUEIRA');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701045','FLÁVIO VESPASIANO NOBRE');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701046','FLAVIO DE OLIVEIRA FIGUEIREDO');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701047','FRAVIO EDSON CELULAI');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701048','HELIO SOLAR CENTRO');

INSERT INTO CLIENTE (CODIGO,NOME)VALUES('31701049','ELIO FILHO DE APOLO');

COMMIT;

 

--Script 3

 

SELECT NOME,CODIGO FROM CLIENTE WHERE FONETIZAR(NOME)=FONETIZAR('CARLOS LUIZ AUGUSTO');

 

--Script 4

 

CREATE TABLE CLIENTE_FONETICA (

  DES_FONETICA VARCHAR2 (40)  NOT NULL,

  CODIGO  CHAR(08)  NOT NULL

   );

 

-- Script 5

 

CREATE OR REPLACE PROCEDURE FONETIZAR_CLIENTE

IS

  CURSOR CLIENTE_cur IS

SELECT CODIGO, FONETIZAR(NOME) AS NOME_CLIENTE FROM CLIENTE;

  NOME_CLIENTE CLIENTE.NOME%TYPE;

  i INTEGER;

  j INTEGER;

  saida CLIENTE.NOME%TYPE;

BEGIN

  -- Apaga o indíce fonético

  DELETE FROM CLIENTE_FONETICA;

 

  FOR CLIENTE_REC IN CLIENTE_CUR LOOP

    -- Separa as palavras fonetizadas e salva na tabela MATERIAL_FONETICA

  NOME_CLIENTE := CLIENTE_REC.NOME_CLIENTE||' ';

  i := 1;

  WHILE TRUE LOOP

  saida:= SUBSTR(NOME_CLIENTE, 1, INSTR(NOME_CLIENTE, ' '));

NOME_CLIENTE := SUBSTR(NOME_CLIENTE, INSTR(NOME_CLIENTE, ' ') + 1, LENGTH(NOME_CLIENTE));

saida := TRIM(saida);

IF LENGTH(saida) IS NULL THEN

   EXIT;

END IF;

IF LENGTH(saida) <= 30 THEN

   INSERT INTO CLIENTE_FONETICA (CODIGO, DES_FONETICA ) VALUES (CLIENTE_rec.CODIGO, saida);

END IF;

  END LOOP;

  END LOOP;

END FONETIZAR_CLIENTE;

/

 

 

--codigo fonte 1

 

unit Unit1;

 

interface

 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, FMTBcd, DB, DBClient, Provider, SqlExpr, Grids, DBGrids,

  StdCtrls, DBXpress;

 

type

  TForm1 = class(TForm)

Edit1: TEdit;

Button1: TButton;

Button3: TButton;

DBGrid1: TDBGrid;

DataSource1: TDataSource;

SQLDataSet1: TSQLDataSet;

DataSetProvider1: TDataSetProvider;

ClientDataSet1: TClientDataSet;

SQLConnection1: TSQLConnection;

procedure Button2Click(Sender: TObject);

procedure Button1Click(Sender: TObject);

procedure DBGrid1DblClick(Sender: TObject);

procedure Button3Click(Sender: TObject);

procedure FormCreate(Sender: TObject);

  private

{ Private declarations }

Function GetPiece(Node: string; Delimiter: string; FirstPiece: integer): string;

Function GetPieces(Node: string; Delimiter: string; FirstPiece: integer; LastPiece: integer): string;

Function PieceLength(Node: string; Delimiter: string): integer;

  public

{ Public declarations }

Resultado: string;

  end;

 

var

  Form1: TForm1;

 

implementation

 

{$R *.dfm}

 

 

Function TForm1.GetPiece(Node: string; Delimiter: string; FirstPiece: integer): string;

begin

 Result := GetPieces(Node, Delimiter, FirstPiece, FirstPiece);

end;

 

Function TForm1.GetPieces(Node: string; Delimiter: string; FirstPiece: integer; LastPiece: integer): string;

var

  p, p0, p1, i, c: integer;

  s: string;

begin

 

  s := Node + Delimiter;

 

  if (FirstPiece = 1) and (LastPiece = 1) then begin

if Pos(Delimiter, Node) = 0 then

Result := Node

else

Result := Copy(Node, 0, Pos(Delimiter, Node) - 1);

Exit;

  end;

 

  p  := 1;

  p0 := 0;

  p1 := 0;

  c  := 0;

 

  for i := 0 to Length(Node) do begin

if s[i] = Delimiter then

inc(p);

 

if FirstPiece = 1 then begin

c := 1;

end;

 

if (c = 0) and (p = FirstPiece) then begin

p0 := i + 1;

c := 1;

end;

 

if (c = 1) and (p < (LastPiece + 1)) then begin

inc(p1);

end;

 

  end;

 

  if p1 <> Length(s) then dec(p1);

 

  Result := Copy(Node, p0, p1);

 

end;

 

Function TForm1.PieceLength(Node: string; Delimiter: string): integer;

var i,j: integer;

  begin

i := 1;

j := 0;

while i > 0 do

begin

  i := pos(Delimiter, node);

node := copy(node,i+1,length(node)-1);

j := j + 1;

end;

  Result := j;

end;

 

 

 

procedure TForm1.Button2Click(Sender: TObject);

begin

  Resultado := ClientDataSet1.Fields[0].AsString;

end;

 

 

 

 

procedure TForm1.Button1Click(Sender: TObject);

const

  FONETIZAR  = 'SELECT FONETIZAR(''%s'') AS RESULTADO FROM DUAL';

  CONSULTAR1 = 'SELECT B.COD_MATERI AS "Código", B.NOM_MATERI AS "Nome do Material" FROM ('+

'SELECT DISTINCT COD_MATERI FROM MATERIAL_FONETICA WHERE ';

  CONSULTAR2 = 'DES_FONETI = ''%s'' ';

  CONSULTAR3 = ') A, MATERIAL B '+

'WHERE A.COD_MATERI = B.COD_MATERI';

var

  Aux, Comando: string;

  i: integer;

begin

  if Edit1.Text = '' then begin

ShowMessage('Digite um texto para Pesquisar; ');

Exit;

  end;

 

  if ClientDataSet1.Active then

ClientDataSet1.Close;

 

  ClientDataSet1.CommandText := Format(FONETIZAR,[Edit1.Text]);

  ClientDataSet1.DisableControls;

 

  ClientDataSet1.Open;

  Aux := (ClientDataSet1.Fields[0].AsString);

 

  Comando := CONSULTAR1;

  for i := 1 to PieceLength(Aux, ' ') do begin

Comando := Comando + Format(CONSULTAR2,[GetPiece(Aux,' ', i)]);

if i <> PieceLength(Aux,' ') then

Comando := Comando + 'OR ';

  end;

  Comando := Comando + CONSULTAR3;

 

  ClientDataSet1.Close;

  ClientDataSet1.EnableControls;

  ClientDataSet1.CommandText := Comando;

  ClientDataSet1.Open;

 

  if ClientDataSet1.RecordCount = 0 then begin

ShowMessage('Sua pesquisa não retornou nenhum resultado.');

ClientDataSet1.Close;

  end;

 

end;

 

procedure TForm1.DBGrid1DblClick(Sender: TObject);

begin

  Resultado := ClientDataSet1.Fields[0].AsString;

  ModalResult := mrOk;

end;

 

procedure TForm1.Button3Click(Sender: TObject);

begin

close;

end;

 

procedure TForm1.FormCreate(Sender: TObject);

begin

 

end;

 

end.

 

 

Links

http://www.oracle.com/technology/software/products/sql/index.html

Ebook exclusivo
Dê um upgrade no início da sua jornada. Crie sua conta grátis e baixe o e-book

Artigos relacionados