make all

cd /usr/src/universe && make all

Posts Tagged ‘scripts’

Personalizando o psql

Posted by Guedes em maio 25, 2008

Personalizando o psqlUma das ferramentas mais utilizadas na administração do PostgreSQL é o nosso bom e velho psql. Sua interface em modo texto permite a sua utilização local ou remota de maneira rápida e eficiente  nos presenteando com alguns recursos interessantes como por exemplo a complementação de código baseada em contexto (proporcionado pelo readline).

Este blog mudou! Acesso este post na íntegra aqui http://guedesoft.net/blog/2008/05/25/personalizando-o-psql/

Anúncios

Posted in postgresql | Etiquetado: , , | 1 Comment »

Exemplo de um script SQL interativo no PostgreSQL

Posted by 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…

Este blog mudou! Acesse este post em: http://guedesoft.net/blog/2008/04/07/exemplo-de-um-script-sql-interativo-no-postgresql/

Posted in postgresql | Etiquetado: , , | 1 Comment »

ALTER TABLE em massa no PostgreSQL…

Posted by Guedes em março 27, 2008

ALTER TABLE em massa no PostgreSQL...Você já se deparou com a necessidade de fazer uma alteração que afeta vários campos de várias tabelas? Imagine a seguinte situação: você possui vários campos em diversas tabelas que representam valores monetários de 10 casas inteiras e 2 decimais, ou seja, tipo numeric(12,2), e por necessidade do cliente o analista informou que isso precisa ser alterado para 15 casas inteiras e 2 decimais, ou seja, tipo numeric(17,2). E agora?

Bem, nosso amigo elefante que nunca esquece, guarda esses dados com bastante carinho e permite que nós, meros mortais, possamos visualizá-los e tomar decisões com eles já que cada banco de dados possui um esquema contendo os dados sobre os seus dados – os metadados. O nome desse esquema é information_schema e contém views que nos permitem, por exemplo, listar os campos de uma tabela com seus respectivos tipos, essa view é declarada como columns. Então o que tem nela?

  SELECT * FROM information_schema.columns;(saída muito grande aqui ...)

Testou? “Coisarada” né? Mas que tal listar as colunas de uma tabela especifica? Suponha que exista uma tabela ‘tb_pessoa’:

SELECT *  FROM information_schema.columns  WHERE table_name =  'tb_pessoa';


 table_catalog | table_schema |  table_name   |      column_name       | ordinal_position | column_default | is_nullable |          data_type          | character_maximum_length | character_octet_length | numeric_precision | numeric_precision_radix | numeric_scale | datetime_precision | interval_type | interval_precision | character_set_catalog | character_set_schema | character_set_name | collation_catalog | collation_schema | collation_name | domain_catalog | domain_schema | domain_name | udt_catalog | udt_schema | udt_name  | scope_catalog | scope_schema | scope_name | maximum_cardinality | dtd_identifier | is_self_referencing
---------------+--------------+---------------+------------------------+------------------+----------------+-------------+-----------------------------+--------------------------+------------------------+-------------------+-------------------------+---------------+--------------------+---------------+--------------------+-----------------------+----------------------+--------------------+-------------------+------------------+----------------+----------------+---------------+-------------+-------------+------------+-----------+---------------+--------------+------------+---------------------+----------------+---------------------
 esquema       | esquema      | tb_pessoa     | tipo_pessoa            |                3 |                | NO          | integer                     |                          |                        |                32 |                       2 |             0 |                    |               |                    |                       |                      |                    |                   |                  |                |                |               |             | esquema     | pg_catalog | int4      |               |              |            |                     | 3              | NO
 esquema       | esquema      | tb_pessoa     | nome                   |                2 |                | NO          | character varying           |                      150 |             1073741824 |                   |                         |               |                    |               |                    |                       |                      |                    |                   |                  |                |                |               |             | esquema     | pg_catalog | varchar   |               |              |            |                     | 2              | NO
 esquema       | esquema      | tb_pessoa     | nome_personalizado     |                9 |                | YES         | character varying           |                       25 |             1073741824 |                   |                         |               |                    |               |                    |                       |                      |                    |                   |                  |                |                |               |             | esquema     | pg_catalog | varchar   |               |              |            |                     | 9              | NO
 esquema       | esquema      | tb_pessoa     | dt_inclusao            |                5 |                | NO          | date                        |                          |                        |                   |                         |               |                    |               |                    |                       |                      |                    |                   |                  |                |                |               |             | esquema     | pg_catalog | date      |               |              |            |                     | 5              | NO
 esquema       | esquema      | tb_pessoa     | nro_documento          |                1 |                | NO          | numeric                     |                          |                        |                14 |                      10 |             0 |                    |               |                    |                       |                      |                    |                   |                  |                |                |               |             | esquema     | pg_catalog | numeric   |               |              |            |                     | 1              | NO

