2011-03-25 10 views
14

Ejemplo:¿INSERT RETURNING está garantizado para devolver las cosas en el orden "correcto"?

create table foo(
    id serial, 
    txt text 
); 

insert into foo(txt) values ('a'),('b'),('c') returning id; 

devoluciones:

id 
---- 
    1 
    2 
    3 
(3 rows) 

Se parece que el primeraid en el valor de retorno será siempre el id para 'a', el segundo para 'b' y así sucesivamente, pero, ¿es este comportamiento definido de insert into, o es una coincidencia que puede fallar en circunstancias extrañas?

Respuesta

15

No veo nada en the documentation que garantice un pedido de RETURNING así que no creo que pueda confiar en ello. Las probabilidades son que el orden RETURNING coincidirá con el orden VALUES, pero no veo ninguna garantía sobre el orden en que se insertará el VALUES; VALUES es casi seguro que se insertarán en orden de izquierda a derecha, pero una vez más, no hay garantía documentada.

Además, el modelo relacional se establece en función de que el orden es algo aplicado por el usuario y no una propiedad inherente de una relación. En general, si no hay forma de especificar explícitamente un pedido, no hay ordenamiento implícito.

Ejecutar resumen: el orden que está viendo es probablemente lo que siempre ocurrirá, pero no está garantizado, así que no dependa de él.

+1

Soy consciente de que las relaciones no están ordenadas, pero no estaba seguro de si la parte 'values' se debe modelar como una relación o una lista :) Esperaba que podría ser un caso especial, ya que el (orden- independiente) alternative 'insert into foo (txt) values ​​(' a '), (' b '), (' c ') return (txt, id) 'parece un poco derrochador (supongo que estoy optimizando prematuramente de nuevo ...) – FunctorSalad

+0

@FunctorSalad: Los 'valores' probablemente se tratan como una lista, pero no lo veo garantizado en ninguna parte.Y si se trata de la orden de 'devolver' el cuello de su botella de rendimiento, entonces probablemente esté bien :) –

+1

De acuerdo, * absolutamente * no confíe en él. PostgreSQL está dentro de sus derechos para ordenar las entradas, sin embargo, resultaría en el mejor rendimiento de inserción, y si las tablas organizadas por índice alguna vez se implementan, probablemente lo hará. –

3

Si bien esto no lo ayudará ahora, 9.1 incluirá "writeable common table expressions". Ese es el nombre oficial de WITH syntax. (Wikipedia.)

Esta nueva capacidad debe dejar de realizar su INSERT ... RETURNING dentro de un WITH, dar un alias, y luego SELECT contra el que con un pedido específico con un viejo y simple cláusula ORDER BY.

+2

Esto es interesante, pero solo se relaciona tangencialmente. Se podría usar como una aproximación cercana de lo que el OP está pidiendo * solo si * el orden de ENTRADA se puede expresar con un 'ORDER BY' inequívoco y equivalente también. – Flimzy

7

Mientras que la documentación no está del todo claro, lo hace afirman que:

Si el comando INSERT contiene una cláusula de regresar, el resultado será similar a la de una instrucción SELECT que contiene las columnas y los valores definidos en la lista de RETORNO, calculada sobre la (s) fila (s) insertadas por el comando.

Ahora "similar a" no es una garantía rigurosa, y he raised this for discussion on the mailing list ... pero en la práctica, PostgreSQL no se hace un lío con el orden de los valores en RETURNING. Es poco probable que alguna vez podamos, incluso si queremos para la optimización, porque demasiadas aplicaciones dependen de que se solicite lo mismo que la entrada.

Así que ... para INSERT INTO ... VALUES (...), (...), ... RETURNING ... y para INSERT INTO ... SELECT ... ORDER BY ... RETURNING ... debe ser seguro asumir que la relación de resultado es la misma en el orden que la entrada.

Cuestiones relacionadas