SlideShare ist ein Scribd-Unternehmen logo
1 von 86
Downloaden Sie, um offline zu lesen
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...
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?
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
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;
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
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!
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),
;
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;
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'
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...;
Algumas fontes são True Type
SERIAL NÃO!
São equivalentes
CREATETABLEtabela(
colunaSERIAL
);
OU
CREATESEQUENCEtabela_coluna_seq;
CREATETABLEtabela(
colunaintegerNOTNULLDEFAULTnextval('tabela_coluna_s
eq')
);
ALTERSEQUENCEtabela_coluna_seqOWNEDBYtabela.coluna;
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
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

Weitere ähnliche Inhalte

Mehr von Dickson S. Guedes

Conhecendo Postgresql.- ENECOMP 2009
Conhecendo Postgresql.- ENECOMP 2009Conhecendo Postgresql.- ENECOMP 2009
Conhecendo Postgresql.- ENECOMP 2009
Dickson S. Guedes
 
Minicurso Postgresql - Enecomp 2009
Minicurso Postgresql - Enecomp 2009Minicurso Postgresql - Enecomp 2009
Minicurso Postgresql - Enecomp 2009
Dickson S. Guedes
 

Mehr von Dickson S. Guedes (20)

Ganhando tempo automatizando com SQL
Ganhando tempo automatizando com SQLGanhando tempo automatizando com SQL
Ganhando tempo automatizando com SQL
 
O mínimo necessário que você precisa conhecer sobre computação quântica
O mínimo necessário que você precisa conhecer sobre computação quânticaO mínimo necessário que você precisa conhecer sobre computação quântica
O mínimo necessário que você precisa conhecer sobre computação quântica
 
Porque aprender várias linguagens me tornou um DBA (e desenvolvedor) melhor
Porque aprender várias linguagens me tornou um DBA (e desenvolvedor) melhorPorque aprender várias linguagens me tornou um DBA (e desenvolvedor) melhor
Porque aprender várias linguagens me tornou um DBA (e desenvolvedor) melhor
 
Pattern matching - O que é? Onde vive? Do que se alimenta? Como se reproduz?
Pattern matching - O que é? Onde vive? Do que se alimenta? Como se reproduz?Pattern matching - O que é? Onde vive? Do que se alimenta? Como se reproduz?
Pattern matching - O que é? Onde vive? Do que se alimenta? Como se reproduz?
 
Primeiros passos machine learning PostgreSQL
Primeiros passos machine learning PostgreSQLPrimeiros passos machine learning PostgreSQL
Primeiros passos machine learning PostgreSQL
 
Dicas de sobrevivência de um DBA sem mouse
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
 
Destistificando o EXPLAIN
Destistificando o EXPLAIN Destistificando o EXPLAIN
Destistificando o EXPLAIN
 
Falando "Postgrês"
Falando "Postgrês"Falando "Postgrês"
Falando "Postgrês"
 
Se meu elefante falasse
Se meu elefante falasseSe meu elefante falasse
Se meu elefante falasse
 
O Elefante Poliglota
O Elefante PoliglotaO Elefante Poliglota
O Elefante Poliglota
 
Como encontrar uma agulha num palheiro de logs
Como encontrar uma agulha num palheiro de logsComo encontrar uma agulha num palheiro de logs
Como encontrar uma agulha num palheiro de logs
 
Como encontrar uma agulha no palheiro de logs do PostgreSQL
Como encontrar uma agulha no palheiro de logs do PostgreSQLComo encontrar uma agulha no palheiro de logs do PostgreSQL
Como encontrar uma agulha no palheiro de logs do PostgreSQL
 
Gerenciando múltiplas versões do PostgreSQL com pgvm
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
 
PGXN - Como distribuir suas extensões com o PostgreSQL
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
 
Pgxn.pgday
Pgxn.pgdayPgxn.pgday
Pgxn.pgday
 
Estripando o Elefante - (Trabalhando com extensões no PostgreSQL)
Estripando o Elefante - (Trabalhando com extensões no PostgreSQL)Estripando o Elefante - (Trabalhando com extensões no PostgreSQL)
Estripando o Elefante - (Trabalhando com extensões no PostgreSQL)
 
Plante uma árvore, escreva um livro, tenha um filho e contribua com software ...
Plante uma árvore, escreva um livro, tenha um filho e contribua com software ...Plante uma árvore, escreva um livro, tenha um filho e contribua com software ...
Plante uma árvore, escreva um livro, tenha um filho e contribua com software ...
 
Conhecendo Postgresql.- ENECOMP 2009
Conhecendo Postgresql.- ENECOMP 2009Conhecendo Postgresql.- ENECOMP 2009
Conhecendo Postgresql.- ENECOMP 2009
 
Minicurso Postgresql - Enecomp 2009
Minicurso Postgresql - Enecomp 2009Minicurso Postgresql - Enecomp 2009
Minicurso Postgresql - Enecomp 2009
 
Testes unitarios no PostgreSQL com pgTAP
Testes unitarios no PostgreSQL com pgTAPTestes unitarios no PostgreSQL com pgTAP
Testes unitarios no PostgreSQL com pgTAP
 

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