Simplicity
Principal
Início
- - - - - - -
Programação
Administração
Modelagem
Projeto
Práticas
Scripts
Módulos Completos
- - - - - - -
Documentação
Dicas
Colaborações
Links
Ferramentas
- - - - - - -
Trabalho
Busca
Forum
Diversos
Contato
Sobre Min
Livro de Visitas
PG - RSS
feed image
 
Dicas PDF Imprimir E-mail
Por Ribamar FS   
21 de June de 2008

Dicas

 

 Esta seção exibe principalmente as dicas que considero importantes para guardar, recebidas no dia-a-dia da lista do PostgreSQL Brasil - Geral. Também mostro algumas  de outras fontes.

 

A ordem foi invertida agora para facilitar futuras consultas: as mais recentes mais acima.

 

57) Instalação silenciosa do PostgreSQL no Windows

Minha aplicacao funciona bem com a instalação abaixo: Dê uma olhada e faça a adaptação para a sua !
 
msiexec /i postgresql-8.2-int.msi /qr INTERNALLAUNCH=1 ADDLOCAL=server,pgadmin DOINITDB=1 CREATESERVICEUSER=1 SERVICEACCOUNT="usuario" SERVICEPASSWORD="senha" SUPERUSER="Administrador" SUPERPASSWORD="senha" PERMITREMOTE=1 BASEDIR="'c:\aplicativo" DATADIR="c:\aplicativo\data" PL_PGSQL=1 LOCALE=Portuguese_Brazil.1252 ENCODING=LATIN1 TRANSFORMS=:lang_pt_br';

Emerson Lopes


1) Criar Tabela tendo outra outra como base e já importando todos os registros dessa outra:
CREATE TABLE tabelanova AS SELECT * FROM tabealexistente;


2) Inserindo com SELECT
Inserir todos os registros de uma tabela em outra:
INSERT INTO tabelaqueimporta SELECT * from tabelaqueexporta;

insert into engenharia.insumos (grupo,insumo,descricao,unidade) select grupo,insumo,descricao, CAST(unidade AS int2) AS "unidade" from engenharia.apagar

insert into engenharia.insumos (grupo,insumo,descricao,unidade) select grupo,insumo,descricao, cast(unidade AS INT2) AS unidade from engenharia.apagar

$conn = pg_connect("host=10.40.100.186 dbname=apoena user=_postgresql");
for($x=10;$x<=87;$x++){
$sql="update engenharia.precos set custo_produtivo = (select custo_produtivo from engenharia.apagar where insumo='$x') where insumo='00' || '$x'";
$ret=pg_query($conn,$sql);
}


3) Atualizar um campo em todos os registros de uma tabela recebendo de outra tabela:

Trabalhando com SQL

Atualizar todos os registros (um campo) puxando de outra tabela:

UPDATE servicos s SET custo = total FROM composicoes c
WHERE s.tabela = c.tabela AND s.servico = c.servico

Uso do Like e de Expressões Regulares

Registros:
Ribamar Ferreira de Sousa
João Pereira Brito

Usando LIKE e ILIKE

SELECT * FROM clientes WHERE nome LIKE 'Riba%'; // Retorna Ribamar Ferreira de Sousa
SELECT * FROM clientes WHERE nome LIKE 'riba%'; // Nada retorna
SELECT * FROM clientes WHERE nome ILIKE 'riba%'; // Retorna Ribamar Ferreira de Sousa
SELECT * FROM clientes WHERE nome NOT LIKE 'pedro'; // Retorna ambos os registros

Usando Expressões Regulares

SELECT * FROM clientes WHERE nome ~~ 'Riba%'; // Retorna Ribamar Ferreira de Sousa
SELECT * FROM clientes WHERE nome ~~ 'riba%'; // Nada retorna
SELECT * FROM clientes WHERE nome ~~* 'riba%'; // Retorna Ribamar Ferreira de Sousa
SELECT * FROM clientes WHERE nome !~~ 'pedro'; // Retorna ambos os registros
SELECT nome FROM clientes WHERE nome ~ 'Ribamar Ferreira de Sousa'; // Retorna Ribamar Ferreira de Sousa
SELECT * FROM clientes WHERE nome !~ 'jorge'; // Retorna ambos


4) Buscar nas tabelas de sistema do postgresql, todos as tabelas de um determinado schema, os campos que sejam do tipo boolean..

SELECT n.nspname AS Schema, c.relname AS Tabela, t.typname AS Tipo
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_type t ON t.oid = c.reltype
WHERE c.relkind = 'r'::"char"
AND t.typname = 'boolean';


5) Exemplos de Joins

Join com 4 tabelas

$w_sql = " TRUE ";

if ( $p_tabela != "") { $w_sql = $w_sql . " AND tabela ~~*'" . $p_tabela . "'"; }
if ( $p_insumo_grupo != "") { $w_sql = $w_sql . " AND insumo_grupo ~~*'" .$p_insumo_grupo."'"; }
if ( $p_insumo != "") { $w_sql = $w_sql . " AND insumo ~~*'" . $p_insumo . "'"; }
if ( $p_fornecedor != "") { $w_sql = $w_sql . " AND fornecedor ~~*'" .$p_fornecedor."'"; }

