變量使用實例
 
                  更新時間 2025-02-14 10:25:08
                    
 
                    最近更新時間: 2025-02-14 10:25:08
                  
   分享文章 
本頁介紹天翼云TeleDB數據庫存儲過程開發的變量使用實例。
 變量聲明語法
name [ CONSTANT ] type [ COLLATE collation_name ] [ NOT NULL ] [ { DEFAULT | := | = } expression ];如果給定DEFAULT子句,它會指定進入該塊時分配給該變量的初始值。如果沒有給出 DEFAULT子句,則該變量被初始化為SQL空值。
CONSTANT選項阻止該變量在初始化之后被賦值,這樣它的值在塊的持續期內保持不變。
COLLATE選項指定用于該變量的一個排序規則。如果指定了NOT NULL,對該變量賦值為空值會導致一個運行時錯誤。所有被聲明為NOT NULL的變量必須被指定一個非空默認值。等號(=)可以被用來代替 PL/SQL-兼容的:=。
定義一個普通變量
teledb=# CREATE OR REPLACE PROCEDURE ordinary_var() AS
$$
DECLARE
    --所有變量的聲明都要放在這里,建議變量以v_開頭,參數以a_開頭
    v_int integer := 1;
    v_text text;    
BEGIN
    v_text = 'teledb_pg';
    RAISE NOTICE 'v_int = %',v_int;  
    RAISE NOTICE 'v_text = %',v_text;  
END;
$$
LANGUAGE plpgsql;
CREATE PROCEDURE
teledb=# CALL ordinary_var();                         
NOTICE:  v_int = 1
NOTICE:  v_text = teledb_pg
CALL
teledb=# 定義CONSTANT 變量
teledb=# CREATE OR REPLACE PROCEDURE p_constant()  AS
$$
DECLARE    
    v_int CONSTANT integer := 1;     
BEGIN
    RAISE NOTICE 'v_int = %',v_int;  
END;
$$
LANGUAGE plpgsql;
CREATE PROCEDURE
teledb=# CALL p_constant();
NOTICE:  v_int = 1
CALLCONSTANT 不能再次賦值
teledb=# CREATE OR REPLACE PROCEDURE p_constant()  AS
$$
DECLARE    
    v_int CONSTANT integer := 1;     
BEGIN
    RAISE NOTICE 'v_int = %',v_int;  
v_int = 10;
END;
$$
LANGUAGE plpgsql;
ERROR:  "v_int" is declared CONSTANT
LINE 7: v_int = 10;
        ^
teledb=#定義NOT NULL變量
teledb=# CREATE OR REPLACE PROCEDURE p_not_null_var() AS
$$
DECLARE    
    v_int integer NOT NULL := 1;     
BEGIN
    RAISE NOTICE 'v_int = %',v_int;  
    SELECT NULL INTO v_int;
    RAISE NOTICE 'v_int = %',v_int;  
END;
$$
LANGUAGE plpgsql;
CREATE PROCEDURE
teledb=# CALL p_not_null_var();
NOTICE:  v_int = 1
ERROR:  null value cannot be assigned to variable "v_int" declared NOT NULL
CONTEXT:  PL/pgSQL function p_not_null_var() line 6 at SQL statement
teledb=#  
定義為NOT NULL變量,則該變量受NOT NULL約束
定義COLLATE 變量
按unicode 值對比大小。
teledb=# CREATE OR REPLACE PROCEDURE p_collate_unicode() AS
$$
DECLARE    
    v_txt1 TEXT COLLATE "C" := '嚴';     
    v_txt2 TEXT COLLATE "C" := '豐';     
BEGIN
IF v_txt1 > v_txt2 THEN
    RAISE NOTICE ' % > % ',v_txt1,v_txt2;
ELSE
    RAISE NOTICE ' % > % ',v_txt2,v_txt1;
END IF; 
END;
$$
LANGUAGE plpgsql;
CREATE PROCEDURE
teledb=# CALL p_collate_unicode();
NOTICE:   豐 > 嚴 
CALL
teledb=#
teledb=# select '嚴'::bytea;
  bytea   
----------
 \xe4b8a5
(1 row)
teledb=# select '豐'::bytea;
  bytea   
----------
 \xe4b8b0
