ถ้าฉันมีตารางที่มี 3 คอลัมน์ - พูด A, B และ D - และฉันต้องแนะนำใหม่ - พูด C เพื่อแทนที่ตำแหน่งปัจจุบันของ D ฉันจะใช้วิธีการต่อไปนี้:
- แนะนำ 2 คอลัมน์ใหม่เป็น C และ D2
- คัดลอกเนื้อหาของ 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
(มีการเพิ่มคอลัมน์ใหม่ก่อนหน้านี้ซึ่งเป็นสาเหตุของการเปลี่ยนชื่อ แต่ไม่ได้รับการแตะต้องจากคิวรีนี้)
การมีคอลัมน์ในลำดับที่แน่นอนหมดความสนใจในการสั่งซื้อ อย่างไรก็ตามเหตุผลในการถามคำถามนี้ไม่ได้กังวลว่าการเปลี่ยนชื่อและลบคอลัมน์อย่างง่ายอาจทำให้เกิดปัญหาจริงสำหรับใครบางคนที่ใช้ฟังก์ชั่นในโหมดการผลิต (เหมือนที่เกิดขึ้นกับตัวเอง)