- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我希望能得到一些帮助来改进将作为数组传入的 UPSERTing 行的方法。我在 Postgres 11.4 上部署了 RDS。我有很多表格要整理,但我从一个简单的表格开始进行实验:
BEGIN;
DROP TABLE IF EXISTS "data"."item" CASCADE;
CREATE TABLE IF NOT EXISTS "data"."item" (
"id" uuid NOT NULL DEFAULT NULL,
"marked_for_deletion" boolean NOT NULL DEFAULT false,
"name_" citext NOT NULL DEFAULT NULL,
CONSTRAINT item_id_pkey
PRIMARY KEY ("id")
);
CREATE INDEX item_marked_for_deletion_ix_bgin ON "data"."item" USING GIN("marked_for_deletion") WHERE marked_for_deletion = true;
ALTER TABLE "data"."item" OWNER TO "user_change_structure";
COMMIT;
到目前为止,函数看起来像这样:
DROP FUNCTION IF EXISTS data.item_insert_array (item[]);
CREATE OR REPLACE FUNCTION data.item_insert_array (data_in item[])
RETURNS int
AS $$
INSERT INTO item (
id,
marked_for_deletion,
name_)
SELECT
d.id,
d.marked_for_deletion,
d.name_
FROM unnest(data_in) d
ON CONFLICT(id) DO UPDATE SET
marked_for_deletion = EXCLUDED.marked_for_deletion,
name_ = EXCLUDED.name_;
SELECT cardinality(data_in); -- array_length() doesn't work. ¯\_(ツ)_/¯
$$ LANGUAGE sql;
ALTER FUNCTION data.item_insert_array(item[]) OWNER TO user_bender;
调用看起来像这样:
select * from item_insert_array(
array[
('2f888809-2777-524b-abb7-13df413440f5',true,'Salad fork'),
('f2924dda-8e63-264b-be55-2f366d9c3caa',false,'Melon baller'),
('d9ecd18d-34fd-5548-90ea-0183a72de849',true,'Fondue fork')
]::item[]
);
我正在尝试为 UPSERT 开发一个注入(inject)安全且性能良好的系统。我将替换一个更简单的多值插入,其中 INSERT 完全在客户端组成。意思是,我不能确定在连接文本时我没有引入缺陷。 (我在这里问过这个问题:Postgres bulk insert/update that's injection-safe. Perhaps a function that takes an array?)
在各种优秀答案的帮助下,我已经走到了这一步:
https://dba.stackexchange.com/questions/224785/pass-array-of-mixed-type-into-stored-function
我不是在尝试所有这些的最复杂版本,例如,我很好每个表有一个函数,很好每个数组元素具有完全相同的格式。整理好基本模式后,我将编写代码生成器来构建我需要的一切。所以,我认为我不需要 VARIADIC 参数列表、多态元素或一切都打包为 JSON。 (虽然我会不时地需要插入 JSON,但这只是数据。)
我仍然可以使用一些补救帮助来解决一些问题:
上面的代码是注入(inject)安全的吗,还是我需要在 PL/pgSQL 中重写它以使用 FOREACH 和 EXECUTE...USING 或 FORMAT 或 quote_literal 等?
我将输入数组设置为 item[]。这很好,因为我正在传递这个小表的所有字段,但我并不总是想传递所有列。我以为我可以使用 anyarray 作为函数中的类型,但我无法弄清楚在那种情况下如何传入数组。是否有通用的数组类型?我可以为这些函数中的每一个创建自定义类型,但我宁愿不这样做。主要是因为我只会在那种情况下使用该类型。
将其实现为过程而不是函数似乎更有意义,这样我就可以在函数内处理事务。我是否基于此?
返回什么有任何风格(或其他)?我现在返回一个计数,这至少有点用。
我在这里有点滑雪,所以任何一般性评论都将不胜感激。为清楚起见,我所追求的是一种安全地插入多行并具有良好性能的模式,理想情况下,不涉及每个函数或 COPY 的自定义类型。
谢谢!
最佳答案
我们有很多不同的服务器推送到 Postgres 中的中央表,这又增加了一个问题。如果我向表中添加一列会怎样:
ALTER TABLE item ADD COLUMN category citext;
现在表格有四列而不是三列。
我所有现有的推送立即中断,因为现在输入中缺少一列。我们可以同时更新所有服务器的可能性为 0%,因此这是不可能的。
一个解决方案是为表的每个版本创建一个自定义类型:
CREATE TYPE item_v1 AS (
id uuid,
marked_for_deletion boolean,
name_ citext);
CREATE TYPE item_v2 AS (
id uuid,
marked_for_deletion boolean,
name_ citext,
category citext);
然后是每种类型的函数:
CREATE OR REPLACE FUNCTION data.item_insert_array (data_in item_v1[])
etc.
CREATE OR REPLACE FUNCTION data.item_insert_array (data_in item_v2[])
etc.
我猜你可能有一个巨大的方法,它接受任何数组并使用 CASE 来整理要运行的代码。出于一些原因我不会那样做,但我想你可以。 (我已经看到这种方法很快就会在不止一种语言中变得坏疽。)
所有这些看起来都是相当多的工作。我缺少更简单的技术吗?我想象您可以提交结构化文本/XML/JSON,解压缩并从那里开始工作。但我不会在“更简单”下归档。
显然,我仍在此处进行设计。我已经编写了足够多的代码来测试我所展示的内容,但我想在返回并在数十个表上实现它之前理清细节。
感谢您的帮助。
关于arrays - 改进基于输入数组的 UPSERT 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57517980/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!