(1 row)按漢字的拼音對比大小。
teledb=# CREATE OR REPLACE PROCEDURE p_collate_pinyin() AS
$$
DECLARE    
    v_txt1 TEXT COLLATE "zh_CN.utf8" := '嚴';     
    v_txt2 TEXT COLLATE "zh_CN.utf8" := '豐';     
BEGIN
    IF v_txt1 > v_txt2 THEN
    RAISE NOTICE ' % -> % ',v_txt1,v_txt2;
    ELSE
    RAISE NOTICE ' % -> % ',v_txt2,v_txt1;
    END IF; 
END;
$$
LANGUAGE plpgsql;
CREATE PROCEDURE
teledb=# CALL p_collate_pinyin();                         
NOTICE:   嚴 -> 豐 
CALL
teledb=#變量賦值
teledb=# CREATE OR REPLACE PROCEDURE p_setval()  AS
$$
DECLARE    
    --定義時賦值
    v_int1 integer = 1; 
    --使用 :=兼容于plsql
    v_int2 integer := 1; 
    v_txt1 text;
    v_float float8;
    --使用查詢賦值
    v_relname text = (select relname FROM pg_class LIMIT 1);    
    v_relpages integer;
    v_rec RECORD;
BEGIN           
    --在函數體中賦值
    v_txt1 = 'teledb_pg';    
    v_float = random();
    --使用查詢賦值的另一種方式
    SELECT relname,relpages INTO v_relname,v_relpages FROM  pg_class ORDER BY random() LIMIT 1;
    RAISE NOTICE 'v_relname = % , relpages = %',v_relname,v_relpages;
END;
$$
LANGUAGE plpgsql;
CREATE PROCEDURE
teledb=# CALL p_setval();
NOTICE:  v_relname = pg_toast_17220_index , relpages = 1
CALL
teledb=#BULK COLLECT
BULK COLLECT 將一個查詢結果集保存起來。
示例1
teledb=# create table t5(f1 integer,f2 varchar(10));
CREATE TABLE
teledb=# insert into t5 values(1,'teledb_pg1'); 
INSERT 0 1
teledb=# insert into t5 values(2,'teledb_pg2'); 
INSERT 0 1
teledb=# create or replace procedure p_bulk_collect()
AS 
$$
declare  
    TYPE t5list IS TABLE OF t5.f2%TYPE;
    t5s t5list;
BEGIN
    SELECT f2 BULK COLLECT INTO t5s FROM t5;    
    FOR i IN t5s.FIRST .. t5s.LAST
    LOOP        
        raise notice '%',t5s[i];
    END LOOP;  
END
$$language plpgsql;
NOTICE:  type reference t5.f2%TYPE converted to character varying
CREATE PROCEDURE
teledb=# CALL p_bulk_collect();
NOTICE:  teledb_pg1
NOTICE:  teledb_pg2
CALL示例2
teledb=# create table tbl_person(id integer, name text, tdd int);
CREATE TABLE
teledb=# insert into tbl_person values(1,'teledb_pg',1);
insert into tbl_person values(2,'pgxz',1);
INSERT 0 1
teledb=# insert into tbl_person values(2,'pgxz',1);
INSERT 0 1
teledb=# insert into tbl_person values(3,'pg',2);
INSERT 0 1
teledb=# create or replace procedure p_bulkcollect_select_into(a_tdd integer) AS 
$$
declare        
   type TAPersonlist is table of tbl_person%rowtype;        
   vpa TAPersonlist;
   rp tbl_person%rowtype;
begin        
   select * bulk collect into vpa from tbl_person where tdd = a_tdd;
   raise notice 'count=%', vpa.count;
   for i in vpa.first..vpa.last loop
       rp = vpa[i];
       raise notice 'loop=%', i;
       raise notice 'vname=%', rp.name;
   end loop;
   raise notice 'vpa.count=%',vpa.count;
end;
$$language plpgsql;
CREATE PROCEDURE
teledb=# CALL p_bulkcollect_select_into(1);
NOTICE:  count=2
NOTICE:  loop=1
NOTICE:  vname=teledb_pg
NOTICE:  loop=2
NOTICE:  vname=pgxz
NOTICE:  vpa.count=2
CALL
teledb=#