Tipo retornado desconhecido na consulta PostgreSQL


9

A seguinte consulta funciona:

SELECT a, b
FROM unnest(ARRAY[(1,2), (3,4)])
AS t(a integer, b integer);

a b
_ _
1 2
3 2

No entanto, não pude usar um tipo de coluna diferente, como varchar(255):

SELECT a, b
FROM unnest(ARRAY[(1,'hello'), (3,'world')])
AS t(a integer, b varchar(255));

ERROR:  42804: function return row and query-specified return row do not match
DETAIL:  Returned type unkown at ordinal position 2, but query expects text.

Parece que, no segundo caso, o tipo de coluna é inferido como unknown, que não é convertido varchar(255)automaticamente.

Como faço para o segundo exemplo funcionar e retornar colunas com o tipo certo, se possível sem avisos e sem modificar a ARRAY[...]definição?

Antecedentes: Estou tentando melhorar o desempenho de operações de inserção em massa grandes usando o psycopg2módulo Python, que não suporta o uso de várias linhas nos VALUESargumentos. Eu tropecei no exemplo acima enquanto tentava outros métodos.


Não sei por que você afirma que o psycopg2 não suporta várias linhas VALUES. O seguinte funciona muito bem para mim:cur.execute('INSERT INTO foo VALUES (%s, %s), (%s, %s), (%s, %s)', (1, 'foo', 2, 'bar', 3, 'baz'))
Dave Jones

O que quero dizer é que ele não suporta um número arbitrário de linhas, por exemplo, algo como cur.execute('INSERT INTO too VALUES %s', (list_of_rows,))isso não existe.
FX

Ahh, e você espera substituir a matriz como um único parâmetro, pelo que entendi.
Dave Jones

Respostas:


7

Você pode fazer isso sem gerar um aviso criando um tipo e lançando os registros para ele:

create type t as (a integer, b varchar(255));

select * from unnest(array[(1,'hello'), (3,'world')]::t[]);
┌───┬───────┐
 a    b   
├───┼───────┤
 1  hello 
 3  world 
└───┴───────┘

testado em 9.4 e 9.3 (db <> violino aqui )


7

É feio, mas você pode tentar:

SELECT a, b::text
FROM unnest(ARRAY[(1,'hello'), (3,'world')])
AS t(a integer, b unknown);

Dessa forma, o tipo definido em AScorresponde à saída de unnest(), que você pode converter para suas necessidades na SELECTlista.

Você pode tentar isso em um pequeno SQLFiddle .


1

Deve fazê-lo:

SELECT a, b
FROM unnest(ARRAY[(1,varchar 'hello'), (3,varchar 'world')])
AS t(a integer, b varchar(255));

11
Isso funciona, no entanto, não fui capaz de forçar psycopg2a inclusão de conversões de tipo dentro da ARRAY[...]definição. É possível fazê-lo sem? Eu editei minha pergunta para refletir isso.
FX
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.