$w_sql="SELECT distinct on (p.tabela, p.insumo_grupo, p.insumo, p.fornecedor) p.custo_produtivo, p.data_inclusao,
t.tabela, t.descricao as tabelad,
ig.grupo, ig.descricao as insumogd,
i.grupo, i.insumo, i.descricao as insumod,
f.codigo_fornecedor, f.razao_social as fornecedord
FROM $m_table as p, $m_table_tab as t, $m_table_ing as ig, $m_table_ins as i, $m_table_for as f
WHERE p.tabela=t.tabela AND p.insumo_grupo=ig.grupo AND p.insumo=i.insumo AND p.fornecedor=f.codigo_fornecedor
AND p.insumo_grupo = i.grupo ORDER BY p.tabela DESC, p.insumo_grupo;";

/*
p - $m_table (engenharia.precos)
i - $m_table_ins (engenharia.insumos)
ig - $m_table_ing (engenharia.insumos_grupos)
t - $m_table_tab (engenharia.tabela)
*/


6) Mudar Tipo de Dados de Campo - CAST (Só >=8.0):

ALTER TABLE tabela ALTER COLUMN campo TYPE tipo;
ALTER TABLE produtos ALTER COLUMN preco TYPE numeric(10,2);
ALTER TABLE produtos ALTER COLUMN data TYPE DATE USING CAST (data AS DATE);


7) Renomear Tabela
ALTER TABLE tabela RENAME TO nomenovo;
ALTER TABLE produtos RENAME TO equipamentos;


8) Tamanho de Tabela, Banco ou Todos os Bancos do SGBD:

Tamanho de Banco de Dados (postgresql 8.1 ou superior):
select pg_database_size('nomebanco');

Tamanho de Tabela
select pg_tablespace_size('nometabela');

Tamanho de todos os bancos de dados do SGBD:
select (sum(relpages) * 8) / 1024 || ' MB' as tamanho from pg_class where relowner > 1;

Ou

select (sum(relpages) / 2^7) :: int || ' MB' as tamanho from pg_class where relowner > 1;


9) Validação de e-mails

1 - select distinct(campo_email),campo_nome, campos_n from tabela where campo_email like '%@%.%'
2 - SELECT POSITION('@', ' Este endereço de e-mail está sendo protegido de spam, você precisa de Javascript habilitado para vê-lo ') > 0
3 - select ' Este endereço de e-mail está sendo protegido de spam, você precisa de Javascript habilitado para vê-lo ' ~ '@'
4 - select ' Este endereço de e-mail está sendo protegido de spam, você precisa de Javascript habilitado para vê-lo ' like '%@%'
5 - select if ('campo_email' like "%@%.%","TRUE","FALSE") as flag, campo_adcional from tabela
6 - select ' Este endereço de e-mail está sendo protegido de spam, você precisa de Javascript habilitado para vê-lo ' similar to '%@%.%';

Estas dicas foram resultado de uma discussão na lista phpfortaleza, do Yahoo.


10) Temos um campo (insumo) com valores = 1, 2, 3, ... 87
Queremos atualizar para 0001, 0002, 0003, ... 0087

UPDATE equipamentos SET insumo = '000' || insumo WHERE LENGTH(insumo) = 1;
UPDATE equipamentos SET insumo = '00' || insumo WHERE LENGTH(insumo) = 2;

Outra saída mais elegante ainda:

UPDATE equipamentos SET insumo = REPEAT('0', 4-LENGTH(insumo)) || insumo;


11) Retornar o número de usuários conectados
select count(*) from pg_stat_activity

pg_stat_database que apresenta para cada banco de dados o número de conexões.
Eu particularmente acho que fica mais fácil de visualizar do que o pg_stat_activity quando se tem muitas conexões.

Mostrar uso dos índices dos bancos de dados:
select * from pg_statio_user_indexes;

select * from pg_stat_user_indexes;

Mostra estatística de uso das tabelas e manutenção:
select * from pg_stat_all_tables;

Mostra todas as tabelas do atual esquema do atual banco:
select * from pg_stat_user_tables;

pg_stat_get_tuples_returned(oid) bigint Number of rows read by sequential scans when argument is a table, or number of index entries returned when argument is an index
pg_stat_get_tuples_fetched(oid) bigint Number of table rows fetched by bitmap scans when argument is a table, or table rows fetched by simple index scans using the index when argument is an index
pg_stat_get_tuples_inserted(oid) bigint Number of rows inserted into table
pg_stat_get_tuples_updated(oid) bigint Number of rows updated in table
pg_stat_get_tuples_deleted(oid) bigint Number of rows deleted from table
pg_stat_get_blocks_fetched(oid) bigint Number of disk block fetch requests for table or index
pg_stat_get_blocks_hit(oid) bigint Number of disk block requests found in cache for table or index
pg_stat_get_last_vacuum_time(oid) timestamptz Time of the last vacuum initiated by the user on this table
pg_stat_get_last_autovacuum_time(oid) timestamptz Time of the last vacuum initiated by the autovacuum daemon on this table
pg_stat_get_last_analyze_time(oid) timestamptz Time of the last analyze initiated by the user on this table
pg_stat_get_last_autoanalyze_time(oid) timestamptz Time of the last analyze initiated by the autovacuum daemon on this table

