3列(A、B、Dなど)のテーブルがあり、新しい列を導入しなければならなかった場合、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
(新しい列が改名の理由ですが、このクエリで触れていないされ、これらの前に追加されました)。
列を特定の順序にすることは、純粋に順序の対象外です。ただし、この質問をする理由は、列の単純な名前変更と削除が、実稼働モードで関数を使用している誰かに実際の問題を引き起こす可能性があるという懸念からです(自分自身に起こりました)。