Esses tempos tinha uma pergunta pipocando em uma lista sobre MySQL onde uma pessoa queria fazer alguma coisa em um procedimento (procedure) e não conseguia. A solução que eu encontrei para ajudar a pessoa foi Prepared Statements.
Para ilustrar o seu uso criei uma tabela:
CREATE TABLE PEDIDO (
CODPEDIDO INT(3) ZEROFILL NOT NULL,
CODCLIENTE INT(3) ZEROFILL NOT NULL,
VALOR DOUBLE NOT NULL,
STATUS CHAR(1) NOT NULL
);
Depois inseri dados:
INSERT INTO Pedido(CodPedido, CodCliente, Valor, Status) VALUES(1, 1, 99.87, 'E');
INSERT INTO Pedido(CodPedido, CodCliente, Valor, Status) VALUES(2, 2, 99.87, 'A');
INSERT INTO Pedido(CodPedido, CodCliente, Valor, Status) VALUES(3, 3, 99.87, 'A');
INSERT INTO Pedido(CodPedido, CodCliente, Valor, Status) VALUES(4, 2, 99.87, 'S');
INSERT INTO Pedido(CodPedido, CodCliente, Valor, Status) VALUES(5, 2, 99.87, 'A');
INSERT INTO Pedido(CodPedido, CodCliente, Valor, Status) VALUES(6, 3, 99.87, 'E');
O Status seria: E – Encerrado, A – Aberto, S – Suspenso.
Depois pode se criar o Prepared Statements, eu fiz dentro de um procedimento, mas poderia ser feito direto no console do MySQL que funcionaria.
Criando o procedimento (procedure):
CREATE PROCEDURE P_PEDIDOS_STATUS(IN STATUS CHAR(1))
BEGIN
SET @StatusPedido = STATUS;
PREPARE psmtp FROM 'SELECT CodPedido, CodCliente, Valor, Status FROM Pedido WHERE Status = (?) GROUP BY CodCliente ORDER BY CodPedido';
EXECUTE psmtp USING @StatusPedido;
DEALLOCATE PREPARE psmtp;
END;
Bom a finalidade aqui é selecionar todos os pedidos por status, para isso passamos por parâmetro o status que desejamos procurar:
Resultados:
mysql> call P_PEDIDOS_STATUS('E');
+-----------+------------+-------+--------+
| CodPedido | CodCliente | Valor | Status |
+-----------+------------+-------+--------+
| 001 | 001 | 99.87 | E |
| 006 | 003 | 99.87 | E |
+-----------+------------+-------+--------+
2 rows in set (0.00 sec)
Query OK, 0 rows affected (0.02 sec)
mysql> call P_PEDIDOS_STATUS('A');
+-----------+------------+-------+--------+
| CodPedido | CodCliente | Valor | Status |
+-----------+------------+-------+--------+
| 002 | 002 | 99.87 | A |
| 003 | 003 | 99.87 | A |
+-----------+------------+-------+--------+
2 rows in set (0.00 sec)
Query OK, 0 rows affected (0.02 sec)
mysql> call P_PEDIDOS_STATUS('S');
+-----------+------------+-------+--------+
| CodPedido | CodCliente | Valor | Status |
+-----------+------------+-------+--------+
| 004 | 002 | 99.87 | S |
+-----------+------------+-------+--------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.02 sec)
Agora, e se quisermos ter um procedimento maluco que receba toda a minha query e a execute? Sei lá qual a finalidade disto (agora não me ocorre nada em mente que justifique, mas vai que você tem um relatório que muda muito pouco de uma query – por exemplo só o where ou o order by - e pode generalizar a chamada passando a query ou parte dela? Sei lá!) então poderiamos “injetar” para o procedimento todo o comando a ser executado no SGBD:
CREATE PROCEDURE P_INJETA_SQL(IN SQLCOMMAND VARCHAR(500))
BEGIN
SET @Command = SQLCOMMAND;
PREPARE psmtp FROM @Command;
EXECUTE psmtp;
DEALLOCATE PREPARE psmtp;
END;
Teste:
mysql> CALL P_INJETA_SQL('SELECT CodPedido, CodCliente, Valor, Status FROM Pedido WHERE Status = ''E'' GROUP BY CodCliente ORDER BY CodPedido');
+-----------+------------+-------+--------+
| CodPedido | CodCliente | Valor | Status |
+-----------+------------+-------+--------+
| 001 | 001 | 99.87 | E |
| 006 | 003 | 99.87 | E |
+-----------+------------+-------+--------+
2 rows in set (0.00 sec)
Query OK, 0 rows affected (0.02 sec)
Beleza, afunfa!
Bom de asas a sua imaginação agora e qualquer coisa comenta aí! :D
quarta-feira, junho 13, 2007
Assinar:
Postar comentários (Atom)
2 comentários:
boaaa...
eu uso prepared statements para fazer paginação de dados usando stored procedures, passo o "limit" via parâmetro..
mas na verdade ainda não sei qual a vantagem de prepared statement
Obrigado pela visita ao blog e pelo comentário.
Vantagem, não sei se é a palavra correta... mas diversas vezes montamos nossos comandos SQL na aplicação e queremos executalos, está é uma maneira :)
Abraço.
Postar um comentário