Melhorou né? Mas que tal agora mostrar só o que interessa? Como por exemplo, o nome ta tabela, o nome da coluna, o tipo da mesma e se ela aceita nulo?

SELECT    table_name      AS nome_tabela,

column_name     AS nome_coluna,

data_type       AS tipo,

is_nullable     AS aceita_nulo

FROM

information_schema.columns

WHERE

table_name = 'tb_pessoa';

nome_tabela  |      nome_coluna       |            tipo             | aceita_nulo

---------------+------------------------+-----------------------------+-------------

tb_pessoa     | tipo_pessoa            | integer                     | NO

tb_pessoa     | nome                   | character varying           | NO

tb_pessoa     | nome_personalizado     | character varying           | YES

tb_pessoa     | dt_inclusao            | date                        | NO

tb_pessoa     | nro_documento          | numeric                     | NO

Melhor ainda né? Se você analisar a descrição da view columns perceberá que pode melhorar a saida acima. Vejamos:

                      Visão "information_schema.columns"          Coluna          |                Tipo                | Modificadores

--------------------------+------------------------------------+---------------

table_catalog            | information_schema.sql_identifier  |

table_schema             | information_schema.sql_identifier  |

table_name               | information_schema.sql_identifier  |

column_name              | information_schema.sql_identifier  |

ordinal_position         | information_schema.cardinal_number |

column_default           | information_schema.character_data  |

is_nullable              | information_schema.character_data  |

data_type                | information_schema.character_data  |

character_maximum_length | information_schema.cardinal_number |

character_octet_length   | information_schema.cardinal_number |

numeric_precision        | information_schema.cardinal_number |

numeric_precision_radix  | information_schema.cardinal_number |

numeric_scale            | information_schema.cardinal_number |

datetime_precision       | information_schema.cardinal_number |

interval_type            | information_schema.character_data  |

interval_precision       | information_schema.character_data  |

character_set_catalog    | information_schema.sql_identifier  |

character_set_schema     | information_schema.sql_identifier  |

character_set_name       | information_schema.sql_identifier  |

collation_catalog        | information_schema.sql_identifier  |

collation_schema         | information_schema.sql_identifier  |

collation_name           | information_schema.sql_identifier  |

domain_catalog           | information_schema.sql_identifier  |

domain_schema            | information_schema.sql_identifier  |

domain_name              | information_schema.sql_identifier  |

udt_catalog              | information_schema.sql_identifier  |

udt_schema               | information_schema.sql_identifier  |

udt_name                 | information_schema.sql_identifier  |

scope_catalog            | information_schema.sql_identifier  |

scope_schema             | information_schema.sql_identifier  |

scope_name               | information_schema.sql_identifier  |

maximum_cardinality      | information_schema.cardinal_number |

dtd_identifier           | information_schema.sql_identifier  |

is_self_referencing      | information_schema.character_data  |

SELECT

table_name        AS nome_tabela,

column_name       AS nome_coluna,

data_type         AS tipo,

numeric_precision AS digitos,

numeric_scale     AS decimais,

is_nullable       AS aceita_nulo

FROM

information_schema.columns

WHERE

data_type = 'numeric';

Agora só falta juntar tudo isso numa panela, cozinhar por alguns minutos e servir o script que irá satisfazer o nosso problema inicial (lembra? mudar de numeric(12,2) para numeric(17,2)):

SELECT     'ALTER TABLE '   || table_name  ||

' ALTER COLUMN ' || column_name ||

' TYPE numeric(17,2);'

FROM

information_schema.columns

WHERE

data_type = 'numeric'  AND

numeric_precision = 12 AND

numeric_scale     = 2;

?column?

-----------------------------------------------------------------------------------

ALTER TABLE tb_funcionario ALTER COLUMN remuneracao_basica TYPE numeric(17,2);

ALTER TABLE tb_pessoa_juridica ALTER COLUMN valor_receita TYPE numeric(17,2);

ALTER TABLE tb_fonte_renda_pf ALTER COLUMN valor_renda TYPE numeric(17,2);

ALTER TABLE tb_caixa ALTER COLUMN saldo_dia TYPE numeric(17,2);

--- CORTE ---

Pronto, ai está o nosso script! Você precisa apenas executá-lo agora.

DESAFIO: como a saida do comando SQL é grande, redirecione a saida para um arquivo e execute-o via psql.

Bom, é isso “:D

