我可以考虑三种方式。两个真的很简单,一个很复杂但与(variable1, variable2)相关。
-
CASE 用法(简单)
-
JSONBusage(简单)
-
TYPE 用法(复杂)
第一个选项:CASE 用法
这是最简单的,但不是真正优化的选项。
当您使用SELECT vals INTO vars 时,您必须拥有相同数量的 val 和 var。因此,在此选项中,每个值都需要一个 CASE。
-- CASE QUERY
DO $$
DECLARE
-- control var
var integer := 1;
-- result vars
var1 integer := 1;
var2 integer := 2;
var3 integer := 3;
var4 integer := 4;
-- final values
val1 integer;
val2 integer;
BEGIN
SELECT
CASE var -- CASE for val1
WHEN 1 THEN var1
WHEN 2 THEN var3 END,
CASE var -- CASE for val2
WHEN 1 THEN var2
WHEN 2 THEN var4 END
INTO val1,val2;
RAISE NOTICE '%',val1; -- outputs: 1
RAISE NOTICE '%',val2; -- outputs: 2
END;$$
如果 var 更改为 '2',则输出将是 3 和 4。
在这里你改变你的代码
CASE var
WHEN 1 THEN
variable1, variable2
WHEN 2 THEN
variable3, variable4
到
CASE var -- CASE for val1
WHEN 1 THEN variable1
WHEN 2 THEN variable3 END,
CASE var -- CASE for val2
WHEN 1 THEN variable2
WHEN 2 THEN variable4 END
如果添加更多变量,就会添加更多案例。
第二个选项:JSONB 用法
此选项是最佳方法,因为您不必为许多 CASE 子句编写代码,也不必为该过程创建额外的步骤。
基本上,您使用 JSONB 变量,其中包含您需要的所有变量,如下所示:
{
"val1": 1,
"val2": 2
}
这就是你的做法:
-- USING JSONB
DO $$
DECLARE
-- control var
var integer := 1;
-- result vars
var1 integer := 1;
var2 integer := 2;
var3 integer := 3;
var4 integer := 4;
-- JSON var that will have val1 and val2 data
jsonvar jsonb;
BEGIN
SELECT CASE var
WHEN 1 THEN CAST('{"val1":'||var1||',"val2":'||var2||'}' as jsonb)
WHEN 2 THEN CAST('{"val1":'||var3||',"val2":'||var4||'}' as jsonb) END
INTO jsonvar;
RAISE NOTICE '%',jsonvar->>'val1'; -- outputs: 1
RAISE NOTICE '%',jsonvar->>'val2'; -- outputs: 2
END;$$
请注意,此处您将 JSON 对象插入到类型为 JSONB 的变量中。将相同数量的 vars 转换为 vals。
由于 JSON 确实是一个灵活的对象,要添加更多变量,您只需相应地调整 JSON。
在 PostgreSQL 中最好使用JSONB 而不是普通的JSON。手册指出:
json 数据类型存储输入文本的精确副本,其中
处理函数必须在每次执行时重新解析;而jsonb数据
以分解的二进制格式存储,使其速度稍慢
输入由于增加了转换开销,但明显更快
过程,因为不需要重新分析。 jsonb 还支持索引,
这可能是一个显着的优势。
第三个选项:TYPE 用法
这个选项比较复杂,因为我们输入的是RECORD 地形。是的,PostgreSQL 中的(data1,data2) 是RECORD。什么是记录?简单来说,就是一个没有数据结构的ROW。
RECORD 是什么意思?好吧,说清楚,当你创建一个表时,例如:
CREATE TABLE data(val1 integer,val2 integer);
如果你想将数据插入到“数据”表中,你必须插入一个记录,所以当你这样做时:
INSERT INTO data(val1,val2) VALUES (1,2);
您将RECORD (1,2) 插入到数据中。
注意 1 和 2 在 括号 (1,2) 内。因此,当您编写 (variable1,variable2) 时,您将创建一个包含变量 1 和变量 2 的 RECORD。
根据说明书
记录变量类似于行类型变量,但它们没有预定义的结构...
RECORD 不是真正的数据类型,只是一个占位符。
这就是问题所在。 RECORD 没有结构,所以 PostgreSQL 不知道如何解析它。当您使用INSERT INTO 时,您告诉PostgreSQL 结构,因此记录采用表的结构(上一个示例)。
当你这样做时:
SELECT
CASE var
WHEN 1 THEN
(variable1, variable2)
WHEN 2 THEN
(variable3, variable4)
您选择了RECORD。
为了简化它,如果你使用SELECT (1,2),你会得到:
row (record)
------------
(1,2)
如何将结构分配给 ROW?好吧,你使用SELECT,FOR,或者你使用TYPE。 SELECT 和FOR 的使用与INSERT INTO 类似,你知道数据结构。在这种情况下,没有引用,因此必须使用 TYPE。
在 PostgreSQL 中,您可以创建个人数据类型。因此,您可以这样做:
CREATE TYPE mytype AS (val1 integer, val2 integer);-- execute only once
类似于表,您可以创建一个 TYPE 一次,该 TYPE 在整个数据库中都可用。要删除你刚刚做的类型DROP TYPE mytype;
mytype 具有变量所需的两个值,就像一个表一样,TYPE 可以具有任何数据类型的任何“列”。
现在,如果你使用SELECT (1,2)::mytype,你会得到:
row (record)
------------
(1,2)
还是一行,因为PostgreSQL不知道怎么解析。
但如果你这样做 SELECT * FROM (VALUES(1,2)) AS mytype(val1,val2); 你会得到
val1 | val2
------+------
1 | 2
这是因为你告诉 PostgreSQL 如何解析它(注意使用VALUES)。
这表明将结构分配给记录行并不容易。但有可能如下图:
-- USING TYPES
-- Requires mytype created
DO $$
DECLARE
-- control var
var integer := 1;
-- result vars
var1 integer := 1;
var2 integer := 2;
var3 integer := 3;
var4 integer := 4;
-- final values
val1 integer;
val2 integer;
BEGIN
SELECT x[1].val1,x[1].val2
FROM(
SELECT ARRAY(
SELECT CASE var
WHEN 1 THEN (var1,var2)::mytype
WHEN 2 THEN (var3,var4)::mytype END
)::mytype[] AS x
)dataset
INTO val1,val2;
RAISE NOTICE '%',val1; -- outputs: 1
RAISE NOTICE '%',val2; -- outputs: 2
END;$$
关键部分是使用ARRAY。
当你执行时:
SELECT x.val1,x.val2
FROM(
SELECT CASE 1
WHEN 1 THEN (1,2)::mytype
WHEN 2 THEN (3,4)::mytype END AS X
)dataset
你得到这个错误:
ERROR: missing FROM-clause entry for table "x"
PostgreSQL 不知道如何解析它,所以你告诉 PostgreSQL 通过一个 ARRAY 来获取它。
SELECT
x[1].val1,x[1].val2
FROM(
SELECT ARRAY(
SELECT CASE 1
WHEN 1 THEN (1,2)::mytype
WHEN 2 THEN (4,5)::mytype END
)::mytype[] AS x
) dataset
这个输出:
val1 | val2
------+------
1 | 2
此选项的问题在于您创建的TYPE 是静态的,因此如果您必须更改它,您将不得不删除类型并重新创建它。
但这就是你的做法。第二种选择是最好的,也是一种更现代的方法。