mirror of
https://github.com/hoshikawa2/agent-ai-mcp-server.git
synced 2026-03-06 18:21:01 +00:00
First commit
This commit is contained in:
124
source/fn_busca_fonetica_produtos.sql
Normal file
124
source/fn_busca_fonetica_produtos.sql
Normal file
@@ -0,0 +1,124 @@
|
||||
CREATE TABLE produtos (
|
||||
id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
codigo VARCHAR2(50),
|
||||
descricao VARCHAR2(4000)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_texto_descricao ON produtos(descricao)
|
||||
INDEXTYPE IS CTXSYS.CONTEXT;
|
||||
|
||||
|
||||
-- DROP TYPES (se existirem)
|
||||
BEGIN
|
||||
EXECUTE IMMEDIATE 'DROP TYPE produto_resultado_tab';
|
||||
EXECUTE IMMEDIATE 'DROP TYPE produto_resultado';
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN NULL;
|
||||
END;
|
||||
/
|
||||
|
||||
-- Criação de um tipo de tabela para retorno da função
|
||||
CREATE OR REPLACE TYPE produto_resultado AS OBJECT (
|
||||
codigo VARCHAR2(50),
|
||||
descricao VARCHAR2(4000),
|
||||
similaridade NUMBER
|
||||
);
|
||||
|
||||
CREATE OR REPLACE TYPE produto_resultado_tab AS TABLE OF produto_resultado;
|
||||
/
|
||||
|
||||
-- Função que faz busca por palavras aproximadas por fonética ou distância
|
||||
-- Criação de um tipo de tabela para retorno da função
|
||||
CREATE OR REPLACE TYPE produto_resultado AS OBJECT (
|
||||
codigo VARCHAR2(50),
|
||||
descricao VARCHAR2(4000),
|
||||
similaridade NUMBER
|
||||
);
|
||||
|
||||
CREATE OR REPLACE TYPE produto_resultado_tab AS TABLE OF produto_resultado;
|
||||
/
|
||||
|
||||
-- Função de busca fonética e por palavras-chave
|
||||
CREATE OR REPLACE FUNCTION fn_busca_avancada(p_termos IN VARCHAR2)
|
||||
RETURN produto_resultado_tab PIPELINED
|
||||
AS
|
||||
v_termos SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST();
|
||||
v_token VARCHAR2(1000);
|
||||
v_descricao VARCHAR2(4000);
|
||||
v_score NUMBER;
|
||||
v_dummy NUMBER;
|
||||
BEGIN
|
||||
-- Dividir os termos da busca
|
||||
FOR i IN 1..REGEXP_COUNT(p_termos, '\S+') LOOP
|
||||
v_termos.EXTEND;
|
||||
v_termos(i) := LOWER(REGEXP_SUBSTR(p_termos, '\S+', 1, i));
|
||||
END LOOP;
|
||||
|
||||
-- Loop pelos produtos
|
||||
FOR prod IN (SELECT codigo, descricao FROM produtos) LOOP
|
||||
v_descricao := LOWER(prod.descricao);
|
||||
v_score := 0;
|
||||
|
||||
-- Avaliar cada termo da busca
|
||||
FOR i IN 1..v_termos.COUNT LOOP
|
||||
v_token := v_termos(i);
|
||||
|
||||
-- 3 pontos se encontrar diretamente
|
||||
IF v_descricao LIKE '%' || v_token || '%' THEN
|
||||
v_score := v_score + 3;
|
||||
ELSE
|
||||
-- 2 pontos se foneticamente similar
|
||||
BEGIN
|
||||
SELECT 1 INTO v_dummy FROM dual
|
||||
WHERE SOUNDEX(v_token) IN (
|
||||
SELECT SOUNDEX(REGEXP_SUBSTR(v_descricao, '\w+', 1, LEVEL))
|
||||
FROM dual
|
||||
CONNECT BY LEVEL <= REGEXP_COUNT(v_descricao, '\w+')
|
||||
);
|
||||
v_score := v_score + 2;
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN NULL;
|
||||
END;
|
||||
|
||||
-- 1 ponto se similar por escrita
|
||||
BEGIN
|
||||
SELECT 1 INTO v_dummy FROM dual
|
||||
WHERE EXISTS (
|
||||
SELECT 1
|
||||
FROM (
|
||||
SELECT REGEXP_SUBSTR(v_descricao, '\w+', 1, LEVEL) AS palavra
|
||||
FROM dual
|
||||
CONNECT BY LEVEL <= REGEXP_COUNT(v_descricao, '\w+')
|
||||
)
|
||||
WHERE UTL_MATCH.EDIT_DISTANCE(palavra, v_token) <= 2
|
||||
);
|
||||
v_score := v_score + 1;
|
||||
EXCEPTION
|
||||
WHEN NO_DATA_FOUND THEN NULL;
|
||||
END;
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
-- Só retorna se houver ao menos algum match
|
||||
IF v_score > 0 THEN
|
||||
PIPE ROW(produto_resultado(prod.codigo, prod.descricao, v_score));
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
RETURN;
|
||||
END;
|
||||
/
|
||||
|
||||
-- Grant para execução, se necessário:
|
||||
GRANT EXECUTE ON fn_busca_fonetica_por_palavra TO PUBLIC;
|
||||
|
||||
|
||||
-- Testes
|
||||
SELECT *
|
||||
FROM TABLE(fn_busca_avancada('harry poter pedra'))
|
||||
ORDER BY similaridade DESC;
|
||||
|
||||
SELECT * FROM TABLE(fn_busca_fonetica_por_palavra('velho mar'))
|
||||
ORDER BY similaridade DESC;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user