Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar

Dickson S. Guedes
Dickson S. GuedesDatabase Administrator em Confesol - Confederação Nacional das Cooperativas de Crédito
Curiosidades que
você (talvez) não
sabia e se sabia …
Dickson S. Guedes
@guediz
PGBR 2015 - Porto Alegre, RS
O aninhador frenético
Problema
SELECT...,
CASEWHENsobrenomeISNULL
THENnome
WHENsobrenomeISNOTNULL
THENsobrenome||','||nome
END
FROM...
Solução
SELECT...,
COALESCE(sobrenome||',','')||nome
FROM...
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
O aninhador frenético II
Problema
SELECT...,
CASEWHENCOALESCE(endereco,'')<>''
THENCASEWHENCOALESCE(
COALESCE(endereco,'')||
''||
COALESCE(bairro,'')
)<>''
THENendereco||''||bairro
ELSECOALESCE(cidade,'')
END
ELSECOALESCE(cidade,'SEMCIDADE')
END
FROM...
LEFTJOIN...
LEFTJOIN...
Possível solução
SELECT...,
COALESCE(endereco||''||bairro,cidade,'SEMCIDADE
'),
FROM...
LEFTJOIN...
LEFTJOIN...
Opa! Três parâmetros?
SELECT...,
COALESCE(endereco||''||bairro,cidade,'SEMCIDADE
'),
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^ ^^^^^^^^^^
FROM...
LEFTJOIN...
LEFTJOIN...
Qual é o resultado disto?
SELECT...,
COALESCE(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NU
LL,'SEMVALOR'),
COALESCE(NULL,NULL,NULL,NULL,NULL,NULL,NULL,'S
EMVALOR'),
COALESCE(NULL,NULL,NULL,NULL,NULL,NULL,'SEMVAL
OR'),
COALESCE(NULL,NULL,NULL,NULL,NULL,'SEMVALOR'),
COALESCE(NULL,NULL,NULL,NULL,'SEMVALOR'),
COALESCE(NULL,NULL,NULL,'SEMVALOR'),
COALESCE(NULL,NULL,'SEMVALOR'),
COALESCE(NULL,'SEMVALOR'),
...
FROM...
Como isso é possível?
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
VARIADIC
CREATEFUNCTIONmenor_de_todos(VARIADICvaloresnumeric[])
RETURNSnumericAS
$$
SELECTmin($1[valor])FROMgenerate_subscripts($1,1)g(
valor);
$$
LANGUAGESQL;
SELECTmenor_de_todos(10,11,12,30,-20,-30)asmenor;
menor
--------
-30
(1row)
Parâmetros! Não é para passar um ARRAY
não!
SELECTmenor_de_todos(ARRAY[10,11,12,30,-20,-30])asme
nor;
^^^^^^
`--assimdaruim
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
O esbanjador de SELECTs
Tudo bunitinho
CREATETYPEsituacao_chequeAS
ENUM('compensado','devolvido','sustado','voador')
;
CREATETABLEcheque(numerointegernotnull,
valor integernotnull,
situacaosituacao_cheque);
INSERTINTOchequeVALUES(1,100.00,NULL);
INSERTINTOcheque
VALUES(2, 500.00,'compensado'),(3,1000.00,'devolvi
do'),
(4, 900.00,'devolvido'),(5,3000.00,'compensa
do'),
(6, 145.00,'sustado'),(7, 45.00,'voador'),
(8, 66.00,'voador'),(9, 96.00,'sustado'),
(10, 45.00,'sustado')
;
ai você vê isso …
SELECT(SELECTCOUNT(*)FROMchequeWHEREsituacao='compen
sado')astotal_compensados,
(SELECTCOUNT(*)FROMchequeWHEREsituacao='devolv
ido') astotal_devolvidos,
(SELECTCOUNT(*)FROMchequeWHEREsituacao='voador
') astotal_voadores
;
mas esperava isso …
SELECTSUM(CASEWHENsituacao='compensado'THEN1ELSE0E
ND)astotal_compensados,
SUM(CASEWHENsituacao='devolvido' THEN1ELSE0E
ND)astotal_devolvidos,
SUM(CASEWHENsituacao='voador' THEN1ELSE0E
ND)astotal_voadores
FROMcheque;
Ei! isso também é possível
SELECTSUM(int4(situacao='compensado'))astotal_compe
nsados,
SUM(int4(situacao='devolvido' ))astotal_devol
vidos,
SUM(int4(situacao='voador' ))astotal_voado
res
FROMcheque;
CAST
CAST('a'='b'ASint4)=0
int4('a'='b') =0
CAST('a'='a'ASint4)=1
int4('a'='a') =1
int4('B'='B')+int4('A'='A') =2
Outros CASTs que funcionam
SELECTtext(1); =>'1'
SELECTdate'2014-01-01';=>'2014-01-01'
SELECTnumeric'1';=>1
SELECTint4'100000000000000';=>outofrange
SELECTint8'100000000000000';=>100000000000000
Então da para fazer algo assim
SELECTSUM(int4(situacao='compensado'))astotal_compe
nsados,
SUM(int4(situacao='devolvido' ))astotal_devol
vidos,
SUM(int4(situacao='voador' ))astotal_voado
res
^^^^^^^^^^^^^,^^^^^^^^^^
FROMcheque; `~~~~~~~~~~´~~~~~transformabooleanparainte
ger
Mas qual é "o" problema?
todos os cheque acima de R$ 1.000,00 foram compensados?
algum cheque abaixo de R$ 800,00 foi devolvido?
Declarativo e explicito MELHOR QUE
implícito.
SELECT
BOOL_AND(situacao='compensado')FILTER(WHEREvalor>
1000)as"todos>1000foramcompensados?",
BOOL_OR(situacao='devolvido') FILTER(WHEREvalor<
800)as"algum<800foidevolvido",
EVERY(situacao='voador') as"algumchequevoado
r?"
FROMcheque;
SELECTbool_and(situacao='compensado')as"todoscompensad
osacimadeR$1.000"
FROMcheque
WHEREvalor>1000;
SELECTbool_or(situacao='devolvido')as"Algumcheque<80
0devolvido?"
FROMcheque
WHEREvalor<800;
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
O explorador do desconhecido
NULL e a aritimética
SELECTNULL=NULL;
SELECTNULL>NULL;
SELECTNULL<NULL;
NULL e a aritimética
SELECTNULL=NULL;=>NULL
SELECTNULL>NULL;=>NULL
SELECTNULL<NULL;=>NULL
O que é NULL?
SELECTNULLISNULL; =>true
SELECTNULLISDISTINCTFROMNULL; =>false
SELECTNULLISNOTDISTINCTFROMNULL; =>true
SELECT1ISNULL; =>false
SELECT1ISDISTINCTFROMNULL; =>true
SELECT1ISNOTDISTINCTFROMNULL; =>false
TESTE DE ATENÇÃO!
Lembram da função menor_de_todos?
SELECTmenor_de_todos(10,11,12,30,-20,-30)asmenor;
menor
--------
-30
(1row)
E se eu passar NULL?
SELECTmenor_de_todos(10,11,12,NULL,-20,-30)asmenor;
menor
--------
?????
(1row)
-30
SELECTmenor_de_todos(10,11,12,NULL,-20,-30)asmenor;
menor
--------
-30
(1row)
menor_de_todos(...)usa a função
min(...)que é uma função de agregação
funções de agregação ignoram NULL
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
O fabricador de registros
Um registro!
SELECTROW(10,'JOAO',1500.50);
Dois registros!
SELECTROW(10,'JOAO',1500.50)=ROW(10,'JOAO',1500.50);
=>true
SELECTROW(10,'JOAO',1500.50)>ROW(9,'PEDRO',500.50);
=>true
SELECTROW(1,'MARIA',1000.10)>ROW(1,'MARIA',1000.11);
=>false
SELECTROW(100,'JOANA',10.60)<ROW(100,'JOANA',NULL);
=>?????
NULL!
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
Lembra o INSERT?
INSERTINTO...VALUES(1,'JOAO',1500.10);
Pensa no VALUES!
/*INSERTINTO...*/VALUES(1,'JOAO',1500.10); --FUNCI
ONA!
VALUES é um comando sozinho!
INSERTINTO...SELECTcodigo,nome,valorFROMtabela_tempo
raria;
INSERTINTO...VALUES(1,'JOAO',1500.10);
VALUES
(1,'...',1500.10),
(2,'...', 500.00),
(3,'...', 100.00),
(4,'...', 50.50),
(5,'...',3500.00),
;
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
O masoquista escrivinhador
SIM! Isto funciona; pode testar!
SELECT1OPERATOR(pg_catalog.+)2 =1+2; =>true
Operadores são funções disfarçadas
SELECT1+1;
^^^__integernadireita
||____operador'+'
|______integernaesquerda
SELECToprname,
oprcode,
CAST(oprleftASregtype), --23éinteger
CAST(oprrightASregtype) --23éinteger
FROMpg_operator
WHEREoprname='+'ANDoprleft=23ANDoprright=23;
oprname|oprcode|oprleft|oprright
---------+---------+---------+----------
+ |int4pl |integer|integer
Operadores são funções disfarçadas
SELECT1+1;
^^^__integernadireita
||____operador'+'
|______integernaesquerda
SELECToprname,
oprcode,
CAST(oprleftASregtype), --23éinteger
CAST(oprrightASregtype) --23éinteger
FROMpg_operator
WHERE(oprname,oprleft,oprright)=('+',23,23);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
`-esteéumoutrojeitodeescrever
oWHEREsemosANDeobtero
mesmoresultado...
oprname|oprcode|oprleft|oprright
---------+---------+---------+----------
+ |int4pl |integer|integer
^^^^^^.___opostgreschamaráestafunçãopara
somarintegercominteger
Logo …
SELECT1+1=2;
SELECTint4pl(1,1)=2;
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
Para o infinito, e além
Sim, tudo isso é possível
SELECT'+Infinity'::float>999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
999999999999999999999999999999999999999999; =>true
SELECT'-Infinity'::float<999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999
999999999999999999999999999999999999999999; =>true
Infinito para datas, também, claro!
SELECT'Infinity'::date>current_date;
=>true
INSERTINTOelemento(nome,validade)VALUES('urânio','Infi
nity');
istoéumdate_.^^^^^^^^
1
SELECT'today'::interval=current_date;
=>true
SELECT'yesterday'::date='today'::date-interval'1day';
=>true
SELECT'tomorroy'::date='today'::date+interval'1day';
=>true
SELECTcurrent_date+'allballs'::time;
=>'2015-09-1800:00:00'
E tudo pode ser rescrito como …
SELECTdate'Infinity'>current_date;
=>true
INSERTINTOelemento(nome,validade)VALUES('urânio','Infi
nity');
istoéumdate_.^^^^^^^^
SELECTinterval'today'=current_date;
=>true
SELECTdate'yesterday'=date'today'-interval'1day';
=>true
SELECTdate'tomorroy'=date'today'+interval'1day';
=>true
SELECTcurrent_date+time'allballs';
=>'2015-09-1800:00:00'
NaNaNaNaNaNaNaN
SELECT'NaN'::numeric+1; => 'NaN'
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
Já que estamos falando de
datas
já viram isso?
SELECT...
CAST(
CAST(anoAStext)||'-'||
CAST(mesAStext)||'-'||
CAST(diaAStext),
ASdate)
),
...
FROM...;
ou isso?
SELECT...
FROM...
WHERE
...
data_nascimento=CAST(
CAST(anoAStext)||'-'||
CAST(mesAStext)||'-'||
CAST(diaAStext),
ASdate)
)
;
;
que se faça a data
SELECT...,
make_date(ano,mes,dia),
...
FROM...;
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
Algumas fontes são True Type
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
SERIAL NÃO!
São equivalentes
CREATETABLEtabela(
colunaSERIAL
);
OU
CREATESEQUENCEtabela_coluna_seq;
CREATETABLEtabela(
colunaintegerNOTNULLDEFAULTnextval('tabela_coluna_s
eq')
);
ALTERSEQUENCEtabela_coluna_seqOWNEDBYtabela.coluna;
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
Chamando funções
Uma função pode ser chamada assim
SELECTupper('nome');
upper
-------
NOME
(1registro)
Uma função pode ser chamada assim
também
SELECT*FROMupper('nome');
upper
-------
NOME
(1registro)
E também pode ser assim
SELECT ('nome').upper;
upper
-------
NOME
(1registro)
Uma tabela comum, uma consulta comum
CREATETABLEpessoa(nometext,data_nascimentodate);
INSERTINTOpessoaVALUES('JOAO',now()-interval'35years
');
SELECTp.nome,p.data_nascimentoFROMpessoap;
e uma consulta não tanto comum
SELECTnome(p),data_nascimento(p)frompessoap;
nome|data_nascimento
------+-----------------
JOAO|1980-09-18
(1registro)
Mas uma função também pode ter seu
retorno como uma tabela
CREATEFUNCTIONduplica(INint,OUTvalor_originalint,OUT
valor_convertidotext)
AS
$$
SELECT$1,CAST($1AStext)||'ehtexto'
$$
LANGUAGESQL;
SELECT*FROMduplica(42);
valor_original|valor_convertido
----------------+------------------
42|42ehtexto
(1registro)
Tempo:1,684ms
Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar
PSQL
isso ajuda
setv_nome'JOAO'
setv_idade18
connectdesenvusuario192.168.1.15432
SELECT*FROMpessoaWHEREnome=:v_nomeANDidade>:v_ida
deg
connecttesteusuario192.168.1.25432
SELECT*FROMpessoaWHEREnome=:v_nomeANDidade>:v_ida
de;
isso também ajuda
setv_cpf1234567890
connectdesenvusuario192.168.1.15432
SELECTnome asv_nome,
idadeasv_idade
FROMpessoa
WHEREcpf=:v_cpfgset
connecttesteusuario192.168.1.25432
SELECT*
FROMpessoa
WHEREnome=:v_nomeANDidade>:v_idade;
Talvez num futuro isso funcione
SELECT...FROMbanco.esquema.tabela;
Bom, não é só isso…
ainda tem muito mais coisas…
Leia o manual
http://www.postgresql.org/docs/manuals/
Visite o IRC, é divertido …
Numa terça-feira monótona, Andrew
Gierth (a.k.a. RhodiumToad) escreveu isto
SELECToid,lowrite(lo_open(oid,131072),a)
FROM(VALUES(lo_create(0)))v(oid),
generate_bytea()asx(a)
;
--(notetheoidreturned)
lo_export828133392'image.png'
SELECTlo_unlink(828133392);
e é isso, obrigado! :)
Conferencia Brasileira de PostgreSQL
18 a 20 de Novembro
email: guedes@guedesoft.net
github:
twitter:
http://pgbr.postgresql.org.br/
http://github.com/guedes
http://twitter.com/guediz
1 de 86

Recomendados

Introdução a python   módulo bIntrodução a python   módulo b
Introdução a python módulo bJader Gabriel
366 visualizações43 slides
Perguntas e Respostas de HistóriaPerguntas e Respostas de História
Perguntas e Respostas de Históriaguesta2f5edf
41.6K visualizações35 slides
RESUMO DO EVANGELHO DE JOÃORESUMO DO EVANGELHO DE JOÃO
RESUMO DO EVANGELHO DE JOÃOAmor pela EBD
35.8K visualizações6 slides
Evangelho segundo JoaoEvangelho segundo Joao
Evangelho segundo JoaoMensagens Virtuais
5.2K visualizações16 slides

Mais conteúdo relacionado

Mais de Dickson S. Guedes(20)

Ganhando tempo automatizando com SQLGanhando tempo automatizando com SQL
Ganhando tempo automatizando com SQL
Dickson S. Guedes15 visualizações
Primeiros passos machine learning PostgreSQLPrimeiros passos machine learning PostgreSQL
Primeiros passos machine learning PostgreSQL
Dickson S. Guedes736 visualizações
Dicas de sobrevivência de um DBA sem mouseDicas de sobrevivência de um DBA sem mouse
Dicas de sobrevivência de um DBA sem mouse
Dickson S. Guedes270 visualizações
Destistificando o EXPLAIN Destistificando o EXPLAIN
Destistificando o EXPLAIN
Dickson S. Guedes260 visualizações
Falando "Postgrês"Falando "Postgrês"
Falando "Postgrês"
Dickson S. Guedes222 visualizações
Se meu elefante falasseSe meu elefante falasse
Se meu elefante falasse
Dickson S. Guedes692 visualizações
O Elefante PoliglotaO Elefante Poliglota
O Elefante Poliglota
Dickson S. Guedes727 visualizações
Como encontrar uma agulha num palheiro de logsComo encontrar uma agulha num palheiro de logs
Como encontrar uma agulha num palheiro de logs
Dickson S. Guedes651 visualizações
Gerenciando múltiplas versões do PostgreSQL com pgvmGerenciando múltiplas versões do PostgreSQL com pgvm
Gerenciando múltiplas versões do PostgreSQL com pgvm
Dickson S. Guedes624 visualizações
PGXN - Como distribuir suas extensões com o PostgreSQLPGXN - Como distribuir suas extensões com o PostgreSQL
PGXN - Como distribuir suas extensões com o PostgreSQL
Dickson S. Guedes385 visualizações
Pgxn.pgdayPgxn.pgday
Pgxn.pgday
Dickson S. Guedes253 visualizações
Conhecendo Postgresql.- ENECOMP 2009Conhecendo Postgresql.- ENECOMP 2009
Conhecendo Postgresql.- ENECOMP 2009
Dickson S. Guedes433 visualizações
Minicurso Postgresql - Enecomp 2009Minicurso Postgresql - Enecomp 2009
Minicurso Postgresql - Enecomp 2009
Dickson S. Guedes220 visualizações
Testes unitarios no PostgreSQL com pgTAPTestes unitarios no PostgreSQL com pgTAP
Testes unitarios no PostgreSQL com pgTAP
Dickson S. Guedes812 visualizações

Curiosidades que você (talvez) não sabia e se sabia vale a pena lembrar