Posted in postgresql | Etiquetado: , , , | 4 Comments »

Será que meu dump foi gerado com sucesso?

Posted by Guedes em março 26, 2008

Será que meu dump foi gerado com sucesso? Uma das atividades mais comuns de um DBA é a geração do arquivo de dump de suas bases de dados, que nada mais é do que um arquivo contendo a imagem do seu banco de dados em um determinado instante do tempo. Como existem ferramentas de linha de comando que geram esses arquivos, é bastante comum utilizá-las em scripts autônomos, agendados diariamente no período noturno. Mas nem tudo são flores e podemos ser supreendidos ao saber que justo aquele dump que precisávamos não foi executado com sucesso. E agora?

Bom, como já diz o ditado “é melhor prevenir do que remediar”… então, que tal melhorar o script que gera o dump?

AVISO: os passos a seguir não se aplicam ao S.O. Windows ‘puro’, você precisa ter o Cygwin instalado!

Nos sistemas operacionais unix-like possuimos a saida padrão (conhecida por stdout, cujo descritor de arquivo é 1), a saída padrão de erros (conhecida por stderr, cujo descritor de arquivo é 2) e a entrada padrão (conhecida por stdin, cujo descritor de arquivo é 0). Estes recursos podem ser utilizados para redirecionar as saidas de nossos programas. No caso do nosso amigo pg_dump geralmente utilizamos ele assim:

postgres@meu_banco ~$ pg_dump meu_banco > meu_banco.dump

O que estamos fazendo, nada mais é do que redirecionar a saída padrão (stdout) do pg_dump para um arquivo chamado ‘meu_banco.dump’. Mas e se ocorrer algum imprevisto, como falta de espaço em disco, por exemplo? Neste caso, podemos redirecionar a saída de erros (que por padrão é a console) para um arquivo com o seguinte comando:

postgres@meu_banco ~$ pg_dump meu_banco > meu_banco.dump 2> meu_banco.erro

A única diferença foi a adição de ‘2> meu_banco.erro’ ao final do comando. No caso isso indica que os dados enviados para a saída padrão de erros (stderr, descritor de arquivo 2), devem ser redirecionados para o arquivo ‘meu_banco.erro’. Sendo assim, após o comando ter sido executado, pode-se verificar se o arquivo ‘meu_banco.erro’ está vazio (indicando sucesso na operação) ou contém algo (indicando que houve erro).

Este método é interessante porque você guarda o erro ocorrido, o que via script pode ajudar a entender a origem do problema e até mesmo servir de conteúdo para um e-mail automaticamente enviado para o DBA.

Outro método que você pode utilizar é redirecionar a saida padrão de erros para /dev/null e utilizar os operadores ‘&&’ e ‘||’ do shell.

pg_dump > meu_banco.dump 2>/dev/null && echo "OK" || echo "ERRO"

No caso acima, se tudo ocorrer bem, ele ecoará “OK” do contrário “ERRO” será retornado.

Colocando tudo num script

Podemos utilizar os conceitos acima para criar um script que automatize este processo todo. Segue:

#!/bin/sh
###############################################
#
# Script de geração de dump full
#
# (c) 2006-2008 Dickson Guedes <guediz at gmail com>
#
###############################################

# Email DBA
CFG_EMAIL="dba@minhaempresa.com"

# Variaveis de mensagens
MSG_OK="Dump gerado com sucesso!"
MSG_ERRO="Dump gerado com erros!"
MSG_DATA=`date +"%Y-%m-%d"`

# Variaveis de caminhos dos utilitarios
PRG_PGDUMP="/usr/bin/pg_dump"

# Variaveis dos arquivos gerados
ARQ_DUMP="meu_banco"
ARQ_DUMP_OK="$ARQ_DUMP-$MSG_DATA.dump"
ARQ_DUMP_ERRO="$ARQ_DUMP-$MSG_DATA.erro"

###############################################

$PRG_PGDUMP >$ARQ_DUMP_OK 2>$ARQ_DUMP_ERRO && STATUS="SUCESSO" || STATUS="ERRO"

if [ "$STATUS" = "SUCESSO" ]; then
        echo "$MSG_OK"   | mail -s"$MSG_OK" $CFG_EMAIL
else
        echo "$MSG_ERRO" | mail -s"$MSG_ERRO" $CFG_EMAIL < $ARQ_DUMP_ERRO
fi

###############################################

DESAFIO: alterar o script acima adicionando a característica de passar o nome do banco de dados através de parâmetros de linha de comando.

Bom, é isso… “:)

Posted in postgresql | Etiquetado: , , , | 1 Comment »