PostgreSQL使用select into時有無STRICT關鍵字的區別


PostgreSQL使用select into target時有無STRICT關鍵字的區別

 摘自官方文檔http://www.postgres.cn/docs/11/plpgsql-statements.html

 

43.5.3. 執行一個有單一行結果的查詢

一個產生單一行(可能有多個列)的 SQL 命令的結果可以被賦值給一個記錄變量、行類型變量或標量變量列表。這通過書寫基礎 SQL 命令並增加一個INTO子句來達成。例如:

SELECT select_expressions INTO [STRICT] target FROM ...;
INSERT ... RETURNING expressions INTO [STRICT] target; UPDATE ... RETURNING expressions INTO [STRICT] target; DELETE ... RETURNING expressions INTO [STRICT] target; 

其中target可以是一個記錄變量、一個行變量或一個有逗號分隔的簡單變量和記錄/行域列表。PL/pgSQL變量將被替換到該查詢的剩余部分中,並且計划會被緩存,正如之前描述的對不返回行的命令所做的。這對SELECT、帶有RETURNINGINSERT/UPDATE/DELETE以及返回行集結果的工具命令(例如EXPLAIN)。除了INTO子句,SQL 命令和它在PL/pgSQL之外的寫法一樣。

提示

注意帶INTOSELECT的這種解釋和PostgreSQL常規的SELECT INTO命令有很大的不同,后者的INTO目標是一個新創建的表。如果你想要在一個PL/pgSQL函數中從一個SELECT的結果創建一個表,請使用語法CREATE TABLE ... AS SELECT

如果一行或一個變量列表被用作目標,該查詢的結果列必須完全匹配該結果的結構,包括數量和數據類型,否則會發生一個運行時錯誤。當一個記錄變量是目標時,它會自動地把自身配置成查詢結果列組成的行類型。

INTO子句幾乎可以出現在 SQL 命令中的任何位置。通常它被寫成剛好在SELECT命令中的select_expressions列表之前或之后,或者在其他命令類型的命令最后。我們推薦你遵循這種慣例,以防PL/pgSQL的解析器在未來的版本中變得更嚴格。

如果STRICT沒有在INTO子句中被指定,那么target將被設置為該查詢返回的第一個行,或者在該查詢不返回行時設置為空(注意除非使用了ORDER BY,否則第一行”的界定並不清楚)。第一行之后的任何結果行都會被拋棄。你可以檢查特殊的FOUND變量(見第 43.5.5 節)來確定是否返回了一行:

SELECT * INTO myrec FROM emp WHERE empname = myname;
IF NOT FOUND THEN
    RAISE EXCEPTION 'employee % not found', myname;
END IF;

如果指定了STRICT選項,該查詢必須剛好返回一行或者將會報告一個運行時錯誤,該錯誤可能是NO_DATA_FOUND(沒有行)或TOO_MANY_ROWS(多於一行)。如果你希望捕捉該錯誤,可以使用一個異常塊,例如:

BEGIN
    SELECT * INTO STRICT myrec FROM emp WHERE empname = myname;
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            RAISE EXCEPTION 'employee % not found', myname;
        WHEN TOO_MANY_ROWS THEN
            RAISE EXCEPTION 'employee % not unique', myname;
END;

成功執行一個帶STRICT的命令總是會將FOUND置為真。

對於帶有RETURNINGINSERT/UPDATE/DELETE,即使沒有指定STRICTPL/pgSQL也會針對多於一個返回行的情況報告一個錯誤。這是因為沒有類似於ORDER BY的選項可以用來決定應該返回哪個被影響的行。

如果為該函數啟用了If print_strict_params,那么當因為 STRICT的要求沒有被滿足而拋出一個錯誤時,該錯誤消息 的DETAIL將包括傳遞給該查詢的參數信息。可以通過設置 plpgsql.print_strict_params為所有函數更改 print_strict_params設置,但是只有修改后被編譯的函數 才會生效。也可以使用一個編譯器選項來為一個函數啟用它,例如:

CREATE FUNCTION get_userid(username text) RETURNS int
AS $$
#print_strict_params on
DECLARE
userid int;
BEGIN
    SELECT users.userid INTO STRICT userid
        FROM users WHERE users.username = get_userid.username;
    RETURN userid;
END
$$ LANGUAGE plpgsql;

失敗時,這個函數會產生一個這樣的錯誤消息

ERROR:  query returned no rows
DETAIL:  parameters: $1 = 'nosuchuser'
CONTEXT:  PL/pgSQL function get_userid(text) line 6 at SQL statement

 

注意

STRICT選項匹配 Oracle PL/SQL 的SELECT INTO和相關語句的行為。

對於要處理來自於一個 SQL 查詢的結果行的情況,請見第 43.6.6 節


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM