Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
Olá,
Suponha que voce tenha uma view X com N campos, voce sabe o nome da view, mas nao sabe o nome de nenhum campo da mesma e voce precisa pegar somente os dados que sejam LIKE '%alguma_coisa%' de qualquer um dos campos desta view.
É possivel?
Ex.:
SELECT FROM "nome_da_view" WHERE LIKE '%alguma_coisa%';
Tem como colocar alguma coisa no lugar do segundo asterisco? =P
Pode parecer algo idiota, mas isso me obriga a criar um arquivo com a query correta para cada consulta que eu tenho que fazer, entao, qualquer ajuda é bem vindo....
Obrigado.
@Motta, SQL dinâmica é permitida em view ?
Não sei, só testando Andrey.
A ideia seria, supondo uma tabela assim
tabela
------
campo1 char
campo2 integer
campo3 char
campo4 date
campo5 char
Um select lê a tabela de metadados
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'tabela'
AND COLUMN_TYPE = 'char'
teria este result
campo1
campo3
campo5
o select montado seria
select *
from tabela
where
(
campo1 like '%motta%'
or
campo3 like '%motta%'
or
campo5 like '%motta%'
)
a parte
campoX like ...
seria um loop do cursor, claro.
uma ideia básica, se uma coluna6 fosse criada na próxima execução ela seria tratada automaticamente.
Estou tentando entender essa parte de SQL dinamica...
Eu poderia fazer uma query somente para pegar os indices e usa-los na comparacao, mas nao me parece algo inteligente...
Outra coisa que eu havia pensado era +- nisso
SELECT p.* FROM view p WHERE 'alguma_coisa' IN(SELECT * FROM view s WHERE s.id=p.id)
O problema e que o select de dentro retorna mais de 1 coluna... tentei concatenar para virar uma string mas n foi....Deixa eu dar a última tacada .. por favor.
DELIMITER $$
CREATE PROCEDURE findAll ( IN tableName VARCHAR( 28 ) , IN search TEXT )
LANGUAGE SQL NOT DETERMINISTIC CONTAINS SQL
BEGIN
DECLARE finished INT DEFAULT FALSE ;
DECLARE columnName VARCHAR ( 28 ) ;
DECLARE stmtFields TEXT ;
DECLARE columnNames CURSOR FOR
SELECT DISTINCT `COLUMN_NAME` FROM `information_schema`.`COLUMNS`
WHERE `TABLE_NAME` = tableName ORDER BY `ORDINAL_POSITION` ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = TRUE;
SET stmtFields = '' ;
OPEN columnNames ;
readColumns: LOOP
FETCH columnNames INTO columnName ;
IF finished THEN
LEAVE readColumns ;
END IF;
SET stmtFields = CONCAT(
stmtFields , IF ( LENGTH( stmtFields ) > 0 , ' AND' , '' ) ,
' `', tableName ,'`.`' , columnName , '` LIKE "' , search , '"'
) ;
END LOOP;
SET @stmtQuery := CONCAT ( 'SELECT * FROM `' , tableName , '` WHERE ' , stmtFields ) ;
PREPARE stmt FROM @stmtQuery ;
EXECUTE stmt ;
CLOSE columnNames ;
END ;:seta:
CALL findAll ( 'messages' , '%termo a ser pequisado%' ) ;
:seta:
SELECT * FROM messages WHERE messages.mid LIKE "%termo a ser pequisado%" AND messages.uid LIKE "%
termo a ser pequisado%" AND messages.text LIKE "%termo a ser pequisado%" AND messages.date LIKE "%term
o a ser pequisado%"
E só pra lembrar, eu não declarei todos os handlers para os erros possíveis não, portanto você vai ter que fazer isso por conta própria.
cara, que massa andrei , so uma duvida, eu nao criei procedimentos ainda, o simples fato de eu executar o codigo do procedimento, apos isso, poderei chamar ele simplismente por CALL nome_do_procedimento(param1,paramN..) ?
andrey, quando eu nao passo nenhum valor no parametro search, a query esta retornando todos os valores, o que esta correto, porem, quando eu insiro algo, nada e encontrado...
Obs.: Ainda estou tentando entender o procedimento, caso tenha algo a acrescentar, eu agradeco. Obrigado.
Ola, encontrei uma solucao, infelizmente sao necessarias 3 queryes , uma para pegar as colunas, outra para contar o total de registros p/ paginar os resultados e a ultima p/ pegar os resultados... segue um exemplo
//aqui eu pego quais sao as colunas que tem na tabela
//o valor que retorna e armazenado em uma var no php, que monta todos os likes p/ todas as colunas
SHOW COLUMNS FROM 'nome_da_tabela'
//aqui eu vejo o total de resultados da query e uso p/ paginar depois...
SELECT COUNT(*) AS rows FROM 'nome_da_tabela' + "tratamento_da_string_da_query_das_colunas_para_likes ";
//aqu ieu pego os valores e monto a array data
SELECT * FROM 'nome_da_tabela' + "tratamento_da_string_da_query_das_colunas_para_likes ";
Conclusao: Funciona, mas olha a gambi hehehe, assim que eu entender o que o andrey postou irei postar minhas consideracoes, ainda so meio amador haha...
Abracos
>
cara, que massa andrei , so uma duvida, eu nao criei procedimentos ainda, o simples fato de eu executar o codigo do procedimento, apos isso, poderei chamar ele simplismente por CALL nome_do_procedimento(param1,paramN..) ?
andrey, quando eu nao passo nenhum valor no parametro search, a query esta retornando todos os valores, o que esta correto, porem, quando eu insiro algo, nada e encontrado...
Obs.: Ainda estou tentando entender o procedimento, caso tenha algo a acrescentar, eu agradeco. Obrigado.
Você chama 'CALL findAll ( nomeDaTabela , valorParaTodosOsLikes ) ;'
#6 :clap:
Andrey, a procedure que voce postou funcionou, abaixo as alteracoes feitas:
... stmtFields , IF ( LENGTH( stmtFields ) > 0 , ' AND' , '' ) , ... ficou
....stmtFields , IF ( LENGTH( stmtFields ) > 0 , ' OR' , '' ) , ...
AND trocado por OR, ja que quaisquer um dos campos compativeis ja sao suficientes.
e
...CONCAT ( 'SELECT * FROM `' , tableName , '` WHERE ' , stmtField... ficou
...CONCAT ( 'SELECT * FROM `' , tableName , '` WHERE' , stmtField...
O espaco apos o where era preenchido com o espaco antes do LIKE, assim, ficavam 2 espacos.
ficou fantastico :D
Duvida:
... SELECT DISTINCT `COLUMN_NAME` FROM `information_schema`.`COLUMNS` ...
O select acima seleciona todas as colunas da tabela, inclusive as ja excluidas, eu tinha um campo antigamente na tabela, chamado Y, este campo foi excluido, mas o where ainda tenta dar um LIKE Y hehe, quando eu trabalho com views nao tenho esse problema, mas eu estava tentando padronizar tanto para tabelas normais quanto para views.
Duvida2: Posso passar um terceiro parametro p/ a procedure com o limit?
Abracos.
>
Andrey, a procedure que voce postou funcionou, abaixo as alteracoes feitas:
... stmtFields , IF ( LENGTH( stmtFields ) > 0 , ' AND' , '' ) , ... ficou
....stmtFields , IF ( LENGTH( stmtFields ) > 0 , ' OR' , '' ) , ...
AND trocado por OR, ja que quaisquer um dos campos compativeis ja sao suficientes.
Isso era a seu critério !
>
...CONCAT ( 'SELECT * FROM `' , tableName , '` WHERE ' , stmtField... ficou
...CONCAT ( 'SELECT * FROM `' , tableName , '` WHERE' , stmtField...
O espaco apos o where era preenchido com o espaco antes do LIKE, assim, ficavam 2 espacos.
Havia percebido, mas não faz muita diferença, no final das contas a query não é exibida pra você e isso não atrapalha na execução .. eu tenho costume de dar um monte de espaço para o código ficar bem legível.
>
Duvida:
... SELECT DISTINCT `COLUMN_NAME` FROM `information_schema`.`COLUMNS` ...
O select acima seleciona todas as colunas da tabela, inclusive as ja excluidas, eu tinha um campo antigamente na tabela, chamado Y, este campo foi excluido, mas o where ainda tenta dar um LIKE Y hehe, quando eu trabalho com views nao tenho esse problema, mas eu estava tentando padronizar tanto para tabelas normais quanto para views.
Isso é estranho, o distinct nesse caso serve apenas para eliminar a repetição.
>
Duvida2: Posso passar um terceiro parametro p/ a procedure com o limit?
:seta:
findAll(IN tableName VARCHAR( 28 ) , IN search TEXT , IN Param3 VARCHAR, IN Param4 VARCHAR)
[iN,OUT,INOUT] => Contexto
IN => Parâmetros de entrada,
OUT => Parâmetros de saída,
INOUT => Contexto para ambos os lados
[...] Nome do parâmetro , o varchar alí você já deve saber do que se trata ..
paulo,
Nessa sua view/tabela são muitas as colunas char e varchar?
Ola prog!
As vezes sao somente 2 colunas, varia de acordo com a tabela que eu passo para a funcao, as vezes ate mesmo FKS, porem, quando eu crio as views, as FKS sao transoformadas nas respectivas strings da FK.
Andrey, consegui adicionar limit com sucesso!
Duvida:
...
OUT => Parâmetros de saída,
...
Esse parametro de saida, eu consigo retornar, por exemplo, uma array na seguinte estrutura:
array(
'dados '=> retorno_da_query,
'totalDePaginas' => alguma_var_que_vai_pegar_count_dentro_da_procedure
)Não .. essa pergunta já foi feita em tal tópico que eu não lembro qual, o SQL não trabalha pro PHP !
Com base na tabela de metadados a query poderia ser montada dinamicamente para cada coluna do tipo char.
Só não sei se a tabela de colunas tem as colunas de uma view (no Oracle por exemplo tem).