This is controlled by configuration parameters that are normally set in postgresql.conf

The function pg_stat_get_backend_idset provides a convenient way to generate one row for each active server process. For example, to show the PIDs and current queries of all server processes:

SELECT pg_stat_get_backend_pid(s.backendid) AS procpid,
pg_stat_get_backend_activity(s.backendid) AS current_query
FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s;

Visualizar os processos do portgresql num UNIX:

ps auxww | grep ^postgres

Formato de retorno:
postgres: user database host activity


12) Corrigindo Estouro do Máximo de transações (2 bilhões)
Constatando:

SELECT datname, age(datfrozenxid) FROM pg_database;

age acusa mais de 2 bilhões

Tarcizio Meurer

- Execute um dumpall na base
- drop a base e o agrupamento de dados
- recrie o agrupamento
- recrie a base
- carrege os dados novemente.


13) Total de Registros de Todos os Bancos do SGBD (PHP):

<?php

$conexao=pg_connect("host=127.0.0.1 user=postgres password=postabir");

$sql="SELECT datname AS banco FROM pg_database ORDER BY datname";
$consulta=pg_query($conexao,$sql);

$banco = array();
$c=0;
while ($data = @pg_fetch_object($consulta,$c)) {
$cons=$data->banco;

$banco[] .= $cons;
$c++;
}

$sql2="SELECT n.nspname as esquema,c.relname as tabela FROM pg_namespace n, pg_class c
WHERE n.oid = c.relnamespace
and c.relkind = 'r' -- no indices
and n.nspname not like 'pg\\_%' -- no catalogs
and n.nspname != 'information_schema' -- no information_schema
ORDER BY nspname, relname";

for ($x=0; $x < count($banco);$x++){
if ($banco[$x] !="template0" && $banco[$x] != "template1" && $banco[$x] !="postgres"){
$conexao2=pg_connect("host=127.0.0.1 dbname=$banco[$x] user=postgres password=postabir");
$consulta2=pg_query( $conexao2, $sql2 );

while ($data = pg_fetch_object($consulta2)) {
$esquematab=$data->esquema.'.'.$data->tabela;
$sql3="SELECT count(*) FROM $esquematab";
$consulta3=pg_query($conexao2,$sql3);
$res=@pg_fetch_array($consulta3);

print 'Banco.Esquema.Tabela -> '.$banco[$x].'.'.$data->esquema.'.'.$data->tabela.' - Registro(s) - '.$res[0].'';
$total += $res[0];
}

}
}
print "Total de Registro de todas as tabelas de todos os bancos ". $total;

?>


14) Uso da Constraint check

CREATE TABLE testes(
codigo serial primary key,
idade integer,
check (idade > 18 AND idade < 70)
)

Alternativas:

check (preco > desconto)

check (desconto > 0 AND preco > desconto)

-------------
Somente aceitar c ou e (simulando campo tipo enum do MySQL):
tipo char(1) check (tipo ='c' OR tipo='e')

Para este cria-se uma combo com values 'c' e 'e'.


15) Manutenção do PostgreSQL:
No CRON:

/home/pgsql/bin/psql -c "vacuum full analyse" -d dadosadv -U postgres

Consultas no Pronpt do SO:
psql -U postgres -d banco -c "SELECT * FROM clientes"

Manutenção em Tabela
vacuum analize tabela;

Reindexar Banco, tabela ou índice
reindex database banco;

Exibir plano de consulta
explain select * from tabela;

Exibir todos os parâmetros de runtime
show all;


16) Consulta com Dias Úteis

Só para constar aqui vai uma expressão SQL que fornece os
dias úteis de um período. Considerei que existe uma tabela
com o registro dos feriados e outros dias que não devem ser
considerados (emendas, pontos facultativos, etc):

SELECT dia FROM
(SELECT ('2007-10-01'::date+s.a*'1 day'::interval) AS dia
FROM generate_series(0, '2007-10-31'::date -
'2007-10-01'::date, 1) AS s(a)) foo
WHERE EXTRACT(DOW FROM dia) BETWEEN 1 AND 5
EXCEPT
SELECT dia FROM tab_feriado;

Osvaldo (na lista postgresql-br)


17) Update em uma chave primária sem causar duplicação de chave

UPDATE teste SET coluna1 = t_aux.coluna1+1
FROM (
SELECT coluna1
FROM teste
ORDER BY coluna1 DESC
) t_aux
WHERE teste.coluna1 = t_aux.coluna1;

Osvaldo (na lista postgresql-br)


18) Como saber se existe uma transação ativa

select pg_stat_activity;

Dica do João Paulo.


19)Inserir data como valor default:

Pode usar também o current_date ou o localtimestamp.

insert into tabela(data) values ((select current_date));

ou

insert into tabela(data) values ((select localtimestampo));


20) Ler último saldo de tabela

Tenho o seguinte conteudo numa tabela de contas:

