A, B 및 D와 같은 3 개의 열이있는 테이블이 있고 D를 현재 위치로 대체하기 위해 C를 말해야하는 경우 다음 방법을 사용합니다.
- C와 D2로 2 개의 새로운 컬럼을 소개합니다.
- D의 내용을 D2로 복사하십시오.
- D를 삭제하십시오.
- D2를 D로 이름을 바꿉니다.
새로운 주문은 A, B, C 및 D입니다.
나는 이것이 지금까지 아무런 문제가 없었기 때문에 이것이 합법적 인 관행이라고 생각했다.
그러나 오늘 같은 테이블에서 명령문을 수행하는 함수가 다음 오류를 반환했을 때 문제가 발생했습니다.
table row type and query-specified row type do not match
그리고 다음 세부 사항 :
Query provides a value for a dropped column at ordinal position 13
PostgreSQL을 다시 시작하고 여기 와 여기에VACUUM FULL
제안 된대로 함수를 삭제하고 다시 작성 하려고 시도했지만 이러한 솔루션은 작동하지 않았습니다 (시스템 테이블이 변경된 상황을 해결하려고한다는 사실은 제외).
아주 작은 데이터베이스로 작업하는 것이 고급스러워서 데이터베이스를 내보내고 삭제 한 다음 다시 가져 와서 내 기능 관련 문제 를 해결 했습니다.
나는 다음과 같이 시스템 테이블을 수정하여 손을 더럽히는 pg_attribute
등 의 자연스러운 순서로 엉망이되어서는 안된다는 사실을 알고 있었다 .
Postgres에서 열의 자연 순서를 변경할 수 있습니까?
내 함수에 의해 발생하는 오류로 판단하면 이제 내 방법으로 열 순서를 변경하는 것도 무의미하다는 것을 알았습니다. 내가하고있는 일이 왜 잘못되었는지에 대해 누군가가 빛을 발할 수 있습니까?
Postgres 버전은 9.6.0입니다.
기능은 다음과 같습니다.
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
나는 모두 열 재정렬 / 이름 변경을 수행 facebook_id
하고 stripe_id
(새 열이 이름 변경에 대한 이유이지만,이 쿼리에 감동하지 않는,이 앞에 추가되었다).
특정 순서로 열을 갖는 것은 순전히 관심이 없습니다. 그러나이 질문을하는 이유는 열의 이름을 바꾸고 삭제하면 프로덕션 모드에서 함수를 사용하는 사람에게 실제 문제가 발생할 수 있기 때문에 걱정할 필요가 없습니다.