make all

cd /usr/src/universe && make all

Exemplo de um script SQL interativo no PostgreSQL

Escrito por Guedes em Abril 7, 2008

Exemplo de um script SQL interativo no PostgreSQLA semana foi corrida, e o final de semana foi totalmente utilizado para descanso e lazer. Mas a vontade de escrever é maior, e cá estou novamente pronto para mais um post. A idéia hoje era falar sobre scripts SQL, então imaginei algo diferente, e pensei em mostrar como fazer um script interativo no PostgreSQL 8.3, associando o seu uso a um cenário hipotético. Vejamos…

Em um universo ideal, é muito comum existir um banco de dados de desenvolvimento, um de testes, um de homologação e um de produção. Neste cenário, imagine que seu Analista de Testes precise testar uma nova funcionalidade do sistema relacionada ao módulo de compras, e que para isso constantemente você tenha que aplicar a carga de testes desse módulo no banco de dados de teste, não é de se estranhar que você possua uma carga pronta (é o mínimo que você deveria ter).

Veja a seguir o script simplificado que representa esse cenário:

CREATE TABLE tb_cliente (
     nr_documento numeric(14,0) NOT NULL,
     nm_cliente character varying(60)
);
ALTER TABLE blog.tb_cliente OWNER TO postgres;

CREATE TABLE tb_compra (
     nr_nota_fiscal numeric(15,0) NOT NULL,
     dt_compra date,
     nr_documento_cliente numeric(14,0)
);
ALTER TABLE blog.tb_compra OWNER TO postgres;

CREATE TABLE tb_item_compra (
     nr_nota_fiscal numeric(15,0) NOT NULL,
     nr_referencia integer NOT NULL,
     qt_item smallint DEFAULT 1
);
ALTER TABLE blog.tb_item_compra OWNER TO postgres;

CREATE TABLE tb_produto (
     nr_referencia integer NOT NULL,
     ds_produto character varying(60) NOT NULL,
     vl_venda numeric(15,2)
);
ALTER TABLE blog.tb_produto OWNER TO postgres;

CREATE SEQUENCE tb_produto_nr_referencia_seq
     INCREMENT BY 1
     NO MAXVALUE
     NO MINVALUE
     CACHE 1;
ALTER TABLE blog.tb_produto_nr_referencia_seq OWNER TO postgres;

ALTER SEQUENCE tb_produto_nr_referencia_seq OWNED BY tb_produto.nr_referencia
ALTER TABLE tb_produto ALTER COLUMN nr_referencia SET DEFAULT nextval('tb_produto_nr_referencia_seq'::regclass);

ALTER TABLE ONLY tb_compra
     ADD CONSTRAINT pk_compra PRIMARY KEY (nr_nota_fiscal);
ALTER TABLE ONLY tb_item_compra
     ADD CONSTRAINT pk_item_compra PRIMARY KEY (nr_nota_fiscal, nr_referencia);
ALTER TABLE ONLY tb_cliente
     ADD CONSTRAINT pk_pessoa PRIMARY KEY (nr_documento);
ALTER TABLE ONLY tb_produt
     ADD CONSTRAINT pk_produto PRIMARY KEY (nr_referencia);

ALTER TABLE ONLY tb_compra
     ADD CONSTRAINT fk_cliente_compra_01 FOREIGN KEY (nr_documento_cliente) REFERENCES tb_cliente(nr_documento);
ALTER TABLE ONLY tb_item_compra
     ADD CONSTRAINT fk_compra_item_compra_01 FOREIGN KEY (nr_nota_fiscal) REFERENCES tb_compra(nr_nota_fiscal);
ALTER TABLE ONLY tb_item_compr
     ADD CONSTRAINT fk_produto_item_compra_01 FOREIGN KEY (nr_referencia) REFERENCES tb_produto(nr_referencia);

Esse é o conteúdo simplificado da entidade cliente no banco de dados de teste:

 nr_documento |        nm_cliente
--------------+---------------------------
74727756632 | Marta Antonia
56548986527 | Antonia Josefina
47040567970 | Adamantina Pereira
24348435149 | Carlos Augusto
80987468692 | José Silveira
56096344407 | Maria Eleontina de Castro
79056669606 | José da Silva Sauro
31887461081 | Ribamar de Castr
45792555043 | Manoel Bandeira

Esse é o conteudo simplificado da entidade produto no banco de dados de teste:

 nr_referencia |    ds_produto     | vl_venda
---------------+-------------------+----------
1 | Sapato Velho      |    15.00
2 | Sapato Novo       |    25.00
3 | Blusa Velha       |    35.00
4 | Blusa Nova        |    45.00
5 | Calça Jeans Velha |    29.50
6 | Calça Jeans Nova  |    49.50
7 | Peruca Masculina  |   439.9
8 | Camisola          |    19.50

E este é o Script de Carga de Teste para as entidades tb_compra e tb_item_compra:

postgres@banco $ cat ~/scripts/carga_compra_teste.sql
/***************************************************
*
* Script de geração de carga
* Modulo de Compras - Banco de dados de Teste
*
* (c) 2007 Dickson Guedes <guediz at gmail dot com>
*
****************************************************/