Lancto--CCorrente--Banco--OP--DataLan-------Valor---------Saldo--
1 12345-6 002 C 19/11/2007 1000.00 1000.00
2 12345-6 002 C 19/11/2007 2000.00 3000.00
3 12345-6 002 D 19/11/2007 100.00 2900.00
4 23450-6 001 C 19/11/2007 2000.00 3000.00
5 23450-6 001 D 19/11/2007 100.00 2900.00

Preciso retornar sempre o último SALDO registrado.
Como nunca vou saber a data exata da periodo de consulta.

Estou executando:

SELECT saldoatual FROM lanban WHERE contacorrente = '12345-6' and datalan <= '2007/12/01' ORDER BY datalan DESC LIMIT 1

Retona o Saldo: 1000.00, preciso pegar o ultimo saldo da conta 12345-6: que é 2900.00.

Isso porque tabelas são conjuntos de dados. O padrão SQL *não* garante a
ordem dos dados. Mesmo se ele garantisse, um simples UPDATE podia mudar
o ordem dos dados e o seu SELECT não retornaria o valor desejado.

> Alguem tem alguma dica?
>
O campo 'Lancto' é do tipo serial? Se for poderias utilizar:
SELECT saldoatual FROM lanban WHERE contacorrente = '12345-6' ORDER BY
"Lancto" DESC LIMIT 1.

Dica do Euler Taveira de Oliveira


21) Formato de moeda

O correto seria:
to_char(1030.52,'9G999D99')
mas o resultado é: 1,030,52
como você pode observar existe um problema no
separador de milhar (indicado pelo G) que é
considerado como , e não como . que seria o esperado.

Uma maneira de contornar (não muito elegante) é:
to_char(1030.52,'9"."999D99')

Corrigido na versão 8.3


22) Saber o Tamanho de Tabela e de Índices

pg_relation_size()
pg_total_relation_size()

-Leo
--
Leonardo Cezar


23) Último Saldo
Fernando Brombatti

A situação é a seguinte. Não se sabe se o serial citado (por N razões) vai ser o último valor existente. Nada me garante que estes dados não sofreram algum UPDATE. Sendo assim, recomendo:
1) alterar o campo DATE para TIMESTAMP
2) alterar o query:
SELECT lan.saldoatual
FROM lanban lan
WHERE lan.contacorrente = '12345-6' AND lan.datalan = (SELECT MAX(maxlan.datalan)
FROM lanban maxlan
WHERE maxlan.contacorrente = lan.contacorrente)
Isso faz com que no primeiro SQL eu traga os lancamentos da conta e no segundo eu trago a máxima data de lançamento para a mesma conta. Como as contas são iguais, trago a máxima data da conta atual, logo tenho o saldo atual.
É confuso, mas é o mais seguro (podem haver UPDATES neste caso também, mas aí não se depende de um serial).
Para este query funcionar bem necessita mais um índice em datalan ao menos.
Nos nossos sistemas da prefeitura nunca usamos saldos desta forma, pois aí se é removido algum registro a informação não fica correta.

Espero não ter confundido tanto.


24) Encontrando tanela de sistema

Para localizar informações desse tipo existe o information_schema
(conforme citado pelo Leandro). Utilizando o catalogo poupa voce de
futuras dores de cabeça quando por exemplo houver alguma alteração
estrutural em tabelas do sistema em versõs futuras. As views do
catalogo deverão permanecer com o máximo de compatibilidade entre
versões (segundo padrão SQL).

Além de ser mais simples:

SELECT *
FROM information_schema.tables
WHERE table_name = 'foobar';

Infelizmente não possuimos referencias a outros banco de dados
(banco.schema.tabela), portanto o comando deverá ser executado em
todos seus bancos para localizar a tabela ou um programeta bash
parecido com isso:

$ ARG=$1 || "foo" && for DATABASE in `psql -U postgres -c "\l" \
| cut -d"|" -f1 | egrep '^(\ [a-z])'`
do
psql -U postgres -d $DATABASE -Atc \
"SELECT 'O banco de dados $DATABASE possui a tabela: $RG'
FROM information_schema.tables
WHERE table_name = '$ARG'";
done;

Abraço!

-Leo


25) Como Localizar e Deletar registros duplicados

1.Select para localizar duplicados
select campo,campo1,count(*)
from tabela having count(*) > 1
group by campo,campo1

2.Deletar duplicados:
delete from tab p1
where rowid < (select max(rowid)
from tab1 p2
where p1.primary_key = p2.primary_key);


26) Inserir registros em uma específica posição
> Hi, how are you? maybe you know how SQL insert data
> bellow or above in database tabe? example insert
> data from position table 5 thanks
>

No, I don't known.
But if you make a copy from table,
create a new table with same structure,
insert a new register,
import register from old table, then first register
are this last register inserted.


27) Timezones do PostgreSQL (lista pgbr-geral)

No POSTGRESQL.CONF tem o timezone onde você pode colocar algo do tipo:

TIMEZONE=BRAZIL/EAST esta é minha configuração, ou seja, de minha região.

Analise.
Wandrey

