Si tuviera una tabla con 3 columnas, digamos A, B y D, y tuviera que introducir una nueva, diga C para reemplazar la posición actual de D. Usaría el siguiente método:
- Introducir 2 nuevas columnas como C y D2.
- Copie el contenido de D a D2.
- Eliminar D.
- Cambiar el nombre de D2 a D.
El nuevo orden sería A, B, C y D.
Pensé que esta era una práctica legítima ya que (hasta ahora) no produjo problemas.
Sin embargo, hoy me encontré con un problema cuando una función que realizaba una declaración en la misma tabla devolvía el siguiente error:
table row type and query-specified row type do not match
Y el siguiente detalle:
Query provides a value for a dropped column at ordinal position 13
Intenté reiniciar PostgreSQL, haciendo una VACUUM FULL
y finalmente eliminando y volviendo a crear la función como se sugiere aquí y aquí, pero estas soluciones no funcionaron (aparte del hecho de que intentan abordar una situación en la que se ha alterado una tabla del sistema).
Teniendo el lujo de trabajar con una base de datos muy pequeña, la exporté, la eliminé y luego la volví a importar y eso solucionó el problema con mi función.
Era consciente del hecho de que uno no debería perder el tiempo con el orden natural de las columnas modificando las tablas del sistema (ensuciarse las manos pg_attribute
, etc.) como se ve aquí:
¿Es posible cambiar el orden natural de las columnas en Postgres?
A juzgar por el error arrojado por mi función, ahora me doy cuenta de que cambiar el orden de las columnas con mi método también es un no-no. ¿Alguien puede arrojar algo de luz sobre por qué lo que estoy haciendo también está mal?
La versión de Postgres es 9.6.0.
Aquí está la función:
CREATE OR REPLACE FUNCTION "public"."__post_users" ("facebookid" text, "useremail" text, "username" text) RETURNS TABLE (authentication_code text, id integer, key text, stripe_id text) AS '
-- First, select the user:
WITH select_user AS
(SELECT
users.id
FROM
users
WHERE
useremail = users.email),
-- Second, update the user (if user exists):
update_user AS
(UPDATE
users
SET
authentication_code = GEN_RANDOM_UUID(),
authentication_date = current_timestamp,
facebook_id = facebookid
WHERE EXISTS (SELECT * FROM select_user)
AND
useremail = users.email
RETURNING
users.authentication_code,
users.id,
users.key,
users.stripe_id),
-- Third, insert the user (if user does not exist):
insert_user AS
(INSERT INTO
users (authentication_code, authentication_date, email, key, name, facebook_id)
SELECT
GEN_RANDOM_UUID(),
current_timestamp,
useremail,
GEN_RANDOM_UUID(),
COALESCE(username, SUBSTRING(useremail FROM ''([^@]+)'')),
facebookid
WHERE NOT EXISTS (SELECT * FROM select_user)
RETURNING
users.authentication_code,
users.id,
users.key,
users.stripe_id)
-- Finally, select the authentication code, ID, key and Stripe ID:
SELECT
*
FROM
update_user
UNION ALL
SELECT
*
FROM
insert_user' LANGUAGE "sql" COST 100 ROWS 1
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
Realicé el cambio de nombre / reordenamiento en ambas columnas facebook_id
y stripe_id
(se agregó una nueva columna antes de estas, que es la razón del cambio de nombre, pero esta consulta no la toca).
Tener las columnas en un cierto orden es puramente de interés para el orden. Sin embargo, la razón para hacer esta pregunta es preocupante porque un simple cambio de nombre y eliminación de una columna puede provocar problemas reales para alguien que usa funciones en modo de producción (como me sucedió a mí mismo).
Respuestas:
Error probable en 9.6 y 9.6.1
Esto me parece completamente un error ...
No sé por qué sucede, pero puedo confirmar que sucede. Esta es la configuración más simple encontrada que reproduce el problema (en la versión 9.6.0 y 9.6.1).
Después de esta configuración, la siguiente declaración simplemente funciona
En este punto, DEJAMOS una columna:
Este cambio hace que la siguiente declaración genere un error
que es lo mismo que mencionó @Andy:
Dejar caer y recrear la función NO resuelve el problema.
VACÍO COMPLETO (la tabla o la base de datos completa) no resuelve el problema.
El informe de error se pasó a la lista de correo de PostgreSQL apropiada y obtuvimos una respuesta muy rápida :
Versión 9.6.2
En 2017-03-06, puedo confirmar que no puedo reproducir este comportamiento en la versión 9.6.2. Es decir, el error parece haber sido corregido en esta versión.
ACTUALIZAR
Por comentario de @Jana: "Puedo confirmar que el error está presente en 9.6.1 y se corrigió en 9.6.2. La corrección también aparece en el sitio web de publicación de postgres : la consulta de corrección espuria" proporciona un valor para los errores de una columna caída durante INSERTAR o ACTUALIZAR en una tabla con una columna caída "
fuente
Sé que probablemente hayas escuchado esto antes, pero esta es una idea horrible.
SELECT *
Entonces, si no importa en absoluto no lo disuade y reconocemos que solo estamos jugando Photoshop con estructura de filas y obsesionados con la visualización, expliquemos algunas cosas más.
CREATE TABLE
(aunque sería una prioridad mucho mayor)Entonces PostgreSQL es una mala capa de visualización. Además de todo eso, si
ALTER
bien funciona, no debes templar al dragón. AmbosALTER TABLE
, y la sección CAVEAT hacen mención de esto,Y, si todo eso no es suficiente, y aún así quieres fingir que es una buena idea, más bien una idea horrible. Entonces prueba esto,
pg_dump -t
BEGIN
una transacciónDROP
la vieja mesa por completo,RENAME
la tabla temporal a la tabla de productos.COMMIT
Si todo eso suena excesivo, tenga en cuenta que la actualización de las filas en la base de datos requiere reescribir las filas (suponiendo que no sean TOSTADAS . Debe analizar los datos y reconstruir el esquema de la tabla, pero de cualquier manera debe reescribir la fila. Si tuviera que hacer esta tarea, así es como lo haría.
Pero, todo esto está hablando en general. Nadie ha reproducido tus resultados.
Has dado un caso de prueba que no podemos ejecutar
Y no nos ha dicho la versión exacta en la que se encuentra.
fuente
Resolví este error haciendo una copia de seguridad y restaurando mi base de datos.
Pasos para Heroku
heroku maintenance:on
heroku pg:backups:capture
heroku pg:backups:restore
heroku restart
heroku maintenance:off
fuente
Me encontré con este error también. Para aquellos que no quieren hacer una copia de seguridad / restaurar completamente su base de datos. Sepa que simplemente copiar la tabla funciona. Sin embargo, no hay una forma "mágica" de copiar una tabla. Lo hice usando:
Después de eso, aún necesitará recrear manualmente sus índices, claves foráneas y valores predeterminados. Volver a crear la mesa de esta manera hizo que el error desapareciera.
fuente