INSERT INTO tb_compra (nr_nota_fiscal, dt_compra, nr_documento_cliente
     VALUES (1234567890, now(), 56473847366);

INSERT INTO tb_item_compra (nr_nota_fiscal, nr_referencia, qt_item)
     VALUES (1234567890, 6,  2);
INSERT INTO tb_item_compra (nr_nota_fiscal, nr_referencia, qt_item)
     VALUES (1234567890, 4,  1);
INSERT INTO tb_item_compra (nr_nota_fiscal, nr_referencia, qt_item)
     VALUES (1234567890, 3, 15);
INSERT INTO tb_item_compra (nr_nota_fiscal, nr_referencia, qt_item
     VALUES (1234567890, 2,  2);

INSERT INTO tb_compra (nr_nota_fiscal, dt_compra, nr_documento_cliente
     VALUES (1122334455, now(), 56096344407);

INSERT INTO tb_item_compra (nr_nota_fiscal, nr_referencia, qt_item)
     VALUES (1122334455, 6,  2);
INSERT INTO tb_item_compra (nr_nota_fiscal, nr_referencia, qt_item)
     VALUES (1122334455, 4,  1);
INSERT INTO tb_item_compra (nr_nota_fiscal, nr_referencia, qt_item)
     VALUES (1122334455, 3, 15);
INSERT INTO tb_item_compra (nr_nota_fiscal, nr_referencia, qt_item
     VALUES (1122334455, 2,  2);

E para executá-lo e utilizo o utilitário psql:

postgresql@banco $ psql bdtesteWelcome to psql 8.4devel, the PostgreSQL interactive terminal.

Type:  \copyright for distribution terms
     \h for help with SQL commands
     \? for help with psql commands
     \g or terminate with semicolon to execute quer
     \q to quit

postgres=# \i ~/scripts/carga_compra_teste.sql

E se eu quisesse tornar esse script interativo?

O utilitário psql além de aceitar instruções SQL, possui um conjunto de instrucoes proprias que nos permitem extenter suas funcionalidades. Utilizaremos duas delas: \echo, que permite enviar um texto para a console do psql e \prompt (a partir da versão 8.3 do PostgreSQL) que permite receber um dado da entrada e salvar um uma variável.

Nosso script acima poderia ficar assim:

/***************************************************
*
* Script de geração de carga
* Modulo de Compras - Banco de dados de Teste
*
* (c) 2007 Dickson Guedes <guediz at gmail dot com>
*
****************************************************/

\echo """"""""""""""""""""""""""""""""""""""""""
\echo " Gerando carga para o ambiente: TESTE   "
\echo "                                        "
\echo " Cenário: Prestacoes de compra a prazo  "
\echo "                                        "
\echo """"""""""""""""""""""""""""""""""""""""""
\echo
\echo Continuar..: Enter
\echo Cancelar...: Ctrl+C

\prompt continua
\unset continuar

\echo
SELECT nr_documento || ' -> ' || nm_cliente AS "Lista de Clientes" FROM tb_cliente;
\echo
\prompt 'Informe um dos números de CPFs acima.: ' v_nr_document
\prompt 'Informe o número da nota fiscal......: ' v_nr_nota_fiscal

\echo '* Inserindo compra para o cliente:' :v_nr_documento 'com número de nota fiscal:' :v_nr_nota_fiscal

INSERT INTO tb_compra (nr_nota_fiscal, dt_compra, nr_documento_cliente) VALUE
     (:v_nr_nota_fiscal, now(), :v_nr_documento);

INSERT INTO tb_item_compra (nr_nota_fiscal, nr_referencia, qt_item) VALUES
     (:v_nr_nota_fiscal, 2, ((RANDOM()*5)+1)::int2),
     (:v_nr_nota_fiscal, 4, ((RANDOM()*5)+1)::int2),
     (:v_nr_nota_fiscal, 7, ((RANDOM()*5)+1)::int2),
     (:v_nr_nota_fiscal, 5, ((RANDOM()*5)+1)::int2);

\echo "* Script finalizado!"

E para executá-lo e utilizo também o utilitário psql:

postgresql@banco $ psql bdtesteWelcome to psql 8.4devel, the PostgreSQL interactive terminal.

Type:  \copyright for distribution terms
\h for help with SQL commands
\? for help with psql commands
\g or terminate with semicolon to execute quer
\q to quit

postgres=# \i ~/scripts/carga_compra_teste.sql

DICA 1: quando usar o \prompt você pode usar 2 (dois) argumentos: um texto explicativo seguido do nome da variável que você deseja armazenar o valor recebido.
DICA 2: os valores das variáveis são recuperados utilizando-se o dois pontos (”:”) precedendo o nome da variável que se deseja ler o valor, como por exemplo \echo ‘Valor da variavel é’ :variavel_qualquer.

DESAFIO 1: Tente alterar o script acima para que os produtos também sejam aleatórios, ou seja, cada vez que o script for executado ele gere uma carga diferente.

DESAFIO 2: Como você trataria o problema de um erro de digitação ou problema de violação de chaves? Você poderia utilizar transações?

Uma resposta para “Exemplo de um script SQL interativo no PostgreSQL”

  1. Fernando F. Disse:

    Estava há um tempo pra ler esse teu artigo, salvei ele no bookmark até que fosse chegada a hora que saberia que precisaria disso. heaheuahe.
    Muito bom, e como o comportamento do psql interativo é bem parecido com o próprio bash, não é difícil brincar com ele.

    Um abraco.

Deixe um comentário

XHTML: Você pode usar estas tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>