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

554 visualizações

Publicada em

Palestra ministrada no PGBR 2015 na Uniritter em Porto Alegre, RS, sobre curiosidades, funcionalidades e características do PostgreSQL que são interesantes e que valem à pena conhecer. Esta palestra também foi ministrada no PGDAY Curitiba, em Setembro de 2015.

Publicada em: Dados e análise
0 comentários
2 gostaram
Estatísticas
Notas
  • Seja o primeiro a comentar

Sem downloads
Visualizações
Visualizações totais
554
No SlideShare
0
A partir de incorporações
0
Número de incorporações
46
Ações
Compartilhamentos
0
Downloads
8
Comentários
0
Gostaram
2
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

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

  1. 1. Curiosidades que você (talvez) não sabia e se sabia … Dickson S. Guedes @guediz PGBR 2015 - Porto Alegre, RS
  2. 2. O aninhador frenético
  3. 3. Problema SELECT..., CASEWHENsobrenomeISNULL THENnome WHENsobrenomeISNOTNULL THENsobrenome||','||nome END FROM...
  4. 4. Solução SELECT..., COALESCE(sobrenome||',','')||nome FROM...
  5. 5. O aninhador frenético II
  6. 6. Problema SELECT..., CASEWHENCOALESCE(endereco,'')<>'' THENCASEWHENCOALESCE( COALESCE(endereco,'')|| ''|| COALESCE(bairro,'') )<>'' THENendereco||''||bairro ELSECOALESCE(cidade,'') END ELSECOALESCE(cidade,'SEMCIDADE') END FROM... LEFTJOIN... LEFTJOIN...
  7. 7. Possível solução SELECT..., COALESCE(endereco||''||bairro,cidade,'SEMCIDADE '), FROM... LEFTJOIN... LEFTJOIN...
  8. 8. Opa! Três parâmetros? SELECT..., COALESCE(endereco||''||bairro,cidade,'SEMCIDADE '), ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^ ^^^^^^^^^^ FROM... LEFTJOIN... LEFTJOIN...
  9. 9. 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...
  10. 10. Como isso é possível?
  11. 11. 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)
  12. 12. Parâmetros! Não é para passar um ARRAY não! SELECTmenor_de_todos(ARRAY[10,11,12,30,-20,-30])asme nor; ^^^^^^ `--assimdaruim
  13. 13. O esbanjador de SELECTs
  14. 14. 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') ;
  15. 15. ai você vê isso … SELECT(SELECTCOUNT(*)FROMchequeWHEREsituacao='compen sado')astotal_compensados, (SELECTCOUNT(*)FROMchequeWHEREsituacao='devolv ido') astotal_devolvidos, (SELECTCOUNT(*)FROMchequeWHEREsituacao='voador ') astotal_voadores ;
  16. 16. 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;
  17. 17. 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;
  18. 18. 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
  19. 19. Outros CASTs que funcionam SELECTtext(1); =>'1' SELECTdate'2014-01-01';=>'2014-01-01' SELECTnumeric'1';=>1 SELECTint4'100000000000000';=>outofrange SELECTint8'100000000000000';=>100000000000000
  20. 20. 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
  21. 21. Mas qual é "o" problema? todos os cheque acima de R$ 1.000,00 foram compensados? algum cheque abaixo de R$ 800,00 foi devolvido?
  22. 22. 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;
  23. 23. O explorador do desconhecido
  24. 24. NULL e a aritimética SELECTNULL=NULL; SELECTNULL>NULL; SELECTNULL<NULL;
  25. 25. NULL e a aritimética SELECTNULL=NULL;=>NULL SELECTNULL>NULL;=>NULL SELECTNULL<NULL;=>NULL
  26. 26. O que é NULL? SELECTNULLISNULL; =>true SELECTNULLISDISTINCTFROMNULL; =>false SELECTNULLISNOTDISTINCTFROMNULL; =>true SELECT1ISNULL; =>false SELECT1ISDISTINCTFROMNULL; =>true SELECT1ISNOTDISTINCTFROMNULL; =>false
  27. 27. TESTE DE ATENÇÃO!
  28. 28. Lembram da função menor_de_todos? SELECTmenor_de_todos(10,11,12,30,-20,-30)asmenor; menor -------- -30 (1row)
  29. 29. E se eu passar NULL? SELECTmenor_de_todos(10,11,12,NULL,-20,-30)asmenor; menor -------- ????? (1row)
  30. 30. -30 SELECTmenor_de_todos(10,11,12,NULL,-20,-30)asmenor; menor -------- -30 (1row)
  31. 31. menor_de_todos(...)usa a função min(...)que é uma função de agregação
  32. 32. funções de agregação ignoram NULL
  33. 33. O fabricador de registros
  34. 34. Um registro! SELECTROW(10,'JOAO',1500.50);
  35. 35. 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); =>?????
  36. 36. NULL!
  37. 37. Lembra o INSERT? INSERTINTO...VALUES(1,'JOAO',1500.10);
  38. 38. Pensa no VALUES! /*INSERTINTO...*/VALUES(1,'JOAO',1500.10); --FUNCI ONA!
  39. 39. 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), ;
  40. 40. O masoquista escrivinhador
  41. 41. SIM! Isto funciona; pode testar! SELECT1OPERATOR(pg_catalog.+)2 =1+2; =>true
  42. 42. 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
  43. 43. 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
  44. 44. Logo … SELECT1+1=2; SELECTint4pl(1,1)=2;
  45. 45. Para o infinito, e além
  46. 46. 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
  47. 47. 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'
  48. 48. 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'
  49. 49. NaNaNaNaNaNaNaN SELECT'NaN'::numeric+1; => 'NaN'
  50. 50. Já que estamos falando de datas
  51. 51. já viram isso? SELECT... CAST( CAST(anoAStext)||'-'|| CAST(mesAStext)||'-'|| CAST(diaAStext), ASdate) ), ... FROM...;
  52. 52. ou isso? SELECT... FROM... WHERE ... data_nascimento=CAST( CAST(anoAStext)||'-'|| CAST(mesAStext)||'-'|| CAST(diaAStext), ASdate) ) ; ;
  53. 53. que se faça a data SELECT..., make_date(ano,mes,dia), ... FROM...;
  54. 54. Algumas fontes são True Type
  55. 55. SERIAL NÃO!
  56. 56. São equivalentes CREATETABLEtabela( colunaSERIAL ); OU CREATESEQUENCEtabela_coluna_seq; CREATETABLEtabela( colunaintegerNOTNULLDEFAULTnextval('tabela_coluna_s eq') ); ALTERSEQUENCEtabela_coluna_seqOWNEDBYtabela.coluna;
  57. 57. Chamando funções
  58. 58. Uma função pode ser chamada assim SELECTupper('nome'); upper ------- NOME (1registro)
  59. 59. Uma função pode ser chamada assim também SELECT*FROMupper('nome'); upper ------- NOME (1registro)
  60. 60. E também pode ser assim SELECT ('nome').upper; upper ------- NOME (1registro)
  61. 61. Uma tabela comum, uma consulta comum CREATETABLEpessoa(nometext,data_nascimentodate); INSERTINTOpessoaVALUES('JOAO',now()-interval'35years '); SELECTp.nome,p.data_nascimentoFROMpessoap;
  62. 62. e uma consulta não tanto comum SELECTnome(p),data_nascimento(p)frompessoap; nome|data_nascimento ------+----------------- JOAO|1980-09-18 (1registro)
  63. 63. 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
  64. 64. PSQL
  65. 65. 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;
  66. 66. 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;
  67. 67. Talvez num futuro isso funcione SELECT...FROMbanco.esquema.tabela;
  68. 68. Bom, não é só isso…
  69. 69. ainda tem muito mais coisas…
  70. 70. Leia o manual http://www.postgresql.org/docs/manuals/
  71. 71. Visite o IRC, é divertido …
  72. 72. 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);
  73. 73. 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

×