quarta-feira, junho 13, 2007
Prepared Statements no MySQL.
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
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
Marcadores:
injeção de sql,
mysql,
prepared statements
sexta-feira, junho 01, 2007
Palestra sobre Hibernate e Jboss SEAM
Ontem fui a duas palestras na Targettrust, uma delas sobre Hibernate e a outra sobre o Jboss Seam.
Sai de lá me perguntando: porque eu fui? :) Com um monte de coisas que eu preciso estudar para finalmente marcar minha prova de certificação agora fiquei ansiando por aprender mais sobre o SEAM.
Muito boa a palestra, pena que teve seu tempo drasticamente encurtado mas mesmo assim muito legal.
O material está no blog do autor: http://www.juliocsmac.blogspot.com.
Bom, mais além eu irei escrever sobre o SEAM e tal...
Por hora é isso, a vida ta corrida! :P
Marcadores:
hibernate,
hibernate anootation,
java,
jboss,
jboss seam
Assinar:
Postagens (Atom)