我希望得到一些帮助,以改进作为数组传入的行的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开发一个注入安全且性能良好的系统。我将替换一个更简单的多值插入,其中INSERT完全在客户端组成。这意味着,我不能确定我在连接文本时没有引入缺陷。(我在这里问过这个问题:Postgres批量插入/更新是注入安全的。也许是一个接受数组的函数?)
在各种优秀答案的帮助下,我已经走到了这一步:
https://dba.stackexchange.com/questions/224785/pass-array-of-mixed-type-into-stored-function
https://dba.stackexchange.com/questions/131505/use-array-of-composite-type-as-function-parameter-and-access-it
https://dba.stackexchange.com/questions/225176/how-to-pass-an-array-to-a-plpgsql-function-with-variadic-parameter/
我没有尝试所有这些的最复杂的版本,例如,我可以接受每个表有一个函数,每个数组元素有完全相同的格式。一旦我整理好基本模式,我将编写代码生成器来构建我需要的一切。所以,我不认为我需要可变的参数列表、多态元素或者一切打包成JSON的东西。(虽然我会时不时需要插入JSON,但那只是数据。)
对于一些问题,我仍然可以使用一些补救帮助:
>
上面的代码是注入安全的,还是我需要在PL/pgSQL中重写它,以便将FOREACH与EXECUTE… USING或FORMAT或quote_literal等一起使用?
我正在将输入数组设置为项[]。这很好,因为我正在传递这个小表的所有字段,但我并不总是想传递所有列。我想我可以使用anyarray作为函数中的类型,但我不知道在那种情况下如何传入数组。是否有一个素材类型的通用数组?我可以为每个函数创建自定义类型,但我宁愿不创建。主要是因为我只会在这种情况下使用类型。
似乎将其实现为过程而不是函数是有意义的,以便我可以在函数中处理事务。我是否偏离了基础?
关于要返回的内容是否有任何风格(或其他)?我现在返回一个计数,这至少有点有用。
我在这里有点过了,所以任何一般性评论都将不胜感激。为了清楚起见,我想要的是一个安全插入多行并具有良好性能的模式,理想情况下,不涉及每个函数或COPY的自定义类型。
谢谢!
我认为你的代码很好。回答你的问题:
> < li>
因为您没有使用动态SQL,所以SQL注入会自动保护您的安全。
使用anyarray
很棘手,通常只适用于C函数。您可能能够让它工作,但会很复杂(例如,涉及元数据查询)。
您提供不完整行的想法需要解决一些困难:
如果您希望在冲突情况下只< code >更新某些列,您可以提供一个附加的< code>upd_cols varbit参数来说明应该更新哪些列。
第四列的更新如下所示:
SET col = CASE WHEN get_bit(upd_cols, 3) = 1
THEN EXCLUDED.col
ELSE item.col
END
我认为在代码中使用事务控制没有任何好处。这将降低<罢工>作用过程,因为调用方可能希望调用您的函数,然后由于某些问题回滚操作。
我会RETURNvoid
(或者使用一个过程),因为调用者已经知道数组有多大了。这就是普通DML语句所做的。
我们有很多不同的服务器在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,将其解压缩并从中工作。但我不会把它归入“simpler”
显然,我仍然在这里进行设计。我已经编写了足够的代码来测试我所展示的内容,但是在返回并在数十个表上实现它之前,我想整理一下细节。
谢谢你的任何帮助。
问题内容: 我有K个特征向量,它们全部共享维n,但具有可变维m(nxm)。他们都一起生活在一个清单中。 我正在寻找的是一种聪明的方法,以零填充这些np.arrays的行,以便它们都共享相同的维m。我曾尝试使用np.pad解决它,但我还无法提出一个漂亮的解决方案。朝正确方向的任何帮助或推动将不胜感激! 结果应该使数组看起来像这样: 问题答案: 您可以使用它,它也可以使用指定填充宽度的元组填充数组。为
我有一个Postgres表,在多个列上有一个唯一的约束,其中一个可以为NULL。对于每个组合,我只希望允许该列中有一条空记录。 我有一个upsert查询,当它遇到col2、col3中具有相同值的记录时,我想更新col4: 但是当col3为空时,冲突不会触发。我读过关于使用触发器的文章。请问让冲突触发的最佳解决方案是什么?
我对C很陌生,现在就在做中学习。在课堂材料中,我有以下功能: 几分钟前,我像这样使用了普通for循环:
本文向大家介绍Java基于Scanner对象的简单输入计算功能示例,包括了Java基于Scanner对象的简单输入计算功能示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Java基于Scanner对象的简单输入计算功能。分享给大家供大家参考,具体如下: 问题及代码: 运行结果: 知识点总结: 建立Scanner对象进行输入。以及nextInt() nextDouble()读入不同类
我想基于现有列中的值在我的数据框架中创建一个新列。新列的输入应为。目前,我正在尝试以下方法: 当我尝试这样做时,我得到一个ValueError,说明如下: ValueError:序列的真值不明确。使用a.empty,a.bool(), 还有别的办法吗? 我的预期输出将是由以下值组成的列:
对手转向 游戏等待用户 用户将文本键入JtextField并按Enter键 游戏执行玩家命令 对手再次转向..