สิ่งนี้เป็นสิ่งที่คาดหวังพฤติกรรมของเอกสาร
ทอมเลนอธิบายไว้ที่นี่
เอกสารในคู่มือที่นี่:
คำสั่งในการปรับเปลี่ยนข้อมูลWITH
จะถูกดำเนินการเพียงครั้งเดียวและ
ดำเนินการให้เสร็จสิ้นเสมอโดยไม่ขึ้นอยู่กับว่าข้อความค้นหาหลักอ่านผลลัพธ์ทั้งหมดของพวกเขาหรือไม่ แจ้งให้ทราบว่าเรื่องนี้จะแตกต่างจากกฎสำหรับSELECT
ในWITH
: ตามที่ระบุไว้ในส่วนก่อนหน้านี้การดำเนินการจะดำเนินการเพียงเท่าที่แบบสอบถามหลักเรียกร้องเอาท์พุทSELECT
เหมืองเน้นหนัก "ข้อมูลการปรับเปลี่ยน" เป็นINSERT
, UPDATE
และDELETE
คำสั่ง (ตรงข้ามกับSELECT
.) คู่มืออีกครั้ง:
คุณสามารถใช้งบข้อมูลการปรับเปลี่ยน ( INSERT
, UPDATE
หรือDELETE
) WITH
ใน
ฟังก์ชั่นที่เหมาะสม
CREATE OR REPLACE FUNCTION public.__post_users_id_coin (_coins integer, _userid integer)
RETURNS TABLE (id integer) AS
$func$
UPDATE users u
SET coin = u.coin + _coins -- see below
WHERE u.id = _userid
RETURNING u.id
$func$ LANGUAGE sql COST 100 ROWS 1000 STRICT;
ฉันลดลงเริ่มต้น (เสียง) และคำสั่ง
เป็นคำพ้องความหมายสั้นSTRICT
ๆRETURNS NULL ON NULL INPUT
ตรวจสอบให้แน่ใจว่าชื่อพารามิเตอร์นั้นไม่ขัดแย้งกับชื่อคอลัมน์ ฉันเติมด้วย_
แต่นั่นเป็นเพียงความชอบส่วนตัวของฉัน
ถ้าฉันcoin
สามารถNULL
แนะนำ:
SET coin = CASE WHEN coin IS NULL THEN _coins ELSE coin + _coins END
ถ้าusers.id
เป็นคีย์หลักแล้วค่าRETURNS TABLE
มิได้ROWs 1000
ทำให้รู้สึกใด ๆ สามารถอัพเดต / ส่งคืนได้เพียงแถวเดียว แต่นั่นคือทั้งหมดที่อยู่ข้างจุดหลัก
โทรเหมาะสม
ไม่มีเหตุผลที่จะใช้ส่วนRETURNING
คำสั่งและค่าส่งคืนจากฟังก์ชันของคุณหากคุณจะเพิกเฉยกับค่าที่ส่งคืนในการโทรอยู่ดี นอกจากนี้ยังไม่มีเหตุผลที่จะแยกย่อยแถวที่ส่งคืนด้วยSELECT * FROM ...
หากคุณไม่สนใจ
เพียงแค่คืนค่าสเกลาร์สเกลาร์ ( RETURNING 1
) กำหนดฟังก์ชันเป็นRETURNS int
(หรือปล่อยRETURNING
พร้อมกันแล้วทำRETURNS void
) และเรียกมันด้วยSELECT my_function(...)
วิธีการแก้
ตั้งแต่คุณ ...
ไม่สนใจผลลัพธ์
.. เพียงแค่SELECT
รูปแบบคงที่ CTE มันรับประกันว่าจะถูกดำเนินการตราบใดที่มีการอ้างอิงในด้านนอกSELECT
(โดยตรงหรือโดยอ้อม)
WITH test AS (SELECT __post_users_id_coin(10, 1))
SELECT 1 FROM test;
หากคุณมีฟังก์ชั่นset-returnและยังไม่สนใจเอาต์พุต:
WITH test AS (SELECT * FROM __post_users_id_coin(10, 1))
SELECT 1 FROM test LIMIT 1;
ไม่จำเป็นต้องส่งคืนมากกว่า 1 แถว ฟังก์ชั่นยังคงเรียกว่า
ในที่สุดก็ไม่มีความชัดเจนว่าทำไมคุณต้องเริ่มต้น CTE อาจเป็นเพียงการพิสูจน์แนวคิด
ที่เกี่ยวข้องอย่างใกล้ชิด:
คำตอบที่เกี่ยวข้องกับ SO:
และพิจารณา: