นี่คือการค้นพบที่น่าสนใจ โดยปกติแล้ว NULL จะไม่มีประเภทข้อมูลที่สันนิษฐานดังที่คุณเห็นที่นี่:
SELECT pg_typeof(NULL);
pg_typeof
───────────
unknown
การเปลี่ยนแปลงนี้เมื่อVALUES
ตารางเข้ามาในรูปภาพ:
SELECT pg_typeof(core) FROM (
VALUES (NULL)
) new_values (core);
pg_typeof
───────────
text
พฤติกรรมนี้อธิบายไว้ในซอร์สโค้ดที่https://doxygen.postgresql.org/parse__coerce_8c.html#l01373 :
/*
* If all the inputs were UNKNOWN type --- ie, unknown-type literals ---
* then resolve as type TEXT. This situation comes up with constructs
* like SELECT (CASE WHEN foo THEN 'bar' ELSE 'baz' END); SELECT 'foo'
* UNION SELECT 'bar'; It might seem desirable to leave the construct's
* output type as UNKNOWN, but that really doesn't work, because we'd
* probably end up needing a runtime coercion from UNKNOWN to something
* else, and we usually won't have it. We need to coerce the unknown
* literals while they are still literals, so a decision has to be made
* now.
*/
(ใช่ซอร์สโค้ดของ PostgreSQL นั้นค่อนข้างง่ายต่อการทำความเข้าใจและสถานที่ส่วนใหญ่ด้วยความเห็นที่ยอดเยี่ยม)
อย่างไรก็ตามทางออกอาจเป็นดังต่อไปนี้ สมมติว่าคุณกำลังสร้างรายการVALUES
ที่ตรงกับคอลัมน์ทั้งหมดของตารางที่ระบุ (ดูหมายเหตุที่สองด้านล่างสำหรับกรณีอื่น ๆ ) จากตัวอย่างของคุณเคล็ดลับเล็ก ๆ อาจช่วยได้:
SELECT (x).* FROM (VALUES ((TRUE, NULL, 1234)::fields)) t(x);
active │ core │ id
────────┼──────┼──────
t │ │ 1234
ที่นี่คุณใช้นิพจน์แถวที่เลือกใช้กับประเภทของตารางแล้วแตกออกเป็นตาราง
ขึ้นอยู่กับข้างต้นคุณUPDATE
อาจมีลักษณะเช่น
UPDATE fields AS t set active = (x).active, core = (x).core
FROM ( VALUES
((true, NULL, 3419)::fields),
((false, NULL, 3420)::fields)
) AS new_values(x) WHERE (x).id = t.id;
หมายเหตุ:
- ฉันลบเครื่องหมายคำพูดคู่เพื่อให้มนุษย์อ่านง่ายขึ้น แต่คุณสามารถเก็บไว้ได้เพราะมันช่วยเมื่อสร้างชื่อ (คอลัมน์)
- หากคุณต้องการเพียงชุดย่อยของคอลัมน์คุณสามารถสร้างประเภทที่กำหนดเองสำหรับวัตถุประสงค์นี้ ใช้พวกเขาในลักษณะเดียวกับที่คุณต้องการข้างต้น (ที่ฉันใช้ประเภทที่สร้างขึ้นโดยอัตโนมัติด้วยตารางโดยถือโครงสร้างแถวหลัง)
ดูสิ่งที่ทั้งการทำงานในdbfiddle
Cannot cast type boolean to bigint in column 1
(ข้อผิดพลาดชี้ที่ :: ระหว่างคำสั่งแรกของเขตข้อมูล)