Outra -----------
Na maioria dos casos é criado um link do diretório de timezones do
S.O. (/usr/share/zoneinfo//usr/share/zoneinfo/) para o diretório de
Timezones do Postgres ($PGDIR/share/timezone )Que possui seu próprio
sistema de controle de timezone, se não me engano a partir d versão 8)

--
Att:
Thiago Risso


28) Inserir Número Aleatório em Tabela

CREATE TABLE page (
id SERIAL PRIMARY KEY,
about TEXT NULL,
);

ALTER TABLE page ADD myrand NUMERIC NOT NULL DEFAULT RANDOM();

UPDATE page SET myrand = DEFAULT;

SELECT id FROM page WHERE myrand >= RANDOM() ORDER BY myrand LIMIT 1;

This approach has some problems:

* If the number you pick is greater than the largest number in the myrand column, you will not find any matching rows.
* The gaps between the random values in the myrand column are not uniform, and thus the rows selected are not random. Imagine a table with two rows and myrand values of 0.8 and 0.9. If the random number compared to myrand is .8 or less, the first row is chosen. But the second row is only chosen if the value picked is between .8 and .9
* If more than one row has the exact same number, it is likely that one of them will never get picked.

Mais detalhes em: http://people.planetpostgresql.org/greg/index.php?/archives/118-guid.htm...


29) Desabilitar Triggers
Vinicius Santos - MSI escreveu:
Thiago Boufleuhr escreveu:

Como faço para desabilitar as triggers em uma sessão no PLSQL ?

Thiago Boufleuhr

ALTER TABLE [NOME DA TABELA]
DISABLE TRIGGER [NOME DA TRIGGER]
Ou
ALTER TABLE [NOME DA TABELA]
DISABLE TRIGGER ALL

ALERTA:
William Leite Araújo: MUITO CUIDADO AO USAR "DISABLE TRIGGER ALL"

As constraints de chave estrangeira são controladas via TRIGGER. Caso desabilite todos os gatilhos, a checagem da integridade referencial (chaves estrangeiras) serão desabilitadas!


30) Codificação de Caracteres
Euler Taveira de Oliveira
>Evandro Ricardo Silvestre wrote: Codificação de caracteres do cliente e
do servidor podem ser diferentes. Se a codificação do cliente é diferente da codificação do servidor, o servidor PostgreSQL tenta fazer uma conversão antes de armazenar/retornar os dados. Um problema que existia é que a aplicação cliente (no caso abaixo o psql) não avisava se a codificação informada ao servidor (client_encoding) era a mesma do ambiente (terminal).
Bem vindo ao psql 8.3.0, o terminal iterativo do PostgreSQL.
Digite: \copyright para mostrar termos de distribuição
\h para ajuda com comandos SQL
\? para ajuda com comandos do psql
\g ou terminar com ponto-e-vírgula para executar a consulta
\q para sair
template1=# show client_encoding;
client_encoding
-----------------
LATIN1
(1 registro)
template1=# show server_encoding;
server_encoding
-----------------
LATIN1
(1 registro)
template1=# select upper('áéíóú');
upper
-------
ÁÉÍÓÚ
(1 registro)
template1=# set client_encoding to 'utf-8';
SET

template1=# show client_encoding;
client_encoding
-----------------
utf-8
(1 registro)
template1=# select upper('áéíóú');
ERRO: sequência de bytes é inválida para codificação "UTF8": 0xe1e9ed
DICA: Este erro pode acontecer também se a sequência de bytes nãocorresponde a codificação esperado pelo servidor, que é controlada por "client_encoding".
ERRO: sequência de bytes é inválida para codificação "UTF8": 0xe1e9ed
DICA: Este erro pode acontecer também se a sequência de bytes não corresponde a codificação esperado pelo servidor, que é controlada por "client_encoding".
[trocando a codificação de caracteres do terminal e digitando novamente]
template1=# select upper('áéí');
upper
-------
ÁÉÍ
(1 registro)


31) Como visualizar as consultas correntes no Postgres

Colaboração: Frederico Palma

Data de Publicação: 16 de fevereiro de 2008

É necessário habilitar o stats_command_string no postgresql.conf:

stats_command_string = true

Essa configuração pode ser alterada em um banco que está ativo sem a necessidade de reiniciá-lo e sem afetar as conexões abertas para recarregar as configurações. Envie um SIGHUP ou use o comando:

pg_ctl reload

Quando stats_command_string está ativo a tabela pg_stat_activity armazena todas consultas correntes.

Realizando a consulta:

SELECT datname,procpid,current_query FROM pg_stat_activity

Teremos a lista dos bancos de dados utilizados com seus respectivos processos (PID) referente às consultas.

SELECT datname,procpid,current_query FROM pg_stat_activity ORDER BY procpid;

datname | procpid | current_query
------------+---------+-----------------
mydatabase1 | 2587 | < IDLE>
mydatabase2 | 15726 | SELECT * FROM users WHERE id=123 ;
mydatabase3 | 15851 | < IDLE>

Publicado originalmente na Dicas-L - http://www.dicas-l.com.br/dicas-l/20080216.php


32) Receber o retorno de duas consultas com Subselects

