Sunteți pe pagina 1din 22

1

RESUMO DO SQL NO POSTGRESQL E OUTRAS DICAS


Retirado da documentação oficial para a versão 8.0 traduzida por Halley Pacheco, encontrada em
http://pgdocptbr.sourceforge.net/pg80/ e também dos e-books: PostgreSQL Introduction and Concepts e Practical
PostgreSQL.
Compilação de Ribamar FS – ribamar.sousa@dnocs.gov.br.

ÍNDICE

1 - Criar Tabela - 2
2 - Excluir Tabelas - 2
3 - Alterando Estrutura de Tabelas - 2
4 - Inserindo Linhas em Tabelas - 2
5 - Consultar Tabelas - 3
6 - Sub-consulta -3
7 - Insert Usando Select - 4
8 - Garantir resultados consistentes utilizando DISTINCT e ORDER BY juntos - 4
9 - Junções entre tabelas - 4
10 - Consulta União Inner Join - 4
11 - Consulta União LEFT OUTER JOIN - 4
12 - Apelido (Alias) - 5
13 - Funções de Agregação - 5
14 - Cláusula HAVIN - 5
15 - Atualizações em Tabelas - 6
16 - Excluindo Registros de Tabelas - 6
17 - Deve-se tomar cuidado com comandos na forma - 6
18 - Visões (Views) - 6
19 - Chaves Estrangeiras - 6
20 - Tipos de dado - 7
21 - Tipos numéricos - 8
22 - Arredondamento em tipo numeric - 8
23 - Tipo Serial - 8
24 - Alteração da seqüência da coluna serial - 8
25 - Auto-Incremento no Postgresql (Tipo Serial) - 9
26 - Ajustando o Tipo de Data do Sistema GBD - 9
27 - Ajustando uma Faixa de Registros com LIMIT and OFFSET - 9
28 - Funções com Cadeias de Caracteres (Strings)
29 - Correspondência com Padrão - 9
30 - Funções de formatação de Tipos de Dados - 12
31 - Exemplos de utilização da função to_char - 13
32 - Funções para data e hora - 14
33 - A função date_part - 16
34 - date_trunc - 16
35 - Data e hora correntes - 16
36 - Utilização de INTERVAL - 17
37 - Número de dias entre duas datas - 17
38 - Obtenção do dia do mês - 17
39 - Utilização das funções para data e hora corrente - 17
40 - Somar dias e horas a uma data - 17
41 - Operadores para os tipos cidr e inet - 18
42 - Funções para os tipos cidr e inet - 18
43 - Funções de informação da sessão - 19
44 - Funções para administração do sistema - 19
45 - Conversão de Tipos - 20
46 - Dicas de Desempenho - 20
2

1 - Criar Tabela

CREATE TABLE clima (


cidade varchar(80) PRIMARY KEY NOT NULL, --chave primária
temp_min int, -- temperatura mínima
temp_max int, -- temperatura máxima
prcp real, -- precipitação
data date
);

O nome dos objetos (tabelas, consultas, etc) são case-insensitives, mas para tornar sensitive podemos delimitá-los com
aspas duplas, inclusive para reconhecer acentos.

2 - Excluir Tabelas

DROP nometabela;

3 - Alterando Estrutura de Tabelas

ALTER TABLE table ADD [ COLUMN ] column_name column_type;


ALTER TABLE books ADD publication date;
ALTER TABLE table ALTER [ COLUMN ] column_name { SET DEFAULT value | DROP DEFAULT };
ALTER TABLE books ALTER COLUMN id SET DEFAULT nextval('book_ids');
ALTER TABLE books RENAME TO literature;
ALTER TABLE table RENAME [ COLUMN ] column_name TO new_column_name;
ALTER TABLE daily_inventory RENAME COLUMN in_stock TO is_in_stock;
ALTER TABLE table ADD CONSTRAINT constraint_name constraint_definition;
ALTER TABLE editions ADD CONSTRAINT foreign_book FOREIGN KEY (book_id) REFERENCES books (id);
ALTER TABLE employees OWNER TO corwin;

4 - Inserindo Linhas em Tabelas

INSERT INTO clima VALUES ('São Francisco', 46, 50, 0.25, '1994-11-27');
INSERT INTO clima (cidade, temp_min, temp_max, prcp, data)
VALUES ('São Francisco', 43, 57, 0.0, '1994-11-29');

Também pode ser utilizado o comando COPY para carregar uma grande quantidade de dados a partir de arquivos
texto puro. Geralmente é mais rápido, porque o comando COPY é otimizado para esta finalidade, embora possua
menos flexibilidade que o comando INSERT. Para servir de exemplo:
COPY clima FROM '/home/user/clima.sql';

Para ficar mais claro, pode ser requisitado explicitamente o valor padrão da coluna individualmente, ou para toda a
linha:
INSERT INTO produtos (cod_prod, nome, preco) VALUES (1, 'Queijo', DEFAULT);
INSERT INTO produtos DEFAULT VALUES;
3

5 - Consultar Tabelas

SELECT cidade, temp_min, temp_max, prcp, data FROM clima;


SELECT cidade, (temp_max+temp_min)/2 AS temp_media, data FROM clima;
SELECT * FROM clima WHERE cidade = 'São Francisco' AND prcp > 0.0;
SELECT * FROM clima ORDER BY cidade, temp_min;

SELECT 3 * 4;
SELECT random();
SELECT now();
SELECT pi() * 3.14;

SINTAXE CORRETA E NESTA ORDEM


SELECT … WHERE … ORDER BY ou GROUP BY … LIMIT …

SELECT cidade, count(*) FROM clients GROUP BY cidade;

SELECT DISTINCT cidade FROM clients; //Trazer somente cidades distintas, sem repetição

SELECT * FROM clientes LIMIT 100 OFFSET 5; // Trazer 100 clientes iniciando do quinto, ou seja, 96

6 - Sub-consulta

SELECT 'test' AS test, id FROM (SELECT * FROM books) AS example_sub_query;

SELECT firstname,
state,
CASE
WHEN state = 'PA' THEN 'close'
WHEN state = 'NJ' OR state = 'MD' THEN 'far'
ELSE 'very far'
END AS distance
FROM friend;

Combinando Selects

test=> SELECT firstname


test-> FROM friend
test-> UNION
test-> SELECT lastname
test-> FROM friend
test-> ORDER BY 1;

test=> INSERT INTO terrestrial_animal (name) VALUES ('tiger');


INSERT 19122 1

test=> INSERT INTO aquatic_animal (name) VALUES ('swordfish');


INSERT 19123 1
4

SELECT name FROM customer WHERE customer_id NOT IN ( SELECT customer_id FROM salesorder );
name
------
(0 rows)
(Customers who have no orders)

7 - Insert Usando Select

SELECT firstname, lastname, city, state INTO newfriend FROM friend;

8 - Garantir resultados consistentes utilizando DISTINCT e ORDER BY juntos


SELECT DISTINCT cidade FROM clima ORDER BY cidade;

9 - Junções entre tabelas

SELECT * FROM clima, cidades WHERE cidade = nome;


SELECT cidade, temp_min, temp_max, prcp, data, localizacao
FROM clima, cidades WHERE cidade = nome;

Como todas as colunas possuem nomes diferentes, o analisador encontra automaticamente a tabela que a coluna
pertence, mas é um bom estilo qualificar completamente os nomes das colunas nas consultas de junção:
SELECT clima.cidade, clima.temp_min, clima.temp_max,
clima.prcp, clima.data, cidades.localizacao
FROM clima, cidades
WHERE cidades.nome = clima.cidade;

Exemplo: SELECT * FROM tabela1 INNER JOIN tabela2 ON campo_tab1 = campo_tab2

campo_tab1 e campo_tab2 são os campos-chave primária e/ou estrangeira.


INNER JOIN – Retorna apenas os registros que satisfizerem a condição (campo_tab1 = campo_tab2)
LEFT JOIN – Retorna todos os registros da tabela à esquerda, mesmo que na da direita não haja correspondente.
RIGHT JOIN - Retorna todos os registros da tabela à direita, mesmo que na da esquerda não haja correspondente.
Ver bom artigo sobre o assunto em: http://pgdocptbr.sourceforge.net/pg74/queries-table-expressions.html.

CONSULTAS ANINHADAS
SELECT região_nome FROM região WHERE região_id =
(SELECT região_id FROM vinharia WHERE vinharia_id =
(SELECT vinharia_id FROM vinho WHERE vinho_id =
17));

10 - Consulta União Inner Join

SELECT *
FROM clima INNER JOIN cidades ON (clima.cidade = cidades.nome);

11 - Consulta União LEFT OUTER JOIN

SELECT * FROM clima LEFT OUTER JOIN cidades ON (clima.cidade = cidades.nome);


cidade | temp_min | temp_max | prcp | data | nome | localizacao
-----------------+------------+---------------+-------+---------------+-----------------+------------
Hayward | 37 | 54 | | 1994-11-29 | |
São Francisco | 46 | 50 | 0.25 | 1994-11-27 | São Francisco | (-194,53)
São Francisco | 43 | 57 |0 | 1994-11-29 | São Francisco | (-194,53)

Existem também a junção externa direita (right outer join) e a junção externa completa (full outer join).
5

12 - Apelido (Alias)

A tabela clima teve seu nome mudado para C1 e C2, para permitir distinguir o lado esquerdo do lado direito da
junção. Estes tipos de "aliases" também podem ser utilizados em outras consultas para reduzir a digitação como, por
exemplo:
SELECT *
FROM clima w, cidades c
WHERE w.cidade = c.nome;

13 - Funções de Agregação

SELECT max(temp_min) FROM clima; max ----- 46


SELECT cidade FROM clima WHERE temp_min = max(temp_min); ERRADO
mas não vai funcionar, porque a função de agregação max não pode ser usada na cláusula WHERE (Esta restrição
existe porque a cláusula WHERE determina as linhas que vão passar para o estágio de agregação e, portanto, precisa
ser avaliada antes das funções de agregação serem computadas). Entretanto, como é geralmente o caso, a consulta
pode ser reformulada para obter o resultado pretendido, o que será feito por meio de uma subconsulta:
SELECT cidade FROM clima
WHERE temp_min = (SELECT max(temp_min) FROM clima);
cidade
---------------
São Francisco

SELECT cidade, max(temp_min) FROM clima GROUP BY cidade;

As linhas agrupadas podem ser filtradas utilizando a cláusula HAVING


SELECT cidade, max(temp_min) AS temperatura_minima
FROM clima
GROUP BY cidade
HAVING max(temp_min) < 40;

SELECT COUNT(*) AS Contagem FROM friend;


SELECT SUM(age) AS Soma FROM friend;
SELECT MAX(age) AS Maximo FROM friend;
SELECT MIN(age) AS Minimo FROM friend;
SELECT AVG(age) AS Media FROM friend;

SELECT state, MIN(age) AS Menor, MAX(age) As Maximo, AVG(age) AS Media FROM friend GROUP BY state
ORDER BY 4 DESC;

SELECT city, state, COUNT(*) AS Contagem FROM friend GROUP BY state, city ORDER BY 1, 2;
city | state | Countagem
-----+-------+-------
Boston | MA | 1
Cedar Creek | MD | 1
Ocean City | NJ | 2
Plymouth | MA | 1
Williamsport | PA | 1

14 - Cláusula HAVIN

SELECT state, COUNT(*) AS Contagem FROM friend GROUP BY state HAVING COUNT(*) > 1 ORDER BY
state;
6

15 - Atualizações em Tabelas
UPDATE clima
SET temp_max = temp_max - 2, temp_min = temp_min - 2
WHERE data > '1994-11-28';

16 - Excluindo Registros de Tabelas


DELETE FROM clima WHERE cidade = 'Hayward';

17 - Deve-se tomar cuidado com comandos na forma


DELETE FROM nome_da_tabela;
Sem uma qualificação, o comando DELETE remove todas as linhas da tabela, deixando-a vazia. O sistema não solicita
confirmação antes de realizar esta operação!

Funcionalidades Avançadas
18 - Visões (Views)

Supondo que a consulta combinando os registros de clima e de localização das cidades seja de particular interesse para
uma aplicação, mas que não se deseja digitar esta consulta toda vez que for necessária, então é possível criar uma
visão baseada na consulta, atribuindo um nome a esta consulta pelo qual será possível referenciá-la como se fosse uma
tabela comum.
CREATE VIEW minha_visao AS
SELECT cidade, temp_min, temp_max, prcp, data, localizacao
FROM clima, cidades
WHERE cidade = nome;

SELECT * FROM minha_visao;


Fazer livre uso de visões é um aspecto chave de um bom projeto de banco de dados SQL. As visões permitem
encapsular, atrás de interfaces que não mudam, os detalhes da estrutura das tabelas, que podem mudar na medida em
que as aplicações evoluem.
As visões podem ser utilizadas em praticamente todos os lugares onde uma tabela real pode ser utilizada. Construir
visões baseadas em visões não é raro.

19 - Chaves Estrangeiras
Desejamos ter certeza que não serão inseridas linhas na tabela clima sem que haja um registro correspondente na
tabela cidades. Isto é chamado de manter a integridade referencial dos dados.

CREATE TABLE cidades (


cidade varchar(80) primary key,
localizacao point
);

CREATE TABLE clima (


cidade varchar(80) references cidades(cidade),
temp_min int,
temp_max int,
prcp real,
data date
);

Agora, ao se tentar inserir uma linha inválida:


INSERT INTO clima VALUES ('Berkeley', 45, 53, 0.0, '1994-11-28');
ERROR: insert or update on table "clima" violates foreign key constraint
"clima_cidade_fkey"
DETAIL: Key (cidade)=(Berkeley) is not present in table "cidades".

20 - Tipos de dado
Nome Aliases Descrição
7

Bigint int8 inteiro de oito bytes com sinal [a]


Bigserial serial8 inteiro de oito bytes com auto-incremento
bit [ (n) ] cadeia de bits de comprimento fixo
bit varying [ (n) ] varbit cadeia de bits de comprimento variável [b]
Boolean bool booleano lógico (verdade/falso)
Box caixa retangular no plano
Bytea dados binários ("matriz de bytes")
character varying [ (n) ] varchar [ (n) ] cadeia de caracteres de comprimento variável [c]
character [ (n) ] char [ (n) ] cadeia de caracteres de comprimento fixo
Cidr endereço de rede IPv4 ou IPv6
Circle círculo no plano
Date data de calendário (ano, mês,dia)
double precision float8 número de ponto flutuante de precisão dupla [d]
inet endereço de hospedeiro IPv4 ou IPv6
integer int, int4 inteiro de quatro bytes com sinal
interval [ (p) ] espaço de tempo
line linha infinita no plano
lseg segmento de linha no plano
macaddr endereço MAC
money quantia monetária
numeric [ (p, s) ] decimal [ (p, s) ] numérico exato com precisão selecionável
path caminho geométrico no plano
point ponto geométrico no plano
polygon caminho geométrico fechado no plano
real float4 número de ponto flutuante de precisão simples
smallint int2 inteiro de dois bytes com sinal
serial serial4 inteiro de quatro bytes com auto-incremento
text cadeia de caracteres de comprimento variável
time [ (p) ] [ without time zone ] hora do dia
time [ (p) ] with time zone timetz hora do dia, incluindo a zona horária
timestamp [ (p) ] [ without time zone ] data e hora
timestamp [ (p) ] with time zone timestamptz data e hora, incluindo a zona horária

SELECT date_part('year', CAST('5/8/1971' AS DATE));

SELECT date('1980-06-25') + interval('21 years 8 days') AS spanned_date;

SELECT isbn, to_char(ship_date, 'YYYY-MM-DD HH24:MI:SS') AS value FROM shipments;


8

21 - Tipos numéricos
Tamanho de
Nome Descrição Faixa de valores
armazenamento
smallint 2 bytes inteiro com faixa pequena -32768 a +32767
integer 4 bytes escolha usual para inteiro -2147483648 a +2147483647
-9223372036854775808 a
bigint 8 bytes inteiro com faixa larga
9223372036854775807
precisão especificada pelo usuário,
decimal variável sem limite
exato
precisão especificada pelo usuário,
numeric variável sem limite
exato
real 4 bytes precisão variável, inexato precisão de 6 dígitos decimais
double
8 bytes precisão variável, inexato precisão de 15 dígitos decimais
precision
serial 4 bytes inteiro com auto-incremento 1 a 2147483647
bigserial 8 bytes inteiro grande com auto-incremento 1 a 9223372036854775807

22 - Arredondamento em tipo numeric

=> CREATE TABLE t ( c NUMERIC(6,3)); => INSERT INTO t VALUES (998.9991); => INSERT INTO t
VALUES (998.9999); => SELECT * FROM t; c --------- 998.999 999.000

23 - Tipo Serial

CREATE TABLE nome_da_tabela (


nome_da_coluna SERIAL
);

equivale a especificar:

CREATE SEQUENCE nome_da_tabela_nome_da_coluna_seq;


CREATE TABLE nome_da_tabela (
nome_da_coluna integer DEFAULT nextval('nome_da_tabela_nome_da_coluna_seq')
NOT NULL
);

24 - Alteração da seqüência da coluna serial

CREATE TABLE t ( c1 SERIAL, c2 TEXT);


NOTICE: CREATE TABLE will create implicit sequence "t_c1_seq" for "serial" column "t.c1" CREATE TABLE
ALTER SEQUENCE t_c1_seq RESTART WITH 1000;
INSERT INTO t VALUES (DEFAULT, 'Primeira linha');
9

25 - Auto-Incremento no Postgresql (Tipo Serial)

test=> CREATE TABLE customer (


test(> customer_id SERIAL PRIMARY KEY,
test(> name CHAR(30)
test(> );

Ao Insert, apenas adicionamos o campo name,pois ocustomer_id é adicionado automaticamente.

26 - Ajustando o Tipo de Data do Sistema GBD

SHOW DATESTYLE;
SET DATESTYLE TO ISO; YYYY-MM-DD HH:MM:SS
SET DATESTYLE TO PostgreSQL; Formato tradicionaldo PostgreSQL (
SET DATESTYLE TO US; MM/DD/YYYY
SET DATESTYLE TO NONEUROPEAN, GERMAN; DD.MM.YYYY
SET DATESTYLE TO EUROPEAN; DD/MM/YYYY

27 - Ajustando uma Faixa de Registros com LIMIT and OFFSET

SELECT isbn, title, publication FROM editions NATURAL JOIN books AS b (book_id)
ORDER BY publication DESC LIMIT 5;

SELECT isbn, title, publication FROM editions NATURAL JOIN books AS b (book_id)
ORDER BY publication DESC LIMIT 5 OFFSET 2;

Traz 5 registros, iniciando do segundo.

28 - Funções com Cadeias de Caracteres (Strings)

SELECT length('1234567890 ');


SELECT 'ae' || 'io' || 'u' AS vogais; vogais -------- aeiou
SELECT CHR(67)||CHR(65)||CHR(84) AS "Dog"; Dog CAT
SELECT INITCAP('the soap') AS "Capitals"; Capitals ---------- The Soap
SELECT LOWER('MR. SCOTT MCMILLAN') AS "Lowercase"; Lowercase -------------------- mr. scott mcmillan
SELECT LTRIM('xyxXxyLAST WORD','xy') AS "LTRIM example"; LTRIM example --------------- XxyLAST
WORD

SELECT REPLACE('JACK and JUE','J','BL') AS "Changes"; Changes ---------------- BLACK and BLUE
SELECT RTRIM('BROWNINGyxXxyyx','xy') AS "RTRIM example"; RTRIM example ---------------
BROWNINGyxX

SELECT SUBSTR('ABCDEFG',3,4) AS "Substring"; Substring ----------- CDEF


SELECT TRIM (0 FROM 0009872348900) AS "TRIM Example"; TRIM Example -------------- 98723489
SELECT UPPER('Large') AS "Uppercase"; Uppercase ----------- LARGE
10

29 - Correspondência com Padrão

O PostgreSQL disponibiliza três abordagens distintas para correspondência com padrão: o operador LIKE tradicional
do SQL; o operador mais recente SIMILAR TO (adicionado ao SQL:1999); e as expressões regulares no estilo
POSIX. Além disso, também está disponível a função de correspondência com padrão substring, que utiliza
expressões regulares tanto no estilo SIMILAR TO quanto no estilo POSIX.

SELECT substring('XY1234Z', 'Y*([0-9]{1,3})');


Resultado: 123
SELECT substring('XY1234Z', 'Y*?([0-9]{1,3})');
Resultado: 1

PostgreSQL 8.0
 SELECT texto FROM textos WHERE texto SIMILAR TO '([a-z]+).([a-z]+).([a-z]+)'; -- ou
 => SELECT texto FROM textos WHERE texto ~ '^([a-z]+)\\.([a-z]+)\\.([a-z]+)$'; -- ou
 => SELECT texto FROM textos WHERE texto ~ '^([a-z]+)[.]([a-z]+)[.]([a-z]+)$';

Selecionar textos começando pela letra "S" maiúscula (_* equivale a %).
• PostgreSQL 8.0.0
=> SELECT texto FROM textos WHERE texto SIMILAR TO 'S%';
-- ou
=> SELECT texto FROM textos WHERE texto SIMILAR TO 'S_*';
-- ou
=> SELECT texto FROM textos WHERE texto ~ '^S';

Selecionar textos contendo "Mc" em qualquer posição.


• PostgreSQL 8.0.0
=> SELECT texto FROM textos WHERE texto SIMILAR TO '%Mc%';
-- ou
=> SELECT texto FROM textos WHERE texto ~ 'Mc';

Selecionar textos terminados por "on".


• PostgreSQL 8.0.0
=> SELECT texto FROM textos WHERE texto SIMILAR TO '%on';
-- ou
=> SELECT texto FROM textos WHERE texto ~ 'on$';

Selecionar textos começando por "J" e terminando por "n".


• PostgreSQL 8.0.0
=> SELECT texto FROM textos WHERE texto SIMILAR TO 'J%n';
-- ou
=> SELECT texto FROM textos WHERE texto ~ '^J.*n$';

Selecionar textos contendo "Cameron" ou "Marie" em qualquer posição.


• PostgreSQL 8.0.0
=> SELECT texto FROM textos WHERE texto SIMILAR TO '%(Cameron|Marie)%';
-- ou
=> SELECT texto FROM textos WHERE texto ~ '(Cameron|Marie)';

Selecionar textos contendo "Maria", "Marie" ou "Mary" (não seleciona "Margaret").


• PostgreSQL 8.0.0
=> SELECT texto FROM textos WHERE texto SIMILAR TO '%Mar(ia|ie|y)%';
-- ou
=> SELECT texto FROM textos WHERE texto ~ 'Mar(ia|ie|y)';

Selecionar textos sem nenhum caractere, ou com somente espaços em branco (no Oracle texto sem nenhum caractere é
igual a nulo).
11

• PostgreSQL 8.0.0
=> SELECT texto, length(texto) FROM textos WHERE texto SIMILAR TO
'[[:space:]]*';
-- ou
=> SELECT texto, length(texto) FROM textos WHERE texto SIMILAR TO '\\s*';
-- ou
=> SELECT texto, length(texto) FROM textos WHERE texto ~ '^[[:space:]]
*$';
-- ou
=> SELECT texto, length(texto) FROM textos WHERE texto ~ '^\\s*$';

Selecionar textos contendo a letra "W" minúscula ou maiúscula, seguida por uma ou mais letras "W" minúsculas ou
maiúsculas.
• PostgreSQL 8.0.0
=> SELECT texto FROM textos WHERE texto SIMILAR TO '%[Ww]([Ww]+)%';
-- ou
=> SELECT texto FROM textos WHERE texto ~ '[Ww]([Ww]+)';
-- ou
=> SELECT texto FROM textos WHERE texto ~ '[Ww]{2,}';

Selecionar textos contendo "Inês", com letras maiúsculas ou minúsculas, com ou sem acento, em qualquer posição.
• PostgreSQL 8.0.0
=> SELECT texto FROM textos WHERE texto SIMILAR TO '%[Ii][nN][eéêEÉÊ]
[Ss]%';
-- ou
=> SELECT texto FROM textos WHERE lower(to_ascii(texto)) SIMILAR TO '%
ines%';
-- ou
=> SELECT texto FROM textos WHERE texto ~ '[Ii][nN][eéêEÉÊ][Ss]';
-- ou
=> SELECT texto FROM textos WHERE lower(to_ascii(texto)) ~ 'ines';

Selecionar textos contendo dígitos.


• PostgreSQL 8.0.0
=> SELECT texto FROM textos WHERE texto SIMILAR TO '%[0-9]+%';
-- ou
=> SELECT texto FROM textos WHERE texto SIMILAR TO '%[[:digit:]]+%';
-- ou
=> SELECT texto FROM textos WHERE texto SIMILAR TO '%\\d+%';
-- ou
=> SELECT texto FROM textos WHERE texto ~ '[0-9]+';
-- ou
=> SELECT texto FROM textos WHERE texto ~ '[[:digit:]]+';
-- ou
=> SELECT texto FROM textos WHERE texto ~ '\\d+';
12

Selecionar textos não contendo espaços em branco (texto sem nenhum caractere não possui espaço em branco, mas no
Oracle texto sem nenhum caractere é igual a nulo).
• PostgreSQL 8.0.0
=> SELECT texto FROM textos WHERE texto NOT SIMILAR TO '%\\s%';
-- ou
=> SELECT texto FROM textos WHERE texto NOT SIMILAR TO '%[[:space:]]%';
-- ou
=> SELECT texto FROM textos WHERE texto !~ '\\s';
-- ou
=> SELECT texto FROM textos WHERE texto !~ '[[:space:]]';

Selecionar textos que podem ser endereços de correio eletrônico.


• PostgreSQL 8.0.0
=> SELECT texto
-> FROM textos
-> WHERE texto SIMILAR TO '[a-zA-Z][\\w.-]*@[a-zA-Z][\\w.-]*.[a-zA-Z]+';
-- ou
-> WHERE texto SIMILAR TO '[a-zA-Z][[:alnum:]\\_.-]*@[a-zA-Z][[:alnum:]
\\_.-]*.[a-zA-Z]+';
-- ou
-> WHERE texto ~ '^[a-zA-Z][\\w.-]*@[a-zA-Z][\\w.-]*[.][a-zA-Z]+$';
-- ou
-> WHERE texto ~ '^[a-zA-Z][[:alnum:]_.-]*@[a-zA-Z][[:alnum:]_.-]*[.][a-
zA-Z]+$';

Selecionar textos que podem ser endereços de hardware de placa Ethernet, formados por 48 bits, expressos como 12
dígitos hexadecimais (0-9 e A-F maiúsculas), no formato 12:34:56:78:9A:BC.
• PostgreSQL 8.0.0
=> SELECT texto
-> FROM textos
-> WHERE texto ~ '^[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-
F]{2}:[0-9A-F]{2}$';
-- ou
-> WHERE texto ~ '^([0-9A-F]{2}:){5}[0-9A-F]{2}$';

30 - Funções de formatação de Tipos de Dados


Função Tipo retornado Descrição Exemplo
to_char(timestamp, converte carimbo do tempo (time stamp) to_char(current_timestamp,
text
text) em cadeia de caracteres 'HH12:MI:SS')
to_char(interval '15h 2m 12s',
to_char(interval, text) text converte intervalo em cadeia de caracteres
'HH24:MI:SS')
to_char(int, text) text converte inteiro em cadeia de caracteres to_char(125, '999')
to_char(double converte real e precisão dupla em cadeia de
text to_char(125.8::real, '999D9')
precision, text) caracteres
to_char(numeric, text) text converte numérico em cadeia de caracteres to_char(-125.8, '999D99S')
to_date('05 Dec 2000', 'DD
to_date(text, text) date converte cadeia de caracteres em data
Mon YYYY')
to_timestamp(text, timestamp with converte cadeia de caracteres em carimbo to_timestamp('05 Dec 2000',
text) time zone do tempo 'DD Mon YYYY')
to_number('12,454.8-',
to_number(text, text) numeric converte cadeia de caracteres em numérico
'99G999D9S')
31 - Exemplos de utilização da função to_char
Expressão PostgreSQL 8.0.0 [a] Oracle 10g (N. do T.) [b]
to_char(current_timestamp, 'Day, DD HH12:MI:SS') 'Friday , 04 02:22:24' 'Friday , 04 02:22:24'
13

to_char(current_timestamp, 'FMDay, FMDD


'Friday, 4 02:22:24' 'Friday, 04 02:22:24'
HH12:MI:SS')
to_char(-0.1, '99.99') ' -.10' ' -.10'
to_char(-0.1, 'FM9.99') '-.1' '-.1'
to_char(0.1, '0.9') ' 0.1' ' 0.1'
to_char(12, '9990999.9') ' 0012.0' ' 0012.0'
to_char(12, 'FM9990999.9') '0012.' '0012.'
to_char(485, '999') ' 485' ' 485'
to_char(-485, '999') '-485' '-485'
to_char(485, '9 9 9') ' 4 8 5' formato inválido
to_char(1485, '9,999') ' 1,485' ' 1,485'
to_char(1485, '9G999') ' 1,485' ' 1,485'
to_char(148.5, '999.999') ' 148.500' ' 148.500'
to_char(148.5, 'FM999.999') '148.5' '148.5'
to_char(148.5, 'FM999.990') '148.500' '148.500'
to_char(148.5, '999D999') -- com localização ' 148,500' ' 148,500'
to_char(3148.5, '9G999D999') ' 3,148.500' ' 3,148.500'
to_char(-485, '999S') '485-' '485-'
to_char(-485, '999MI') '485-' '485-'
to_char(485, '999MI') '485 ' '485 '
to_char(485, 'FM999MI') '485' '485'
to_char(485, 'PL999') '+485' formato inválido
to_char(485, 'SG999') '+485' formato inválido
to_char(-485, 'SG999') '-485' formato inválido
to_char(-485, '9SG99') '4-85' formato inválido
to_char(-485, '999PR') '<485>' '<485>'
to_char(485, 'L999') -- com localização 'R$ 485' ' R$485'
to_char(485, 'RN') ' CDLXXXV' ' CDLXXXV'
to_char(485, 'FMRN') 'CDLXXXV' 'CDLXXXV'
to_char(5.2, 'FMRN') 'V' 'V'
to_char(482, '999th') ' 482nd' formato inválido
to_char(485, '"Good number:"999') 'Good number: 485' formato inválido
to_char(485.8, '"Pre:"999" Post:" .999') 'Pre: 485 Post: .800' formato inválido
to_char(12, '99V999') ' 12000' ' 12000'
to_char(12.4, '99V999') ' 12400' ' 12400'
to_char(12.45, '99V9') ' 125' ' 125'
Notas:
a. localização — set lc_numeric to 'pt_BR'; set lc_monetary to 'pt_BR'; (N. do T.)
b. localização — ALTER SESSION SET NLS_TERRITORY="BRAZIL"; (N. do T.)
14

32 - Funções para data e hora


Tipo
Função Descrição Exemplo Resultado
retornado
Subtrai os argumentos, produzindo um age(timestamp '2001-04- 43 years 9
age(timestamp,
interval resultado "simbólico" que utiliza anos e 10', timestamp '1957-06- mons 27
timestamp)
meses 13') days
age(timestamp '1957-06- 43 years 8
age(timestamp) interval Subtrai de current_date
13') mons 3 days
current_date date Data de hoje; veja a Seção 9.9.4
time with
current_time Hora do dia; veja a Seção 9.9.4
time zone
timestamp
current_timesta
with time Data e hora; veja a Seção 9.9.4
mp
zone
date_part(text, double Retorna subcampo (equivale ao extract); date_part('hour', timestamp
20
timestamp) precision veja a Seção 9.9.1 '2001-02-16 20:38:40')
date_part(text, double Retorna subcampo (equivale ao extract); date_part('month', interval
3
interval) precision veja a Seção 9.9.1 '2 years 3 months')
date_trunc('hour',
date_trunc(text, Trunca na precisão especificada; veja a 2001-02-16
timestamp timestamp '2001-02-16
timestamp) Seção 9.9.2 20:00:00
20:38:40')
extract(campo extract(hour from
double
from Retorna subcampo; veja a Seção 9.9.1 timestamp '2001-02-16 20
precision
timestamp) 20:38:40')
extract(campo double extract(month from interval
Retorna subcampo; veja a Seção 9.9.1 3
from interval) precision '2 years 3 months')
isfinite Testa carimbo do tempo finito (diferente de isfinite(timestamp '2001-
boolean true
(timestamp) infinito) 02-16 21:28:30')
isfinite(interval) boolean Testa intervalo finito isfinite(interval '4 hours') true
localtime time Hora do dia; veja a Seção 9.9.4
localtimestamp timestamp Data e hora; veja a Seção 9.9.4
timestamp
Data e hora corrente (equivale ao
now() with time
current_timestamp); veja a Seção 9.9.4
zone
timeofday() text Data e hora corrente; veja a Seção 9.9.4

SELECT extract(CENTURY FROM TIMESTAMP '2000-12-16 12:21:13');


Resultado: 20
SELECT extract(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40');
Resultado: 21

SELECT extract(DAY FROM TIMESTAMP '2001-02-16 20:38:40');


Resultado: 16

decade
O campo ano dividido por 10
SELECT extract(DECADE FROM TIMESTAMP '2001-02-16 20:38:40');
Resultado: 200
dow
O dia da semana (0 - 6; Domingo é 0) (para valores timestamp apenas)
SELECT extract(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
15

Resultado: 5

Exemplos:

 SELECT extract(DOW FROM TIMESTAMP '2005-08-14 20:38:40') AS Domingo; domingo --------- 0 (1 linha)
=> SELECT to_char(TIMESTAMP '2005-08-14 20:38:40','D') AS Domingo; domingo --------- 1 (1 linha)
 => SELECT extract(DOW FROM TIMESTAMP '2005-08-20 20:38:40') AS Sábado; sábado -------- 6 (1 linha)
=> SELECT to_char(TIMESTAMP '2005-08-20 20:38:40','D') AS Sábado; sábado -------- 7 (1 linha)

SELECT to_char(TIMESTAMP '2004-12-31 23:59:59', 'DDD') AS dia; dia ----- 366

epoch
Para valores date e timestamp, o número de segundos desde 1970-01-01 00:00:00-00 (pode ser
negativo); para valores interval, o número total de segundos do intervalo
SELECT extract(EPOCH FROM TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-
08');
Resultado: 982384720

SELECT extract(EPOCH FROM INTERVAL '5 days 3 hours');


Resultado: 442800
Abaixo está mostrado como converter de volta um valor de época para um valor de carimbo do
tempo:
SELECT TIMESTAMP WITH TIME ZONE 'epoch' + 982384720 * INTERVAL '1 second';
hour
O campo hora (0 - 23)
SELECT extract(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
Resultado: 20
month
Para valores timestamp, o número do mês do ano dentro do ano (1 - 12); para valores interval,
o número de meses, módulo 12 (0 - 11)
SELECT extract(MONTH FROM TIMESTAMP '2001-02-16 20:38:40');
Resultado: 2

SELECT extract(MONTH FROM INTERVAL '2 years 3 months');


Resultado: 3

SELECT extract(MONTH FROM INTERVAL '2 years 13 months');


Resultado: 1
16

week
O número da semana do ano onde o dia se encontra. Por definição (ISO 8601), a primeira
semana do ano contém o dia 4 de janeiro deste ano; a semana ISO-8601 começa na segunda-
feira. Em outras palavras, a primeira quinta-feira do ano está na primeira semana do ano.
(apenas para valores timestamp)
SELECT extract(WEEK FROM TIMESTAMP '2001-02-16 20:38:40');
Resultado: 7
year
O campo ano. Deve-se ter em mente que não existe o ano 0 DC e, portanto, subtrair anos AC
de DC deve ser feito com cautela.
SELECT extract(YEAR FROM TIMESTAMP '2001-02-16 20:38:40');
Resultado: 2001

33 - A função date_part é modelada segundo a função equivalente tradicional do Ingres à função extract do padrão
SQL:
date_part('campo', fonte)
Deve ser observado que, neste caso, o parâmetro campo deve ser um valor cadeia de caracteres, e não um nome. Os
nomes de campo válidos para date_part são os mesmos da função extract.
SELECT date_part('day', TIMESTAMP '2001-02-16 20:38:40');
Resultado: 16

SELECT date_part('hour', INTERVAL '4 hours 3 minutes');


Resultado: 4

34 - date_trunc
A função date_trunc é conceitualmente similar à função trunc para números.
date_trunc('campo', fonte)

SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40');


Resultado: 2001-02-16 20:00:00

SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40');


Resultado: 2001-01-01 00:00:00

35 - Data e hora correntes


SELECT CURRENT_TIME;
Resultado: 14:39:53.662522-05

SELECT CURRENT_DATE;
Resultado: 2001-12-23

SELECT CURRENT_TIMESTAMP;
Resultado: 2001-12-23 14:39:53.662522-05

SELECT CURRENT_TIMESTAMP(2);
Resultado: 2001-12-23 14:39:53.66-05

SELECT LOCALTIMESTAMP;
Resultado: 2001-12-23 14:39:53.662522

Também existe a função timeofday(), que por motivos históricos retorna uma cadeia de caracteres do tipo text, e não
um valor do tipo timestamp:
17

SELECT timeofday();
Resultado: Sat Feb 17 19:07:32.000126 2001 EST

SELECT CURRENT_TIMESTAMP;
SELECT now();

36 - Utilização de INTERVAL

SELECT INTERVAL'20 DAY' - INTERVAL'240 HOUR' AS intervalo; intervalo ----------- 10 days (1 linha) =>
SELECT INTERVAL '4 DAYS 5 HOURS 12 MINUTES'; interval ----------------- 4 days 05:12:00

37 - Número de dias entre duas datas


SELECT date('1950-07-16') - date('1949-11-21') AS dias; dias ------ 237

38 - Obtenção do dia do mês

SELECT date_part('day',CURRENT_TIMESTAMP) AS dia; dia ----- 14 (1 linha)


 SELECT extract(DAY FROM CURRENT_TIMESTAMP) AS dia; dia ----- 14 (1 linha)
 => SELECT to_char(CURRENT_TIMESTAMP,'DD') AS dia; dia ----- 14

39 - Utilização das funções para data e hora corrente


SELECT CURRENT_DATE; date ------------ 2005-03-04 (1 linha)
 SELECT CURRENT_TIME; timetz -------------------- 16:42:07.33-03 (1 linha)
 => SELECT CURRENT_TIMESTAMP; timestamptz ------------------------------- 2005-03-04 16:42:07.38-03 (1
linha)
 => SELECT CURRENT_TIME(0); timetz ------------- 16:42:07-03 (1 linha)
 => SELECT CURRENT_TIMESTAMP(0); timestamptz ------------------------ 2005-03-04 16:42:07-03 (1 linha)
=> SELECT LOCALTIME AS agora; agora ------------- 16:42:07.53 (1 linha)
 => SELECT LOCALTIMESTAMP; timestamp ---------------------------- 2005-03-04 16:42:07.58 (1 linha)
 => SELECT LOCALTIME (0) AS agora; agora ---------- 16:42:08 (1 linha)
 => SELECT LOCALTIMESTAMP (0) AS agora; agora --------------------- 2005-03-04 16:42:08 (1 linha)
 => SELECT CURRENT_TIMESTAMP AT TIME ZONE 'UTC' AS UTC; utc ---------------------------- 2005-03-
04 19:42:07.73 (1 linha)
 => SELECT now(); now ------------------------------- 2005-03-04 16:42:07.891-03 (1 linha)
 => SELECT timeofday(); timeofday ------------------------------------- Fri Mar 04 16:42:07.941000 2005 BRT (1
linha) => SELECT to_char(CURRENT_TIMESTAMP, 'DD-MM-YYYY HH24:MI:SS') AS agora; agora
-------------------- 04-03-2005 16:42:07

40 - Somar dias e horas a uma data

SELECT cast('2004-07-16' AS date) + interval'30 days' AS data; data --------------------- 2004-08-15 00:00:00 (1 linha)
=> SELECT cast('2004-07-16 15:00:00' AS timestamp) + interval'30 days' AS data; data --------------------- 2004-08-15
15:00:00 (1 linha)
 SELECT current_timestamp as agora, -> current_timestamp + interval'3 days 3 hours' AS depois;
 agora | depois
 -------------------------------+-------------------------------
 2005-04-01 08:16:44.029386-03 | 2005-04-04 11:16:44.029386-03
18

41 - Operadores para os tipos cidr e inet


Operador Descrição Exemplo
< Menor inet '192.168.1.5' < inet '192.168.1.6'
<= menor ou igual inet '192.168.1.5' <= inet '192.168.1.5'
= Igual inet '192.168.1.5' = inet '192.168.1.5'
>= maior ou igual inet '192.168.1.5' >= inet '192.168.1.5'
> Maior inet '192.168.1.5' > inet '192.168.1.4'
<> Diferente inet '192.168.1.5' <> inet '192.168.1.4'
<< está contido em inet '192.168.1.5' << inet '192.168.1/24'
<<= está contido ou é igual inet '192.168.1/24' <<= inet '192.168.1/24'
>> contém inet '192.168.1/24' >> inet '192.168.1.5'
>>= contém ou é igual inet '192.168.1/24' >>= inet '192.168.1/24'

42 - Funções para os tipos cidr e inet


Tipo
Função Descrição Exemplo Resultado
retornado
broadcast 192.168.1.2
broadcast(inet) inet endereço de difusão da rede
('192.168.1.5/24') 55/24
host(inet) text extrai o endereço de IP como texto host('192.168.1.5/24') 192.168.1.5
masklen
masklen(inet) integer extrai o comprimento da máscara de rede 24
('192.168.1.5/24')
set_masklen(inet, define o comprimento da máscara de rede para o set_masklen 192.168.1.5
inet
integer) valor do tipo inet ('192.168.1.5/24', 16) /16
netmask 255.255.25
netmask(inet) inet constrói máscara de rede para a rede
('192.168.1.5/24') 5.0
hostmask
hostmask(inet) inet constrói máscara de hospedeiro para a rede 0.0.0.3
('192.168.23.20/30')
network 192.168.1.0
network(inet) cidr extrai do endereço a parte de rede
('192.168.1.5/24') /24
extrai o endereço de IP e o comprimento da 192.168.1.5
text(inet) text text(inet '192.168.1.5')
máscara de rede como texto /32
abbrev(cidr
abbrev(inet) text formato de exibição abreviado como texto 10.1/16
'10.1.0.0/16')
extrai a família de endereços; 4 para IPv4, e 6
family(inet) integer family('::1') 6
para IPv6
19

43 - Funções de informação da sessão


Tipo
Nome Descrição
retornado
current_database() name nome do banco de dados corrente
current_schema() name nome do esquema corrente
current_schemas nomes dos esquemas no caminho de procura incluindo, opcionalmente, os
name[]
(boolean) esquemas implícitos
current_user name nome do usuário do contexto de execução corrente
inet_client_addr() inet endereço da conexão remota
inet_client_port() int4 porta da conexão remota
inet_server_addr() inet endereço da conexão local
inet_server_port() int4 port da conexão local
session_user name nome do usuário da sessão
user name equivale a current_user
version() text informação da versão do PostgreSQL

44 - Funções para administração do sistema


Funções para definição de configuração
Tipo
Nome Descrição
retornado
current_setting(nome_da_definição) text valor corrente da definição
set_config(nome_da_definição, novo_valor, é_local) text define o parâmetro e retorna o novo valor

SELECT current_setting('datestyle'); current_setting ----------------- ISO, DMY


SELECT set_config('log_statement_stats', 'off', false); set_config ------------ off

Funções de controle de cópia de segurança


Nome Tipo retornado Descrição
pg_start_backup(texto_do_rótulo) text configura para realizar cópia de segurança on-line
pg_stop_backup() text Termina a realização da cópia de segurança on-line

A função pg_start_backup recebe um único parâmetro que é um rótulo arbitrário definido pelo usuário para a cópia de
segurança (habitualmente é o nome sob o qual o arquivo da cópia de segurança será armazenado). A função escreve o
arquivo rótulo da cópia de segurança no diretório de dados do agrupamento de bancos de dados e, então, retorna o
deslocamento no WAL do início da cópia de segurança como texto (o usuário não precisa prestar atenção a este valor
do resultado, mas é fornecido para o caso de ser útil).
A função pg_stop_backup remove o arquivo rótulo criado pela função pg_start_backup e, em seu lugar, cria o arquivo
de histórico de cópia de segurança na área de arquivamento do WAL. O arquivo de histórico inclui o rótulo fornecido
para a função pg_start_backup, os deslocamentos inicial e final do WAL para a cópia de segurança, e o tempo de
início e de fim da cópia de segurança. O valor retornado é o deslocamento no WAL do fim da cópia de segurança
(que, novamente, pode ser pouco interessante).
20

45 - Conversão de Tipos

SELECT text 'Origem' AS "local", point '(0,0)' AS "valor";

46 - Dicas de Desempenho

Utilização do comando EXPLAIN

O PostgreSQL concebe um plano de comando para cada comando recebido. A escolha do plano correto,
correspondendo à estrutura do comando e às propriedades dos dados, é absolutamente crítico para o bom desempenho.
Pode ser utilizado o comando EXPLAIN para ver o plano criado pelo sistema para qualquer comando. A leitura do
plano é uma arte que merece um tutorial extenso, o que este não é; porém, aqui são fornecidas algumas informações
básicas.
Os números apresentados atualmente pelo EXPLAIN são:
• O custo de partida estimado (O tempo gasto antes de poder começar a varrer a saída como, por exemplo, o
tempo para fazer a classificação em um nó de classificação).
• O custo total estimado (Se todas as linhas fossem buscadas, o que pode não acontecer: uma consulta contendo
a cláusula LIMIT pára antes de gastar o custo total, por exemplo).
• Número de linhas de saída estimado para este nó do plano (Novamente, somente se for executado até o fim).
• Largura média estimada (em bytes) das linhas de saída deste nó do plano.

EXPLAIN SELECT * FROM tenk1;


QUERY PLAN
Seq Scan on tenk1 (cost=0.00..333.00 rows=10000 width=148)

Agora a consulta será modificada para incluir uma condição WHERE:


EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 1000;

Modificando-se a consulta para restringir mais ainda a condição


EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 50;

Adição de outra condição à cláusula WHERE:


EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 50 AND stringu1 = 'xxx';

A seguir é feita a junção de duas tabelas, utilizando as colunas sendo discutidas:


EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 50 AND t1.unique2 =
t2.unique2;

Uma forma de ver outros planos é forçar o planejador a não considerar a estratégia que sairia vencedora, habilitando e
desabilitando sinalizadores de cada tipo de plano (Esta é uma ferramenta deselegante, mas útil.
SET enable_nestloop = off;
EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 50 AND t1.unique2 =
t2.unique2;
21

É possível verificar a precisão dos custos estimados pelo planejador utilizando o comando EXPLAIN ANALYZE. Na
verdade este comando executa a consulta, e depois mostra o tempo real acumulado dentro de cada nó do plano junto
com os custos estimados que o comando EXPLAIN simples mostraria. Por exemplo, poderia ser obtido um resultado
como este:
EXPLAIN ANALYZE SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 < 50 AND
t1.unique2 = t2.unique2;

47 - ROTINAS DEMANUTENÇÃO DO BANCO DE DADOS

Limpeza
vacuum
vacuum full
analyze
VACUUM ANALYZE;
VACUUM FULL ANALYZE;

48 - Formatar Data no PostgreSQL como DD/MM/YYYY

Não é função do servidor de banco de dados formatar datas (ou o que quer
que seja) em todas as maneiras possíveis e imagináveis para todo mundo. O
PostgreSQL dispões de facilidades de sobra para formatar datas em qualquer
formato
(veja http://www.postgresql.org/idocs/index.php?functions-formatting.html):

foobar=# select to_char(timestamp 'now', 'DD/MM/YYYY');


to_char
------------
02/08/2002

foobar=# select to_char('2002-04-21'::timestamp, 'DD/MM/YYYY');


to_char
------------
21/04/2002

foobar=# select to_char(date '2002-04-21', 'DD/MM/YYYY');


to_char
------------
21/04/2002

So você não quer escrever isso tudo nas suas consultas, crie uma função
armazenada para tornar abstrato:

CREATE OR REPLACE FUNCTION form_data(timestamp) RETURNS varchar AS '


DECLARE
v_data ALIAS FOR $1;
consulta VARCHAR;
resultado RECORD;
BEGIN
consulta := ''SELECT to_char(timestamp '''''' || $1 ||
'''''',''''DD/MM/YYYY'''') as data_final'';
FOR resultado IN EXECUTE consulta LOOP
return resultado.data_final;
END LOOP;
END;
' LANGUAGE 'plpgsql';
22

foobar=# select form_data(now());


form_data
------------
02/08/2002

foobar=# select form_data('2001-02-23');


form_data
------------
23/02/2001

Se a infinidade de apóstrofos lhe confundiu, não se preocupe, confunde a


todos. O time do PostgreSQL está trabalhando para eliminar essa feiúra
(patch, alguém?). Veja http://www.postgresql.org/idocs/index.php?plpgsql-porting.html para uma
"cola" boa (que eu fiz para mim mesmo, para momentos como esso :-)).

-Roberto

Fonte: http://br.groups.yahoo.com/group/postgresql-br/message/4747

S-ar putea să vă placă și