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
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo