ind*_*ago 8 postgresql datatypes functions postgresql-9.1 array
我有一张桌子叫书
CREATE TABLE book
(
id smallint NOT NULL DEFAULT 0,
bname text,
btype text,
bprices numeric(11,2)[],
CONSTRAINT key PRIMARY KEY (id )
)
Run Code Online (Sandbox Code Playgroud)
和一个函数 save_book
CREATE OR REPLACE FUNCTION save_book(thebook book)
RETURNS text AS
$BODY$
DECLARE
myoutput text :='Nothing has occured';
BEGIN
update book set
bname=thebook.bname,
btype=thebook.btype,bprices=thebook.bprices WHERE id=thebook.id;
IF FOUND THEN
myoutput:= 'Record with PK[' || thebook.id || '] successfully updated';
RETURN myoutput;
END IF;
BEGIN
INSERT INTO book values(thebook.id,thebook.bname,thebook.btype,
thebook.bprices);
myoutput:= 'Record successfully added';
END;
RETURN myoutput;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
Run Code Online (Sandbox Code Playgroud)
现在当我调用函数时
SELECT save_book('(179,the art of war,fiction,{190,220})'::book);
Run Code Online (Sandbox Code Playgroud)
我得到了错误
ERROR: malformed array literal: "{190"
SQL state: 22P02
Character: 18
Run Code Online (Sandbox Code Playgroud)
我不明白,因为我没有看到数组格式有任何错误,有什么帮助吗?
这种事情变得复杂了。我现在正在做一些相关的项目。基本的调整是 PostgreSQL 使用一种在元组表示中内部使用双引号来表示文字值的格式,因此:
SELECT save_book('(179,the art of war,fiction,"{190,220}")'::book);
Run Code Online (Sandbox Code Playgroud)
应该管用。本质上,一个巧妙的技巧是创建一个 csv 并包含在元组或数组标识符中。最大的问题是您必须处理转义(根据需要在每个级别加倍引号)。所以下面是完全等效的:
SELECT save_book('(179,"the art of war","fiction","{""190"",""220""}")'::book);
Run Code Online (Sandbox Code Playgroud)
第二种方法是使用行构造函数:
SELECT save_book(row(179,'the art of war','fiction', array[190,220])::book);
Run Code Online (Sandbox Code Playgroud)
第一个解决方案的明显优势是能够利用现有的编程框架进行 CSV 生成和转义。第二个是 SQL 中最干净的。它们可以混合搭配。
如果您想知道行类型的正确语法,请询问 Postgres。它应该知道:
SELECT b FROM book b LIMIT 1; -- or: WHERE id = 179;
Run Code Online (Sandbox Code Playgroud)
它将以有效格式返回您的行的文本表示:
(179,"the art of war",fiction,"{190,220}")
Run Code Online (Sandbox Code Playgroud)
列的值表示为一个不带引号的逗号分隔列表,用括号括起来。
如果可能存在歧义,则在值周围使用双引号 - 包括带有空格的文本。虽然在这种特殊情况下,周围的双引号"the art of war"是可选的,但周围的双引号"{190,220}"对于数组来说是必需的。
将字符串括在单引号中,修改并测试:
SELECT '(333,the art of war,fiction,"{191,220,235}")'::book
Run Code Online (Sandbox Code Playgroud)
考虑我们在前面的相关问题下讨论的内容:UPSERT 函数中的复合类型问题
一个单独的块(BEGIN .. END;如果你想赶上)是唯一有用EXCEPTION的INSERT可能引起。由于具有异常的块会带来一些开销,因此有一个可能永远不会进入的单独块是有意义的:
CREATE OR REPLACE FUNCTION save_book(thebook book)
RETURNS text AS
$BODY$
BEGIN
UPDATE book
SET bname = thebook.bname
,btype = thebook.btype
,bprices = thebook.bprices
WHERE id = thebook.id;
IF FOUND THEN
RETURN format('Record with PK[%s] successfully updated', thebook.id);
END IF;
BEGIN
INSERT INTO book SELECT (thebook).*;
RETURN format('Record with PK[%s] successfully inserted', thebook.id);
EXCEPTION WHEN unique_violation THEN
UPDATE book
SET bname = thebook.bname
,btype = thebook.btype
,bprices = thebook.bprices
WHERE id = thebook.id;
END;
RETURN format('Record with PK[%s] successfully updated', thebook.id);
END
$BODY$ LANGUAGE plpgsql
Run Code Online (Sandbox Code Playgroud)
否则,简化:
CREATE OR REPLACE FUNCTION save_book(thebook book)
RETURNS text AS
$BODY$
BEGIN
UPDATE book
SET bname = thebook.bname
,btype = thebook.btype
,bprices = thebook.bprices
WHERE id = thebook.id;
IF FOUND THEN
RETURN format('Record with PK[%s] successfully updated', thebook.id);
END IF;
INSERT INTO book SELECT (thebook).*;
RETURN format('Record with PK[%s] successfully inserted', thebook.id);
END
$BODY$ LANGUAGE plpgsql
Run Code Online (Sandbox Code Playgroud)
我也简化了你的INSERT陈述。在给定的情况下,从 INSERT 中省略列列表是安全的。
| 归档时间: |
|
| 查看次数: |
9762 次 |
| 最近记录: |