select (a.x + b.y) as total from
    (select sum(valor_empenho)as x from planejamento.empenho
        where codigo_acao = '2272') a,
    (select sum(valor_empenho_reforco)as y from planejamento.empenho_reforco
        where numero_empenho in (select numero_empenho from planejamento.empenho where codigo_acao = '2272' )) b

Dica da colega Fátima Ramalho do DNOCS


33) Operando com Data e Hora

SELECT '10/01/2005'::DATE - '01/01/2000'::DATE
SELECT NOW() - '2001/1/1'
SELECT (current_date - '1956-08-03')/365
SELECT 'today'::date;
SELECT '12:16'::time;
SELECT '12:16:32.43'::time with time zone;
SELECT 'now'::time with time zone;
SELECT '2001-01-12'::timestamp;


34) Calculando com o PostgreSQL

Truncando casas depois da vírgula (4)

SELECT trunc ( ( 1550.99 * 6 ) / 100 , 4);

 trunc
 - - - - -
 93.0594
(1 row)


Truncando casas depois da vírgula (2)

SELECT trunc ( ( 1550.99 * 6 ) / 100 , 2);

 trunc
 - - - - -
 93.05
(1 row)


Arredondando casas depois da vírgula (4)

SELECT round ( ( 1550.99 * 6 ) / 100 , 4);

 round
 - - - - -
 93.0594
(1 row)


Arredondando casas depois da vírgula (2)

SELECT round ( ( 1550.99 * 6 ) / 100 , 2);

 round
 - - - - -
 93.06
(1 row)


35) Quando precisamos alterar uma tabela, por exemplo, removendo um campo podemos usar:

SELECT ... -- select todos os campos, menos o que deseja remover
INTO TABLE nova
FROM antiga;
DROP TABLE antiga;
ALTER TABLE nova RENAME TO antiga;

Autor: Melanie Nelson


36) Backup e restore

pg_dumpall -o > dumpfile
The -o option causes the unique object identifiers to be dumped as well as the user-defined database objects.

If you have issued GRANT and REVOKE privileges commands, you must include the -z flag in the dump command to have these stored:

pg_dumpall -oz > dumpfile

The command to reload the database is:

psql -e database < dumpfile

Inserindo valor NULL em tabela

INSERT INTO table VALUES ('xxx', 'yyy', NULL, 'zzz')

If the NULL is to go into the last field, it can be omitted, and will be inserted by default (unless you specified otherwise at the time you created the table)

note:The single quotes around non-null values are only required for character type fields

If you are using the COPY command, NULL fields should be indicated by \N in the file from which the data is being copied.

Autor: Melanie Nelson


37) E-books online sobre PostgreSQL

http://etutorials.org/SQL/Postgresql/Part+I+General+PostgreSQL+Use/

Sams - PHP and PostgreSQL Advanced Web Programming
http://jlbtc.eduunix.cn/index/html/php/Sams%20-%20PHP%20and%20PostgreSQL%20Advanced%20Web%20Programming/

PostgreSQL Prático:
http://www.ribafs.net/down/1PostgreSQL_Pratico.pdf ou

http://pt.wikibooks.org/wiki/PostgreSQL_Prático

PostgreSQL - A Comprehensive Guide:
http://www.conjectrix.com/pgbook/index.html
Arquivos de exemplo: http://www.conjectrix.com/pgbook/source2/bookdata.tar.gz

38) Cursos

Dextra (SP e Campinas)
http://www.dextra.com.br/

OpenDB
http://opendb.com.br/v1/index.php

Evolução (Fortaleza)
http://www.evolucao.com.br

dbExperts (SP)
http://www.dbexperts.com.br

Virgos
http://www.virgos.com.br/portal/treinamento/ementa.php?curso=32

Sisnema
http://www.sisnema.com.br/Materias/idmat013773.htm

Vídeo Aulas para Iniciantes (3 vídeos)
http://postgresql.org.br/VideoAulas

TargetTrus (Porto Alegre)
http://www.targettrust.com/pls/portal/page0030.CURSOS?p_tecnologia=5


39) Banco corrompido

Muito bem. Caso ainda esteja com o problema, converta o arquivo de backup para o modo texto, usando o pg_restore sem especificar o banco de dados, mas um arquivo, por exemplo :

 pg_restpres -F c [arquivo de backup] > novo_arquivo.sql

40) ENCONTRAR REGISTROS DUPLICADOS

SELECT DISTINCT cep FROM cep_tabela
WHERE cep IN (SELECT cep FROM cep_tabela AS Tmp GROUP BY cep,tipo,logradouro, bairro, municipio,uf HAVING Count(*) >1 ) ORDER BY cep;
(Adaptação de consulta gerada pelo assistente Encontrar duplicadas do Access).

Ou:
select count(*) as quantos, cep from cep_tabela group by cep having count(*) > 1;

REMOVER DUPLICADOS
Para tabelas criadas WITH OIDS:
DELETE FROM cep_tabela2 WHERE oid NOT IN
(SELECT min(oid) FROM cep_tabela2 GROUP BY cep, tipo, logradouro, bairro, municipio, uf);

Do exemplo 8.10 do manual em português do Brasil.

Ou:

Criando uma segunda tabela que conterá somente os registros exclusivos e ainda guarda uma cópia da tabela original:

CREATE TABLE cep_tabela2 AS SELECT cep, tipo, logradouro, bairro, municipio, uf FROM cep_tabela GROUP BY cep, tipo, logradouro, bairro, municipio, uf ORDER BY cep;

Caso não importe qual das duplicatas irá permanecer:
CREATE TABLE tab_temp AS SELECT DISTINCT * FROM tabela;
DROP tabela;
ALTER TABLE tab_temp RENAME TO tabela;
(Dica de Osvaldo Rosario Kussama na lista de PostgreSQL Brasil)


41) Retornar Registro Aleatório

    SELECT col
    FROM tab
    ORDER BY random()
    LIMIT 1;


42) Alterar o Tipo de Dados de um Campo

    BEGIN;
    ALTER TABLE tab ADD COLUMN new_col new_data_type;
    UPDATE tab SET new_col = CAST(old_col AS new_data_type);
    ALTER TABLE tab DROP COLUMN old_col;
    COMMIT;


43) Limites do PostgreSQL

What is the maximum size for a row, a table, and a database?

These are the limits:

    Maximum size for a database?    unlimited (32 TB databases exist)
    Maximum size for a table?    32 TB
    Maximum size for a row?    400 GB
    Maximum size for a field?    1 GB
    Maximum number of rows in a table?    unlimited
    Maximum number of columns in a table?    250-1600 depending on column types
    Maximum number of indexes on a table?    unlimited

Fonte da 41, 42 e 43: FAQs do PostgreSQL: http://www.postgresql.org/docs/faqs.FAQ.html


44) Qual o espaço em disco necessário para armazenar arquivos textos

A PostgreSQL database may require up to five times the disk space to store data from a text file.

As an example, consider a file of 100,000 lines with an integer and text description on each line. Suppose the text string avergages twenty bytes in length. The flat file would be 2.8 MB. The size of the PostgreSQL database file containing this data can be estimated as 5.2 MB:

    24 bytes: each row header (approximate)
    24 bytes: one int field and one text field
   + 4 bytes: pointer on page to tuple
   ----------------------------------------
    52 bytes per row

   The data page size in PostgreSQL is 8192 bytes (8 KB), so:

   8192 bytes per page
   -------------------   =  158 rows per database page (rounded down)
     52 bytes per row

   100000 data rows
   --------------------  =  633 database pages (rounded up)
      158 rows per page

633 database pages * 8192 bytes per page  =  5,185,536 bytes (5.2 MB)

Indexes do not require as much overhead, but do contain the data that is being indexed, so they can be large also.

NULLs are stored as bitmaps, so they use very little space.


45) Como saber se o conteúdo de um campo é NULL?

   SELECT *
   FROM tab
   WHERE col IS NULL;

To concatentate with possible NULLs, use COALESCE(), like this:

   SELECT COALESCE(col1, '') || COALESCE(col2, '')
   FROM tab

To sort by the NULL status, use the IS NULL  and IS NOT NULL modifiers in your ORDER BY clause. Things that are true will sort higher than things that are false, so the following will put NULL entries at the top of the resulting list:

   SELECT *
   FROM tab
   ORDER BY (col IS NOT NULL)


46) Saber a versão atual do PostgreSQL

SELECT version();


47) Criar campo com time como valor default:

CREATE TABLE test (x int, modtime TIMESTAMP DEFAULT CURRENT_TIMESTAMP );


48) Retornando Números para Like

select cont_codi, cont_desc
 from conta
 where cont_codi like '%1%'

Converte o campo para string. Isso ocorre porque não é feito o cast
automatico.
select cont_codi, cont_desc
from conta
where CAST(cont_codi as STRING) like '%1%'

Evandro

ou

Utilize cast explícito.
cont_codi::text like '%1%'

Osvaldo

O Operador LIKE é utilizado para STRINGS [1]!
Faça um CAST para TEXT;

SELECT  '1%' like 123456::text

[1]
trisso-> \do ~~
 pg_catalog | ~~   | bytea                        | bytea
        | boolean         | matches LIKE expression
 pg_catalog | ~~   | character                    | text
        | boolean         | matches LIKE expression
 pg_catalog | ~~   | name                         | text
        | boolean         | matches LIKE expression
 pg_catalog | ~~   | text                         | text
        | boolean         | matches LIKE expression

Thiago Risso


49) Encontrar Tabela em Banco, retornando esquema e tabela

select schemaname, tablename from pg_tables
    where schemaname not like 'pg_%'
    and schemaname not like 'information_schema'
    and tablename='estados';


50) Servidor lento

1900MiB, imagino.

As razões mais comuns para tal comportamento na minha experiência são
programas PL/SQL trabalhando registro-a-registro em vez de usarem
operadores de conjunto; uso de espaço de troca de memória virtual;
fragmentação de objetos em disco; mau uso dos caches.  Há outras,
essas são as mais comuns.

Sem mais informações, impossível ajudar.  Parece o tipo de situação
que requereria um consultor, se o objetivo for a solução mais rápida
possível.   
Leandro


51) Como posso fazer par limitar um espaço de utilização do banco de
> dados? Por exemplo, quero dar para cada usuário o tamanho de 3MB de
> banco de dados, como é que faço este tipo de limitação?

Só conheço um jeito efetivo para isso: Criar TABLESPACES em partições
específicas para cada usuário. Se você tiver muitos usuários, melhor
usar LVM. Cada usuário só poderá criar objetos no tablespace que ele
tem permissão. A tablespace terá o espaço equivalente ao da partição
onde ela se encontra. Se você utilizar XFS, poderá esticar o tamanho
das partições on-the-fly, mas não poderá diminuir as partições. Se
criar com EXT3 poderá aumentar e diminuir a partição, mas terá de
desmontar ela para realizar a operação.
Fábio Telles


52) Gostaria que retornassem TODAS as datas, e nas que não teve saída, retornasse 0 no valor

select * from tabela where data between 2008-06-01 and 2008-06-05

Eu estou fazendo um SELECT das minhas saídas, por exemplo: SELECT data,
sum(valor) FROM saidas GROUP BY data....
Porém nas datas que não teve saída, ele não me retorna nada, eu gostaria que
retornassem TODAS as datas, e nas que não teve saída, retornasse 0 no
valor....

SELECT (inicio + i)::date   FROM generate_series(0, fim - inicio) i;

Onde início e fim são suas datas. Se desejar uma função tente esta:

CREATE OR REPLACE FUNCTION gen_datas(inicio date, fim date)
RETURNS SETOF date AS $$
 SELECT $1 + i
   FROM generate_series(0, $2 - $1) i;
$$ LANGUAGE SQL IMMUTABLE;

Osvaldo

Usei esta consulta para um problema semelhante:

SELECT s."Data", sum(coalesce(tab_data.valor,0)) AS "Valor"
FROM gen_datas(('2003-12-10'::date - '1
month'::interval)::date,'2003-12-10'::date) AS s("Data")
     LEFT OUTER JOIN tab_data
                  ON s."Data" = tab_data.data
GROUP BY s."Data"
ORDER BY s."Data" ASC;

A função gen_datas é a da outra mensagem enviada anteriormente.

Osvaldo


53) Verificar se Campo Existe (Catálogo)

Você pode acessar as tabelas do catalogo e verificar se o campo existe.
Por exemplo:

 SELECT a.relname AS Tabela, b.attname AS Campo
 FROM pg_class a
 JOIN pg_attribute b ON (b.attrelid = a.relfilenode)
 WHERE  b.attstattarget = -1 AND
        a.relname = <TABELA> AND  b.attname = <CAMPO>;
 IF NOT FOUND THEN
   **** existe o campo
 ELSE
   **** não existe o campo
 END IF;


54) Eu gostaria de fazer um select que entre os campos especificados tenha
outro select. Até ai tudo bem, mas preciso filtar esse select no campo
com um valor do outro select.
Exemplo:

SELECT campo1, (SELECT campoX FROM tb WHERE campo = campo1 LIMIT 1) as campo2
FROM tb2

O problema é que esse campo1 do WHERE do segundo select é o mesmo
campo1 da lista do primeiro select. Como especifico isso?

SELECT campo1, x.campox as campo2
FROM tb2 as a
LEFT JOIN (SELECT campoX FROM tb WHERE campo = campo1 LIMIT 1) as x on (a.campo1 = x.campo1)
Rúben Lício

SELECT tb2.campo1,
       (SELECT campoX FROM tb
         WHERE tb.campo = tb2.campo1 LIMIT 1) as campo2
FROM tb2;
Osvaldo

Você pode usar a seguinte sintaxe:

SELECT a.Campo1, (SELECT CampoX FROM tb WHERE campo = a.Campo1 LIMIT 1) as Campo2 FROM tb2 a;
Willian Jhonnes L. dos Santos


55) Saber a consulta em execução de um PID

select procpid,
      usename,
      datname,
      current_query,
      client_addr || ':' || client_port
from   pg_stat_activity
where  procpid = 23160;


56) Select em campo

SELECT a.idfunc,a.nome,a.cpf,a.rg,b.setor,c.nome,c.cidade,
(select f.descricao from funcao f join atividades g on (f.idfuncao = g.idatividade) where g.idfunc = a.idfunc order by g.datainicial desc limit 1)
FROM....
 
Esta sentença retorna a ultima funcao registrada do funcionario, entre outras informacoes.
--Paulo
 

Comentários
Adicionar Pesquisar
Escrever comentário
Nome:
Email:
 
Website:
Título:
UBBCode:
[b] [i] [u] [url] [quote] [code] [img] 
 
 
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch:
:(:shock::X:side::):P:unsure::woohoo::huh::whistle:;):s
:!::?::idea::arrow:
 
Please input the anti-spam code that you can read in the image.

3.25 Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved."

 
< Anterior   Próximo >
© 2008 PostgreSQL - Curso Online
Joomla! is Free Software released under the GNU/GPL License.
Design by DeiseHost.Com