要快速从 Python 数组转换为 PostgreSQL?
To convert from Python arrays to PostgreSQL quickly?
这是以下问题的后续问题:How to cast to int array in PostgreSQL?
我在想如何快速将 Python 的有符号整数数组数组的数据类型转换为 PostgreSQL 的 int
:
import numpy as np; # use any data format of Python here
event = np.array([[1,2],[3,4]]);
其中 []
应替换为 {}
并在手动情况下用 '
包围。
在 PostgreSQL 中,接受以下作为数据类型
的语法
...
FOR EACH ROW EXECUTE PROCEDURE insaft_function('{{1,2},{3,4}}');
@JohnMee 的建议
str(event).replace('[','{').replace(']','}').replace('\n ',',')
@ErwinBrandstetter 的建议
坚持使用有符号整数,因为 SQL 标准支持它。
映射到 int
,所以就在 PostgreSQL 端:
TG_ARGV::int[]
我想坚持这个欧文的建议。
测试 运行 @ErwinBrandstetter 答案的简单版本
我必须通过从函数中删除 table-name 来简化他的回答以使其足够集中在这里,因此只需保留一个初始 table measurements[= 的触发器49=]:
CREATE OR REPLACE FUNCTION f_create_my_trigger(_arg0 text)
RETURNS void AS
$func$
BEGIN
EXECUTE format($$
DROP TRIGGER IF EXISTS insaft_ids ON measurements;
CREATE TRIGGER insaft_ids
AFTER INSERT ON measurements
FOR EACH ROW EXECUTE PROCEDURE insaft_function(%1$L)$$
, _arg0
);
END
$func$ LANGUAGE plpgsql;
而我运行:
sudo -u postgres psql detector -c "SELECT f_create_my_trigger('[[1,2],[3,4]]');"
但得到空输出:
f_create_my_trigger
---------------------
(1 row)
如何在 Python 中为 PostgreSQL 9.4 映射到 int
?
设置
您想(重复?)使用 my related answer on dba.SE 中概述的相同触发器函数创建触发器。您需要将值传递给触发器函数以创建具有 multiple 列值的 multiple 行,因此是二维数组。 (但是我们可以使用任何明确定义的字符串!)
将值传递给 PL/pgSQL 触发器函数(触发行的列值除外)的唯一方法是 text
参数,它们可以在函数内部作为 0-based array of text in the special array variable TG_ARGV[]
访问.您可以传递可变数量的参数,但我们之前讨论了表示二维数组的单个字符串文字。
输入来自二维 Python 数组,其中包含 有符号整数 数字,适合 Postgres 类型 integer
。使用 Postgres 类型 bigint
来覆盖无符号整数,.
Python 中的文本表示如下所示:
[[1,2],[3,4]]
Postgres 数组文字的语法:
{{1,2},{3,4}}
并且您想使该过程自动化。
全自动化
您可以在客户端连接 CREATE TRIGGER
语句的字符串,或者您可以将逻辑保留在服务器端函数中并只传递参数。
演示一个采用 table 名称和传递给触发器函数的字符串的示例函数。触发函数insaft_function()
is defined in your previous question on dba.SE.
CREATE OR REPLACE FUNCTION f_create_my_trigger(_tbl regclass, _arg0 text)
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format($$
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
CREATE TRIGGER insaft_%1$s_ids
AFTER INSERT ON %1$s
FOR EACH ROW EXECUTE PROCEDURE insaft_function(%2$L)$$
, _tbl
, translate(_arg0, '[]', '{}')
);
END
$func$;
致电:
SELECT f_create_my_trigger('measurements', '[[1,2],[3,4]]');
或者:
SELECT f_create_my_trigger('some_other_table', '{{5,6},{7,8}}');
现在您可以传递 [[1,2],[3,4]]
(带方括号)或 {{1,2},{3,4}}
(带花括号)。两者的工作原理相同。 translate(_arg0, '[]', '{}'
将第一种形式转换为第二种形式。
如果同名触发器存在,此函数会在创建新触发器之前删除它。您可能想要删除或保留此行:
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
这 运行 具有调用数据库角色的权限。如果需要,您可以使它 运行 具有超级用户(或任何其他)权限。参见:
- Is there a way to disable updates/deletes but still allow triggers to perform them?
有很多方法可以实现这一点。这取决于具体要求。
解释 format()
format()
和数据类型 regclass
有助于安全地连接 DDL 命令并使 SQL 注入不可能。参见:
- Table name as a PostgreSQL function parameter
第一个参数是“格式字符串”,后面是要嵌入到字符串中的参数。我使用 dollar-quoting,这对于示例来说并不是绝对必要的,但通常是连接包含单引号的长字符串的好主意:$$DROP TRIGGER ... $$
format()
是沿 C 函数 sprintf
建模的。 %1$s
是 format()
函数的格式说明符。这意味着格式字符串后的第一个 (1$
) 参数被插入为 未加引号的字符串 (%s
),因此:%1$s
。 format 的第一个参数是示例中的 _tbl
- regclass
参数自动呈现为合法标识符,必要时加双引号,因此 format()
不必做更多。因此只有 %s
,而不是 %I
(标识符)。阅读上面的链接答案了解详情。
使用的另一个格式说明符是 %2$L
:第二个参数作为 引用的字符串文字 .
如果您是 format()
的新手,请尝试这些简单的示例来理解:
SELECT format('input -->|%s|<-- here', '[1,2]')
, format('input -->|%s|<-- here', translate('[1,2]', '[]', '{}'))
, format('input -->|%L|<-- here', translate('[1,2]', '[]', '{}'))
, format('input -->|%I|<-- here', translate('[1,2]', '[]', '{}'));
这是以下问题的后续问题:How to cast to int array in PostgreSQL?
我在想如何快速将 Python 的有符号整数数组数组的数据类型转换为 PostgreSQL 的 int
:
import numpy as np; # use any data format of Python here
event = np.array([[1,2],[3,4]]);
其中 []
应替换为 {}
并在手动情况下用 '
包围。
在 PostgreSQL 中,接受以下作为数据类型
...
FOR EACH ROW EXECUTE PROCEDURE insaft_function('{{1,2},{3,4}}');
@JohnMee 的建议
str(event).replace('[','{').replace(']','}').replace('\n ',',')
@ErwinBrandstetter 的建议
坚持使用有符号整数,因为 SQL 标准支持它。
映射到 int
,所以就在 PostgreSQL 端:
TG_ARGV::int[]
我想坚持这个欧文的建议。
测试 运行 @ErwinBrandstetter 答案的简单版本
我必须通过从函数中删除 table-name 来简化他的回答以使其足够集中在这里,因此只需保留一个初始 table measurements[= 的触发器49=]:
CREATE OR REPLACE FUNCTION f_create_my_trigger(_arg0 text)
RETURNS void AS
$func$
BEGIN
EXECUTE format($$
DROP TRIGGER IF EXISTS insaft_ids ON measurements;
CREATE TRIGGER insaft_ids
AFTER INSERT ON measurements
FOR EACH ROW EXECUTE PROCEDURE insaft_function(%1$L)$$
, _arg0
);
END
$func$ LANGUAGE plpgsql;
而我运行:
sudo -u postgres psql detector -c "SELECT f_create_my_trigger('[[1,2],[3,4]]');"
但得到空输出:
f_create_my_trigger
---------------------
(1 row)
如何在 Python 中为 PostgreSQL 9.4 映射到 int
?
设置
您想(重复?)使用 my related answer on dba.SE 中概述的相同触发器函数创建触发器。您需要将值传递给触发器函数以创建具有 multiple 列值的 multiple 行,因此是二维数组。 (但是我们可以使用任何明确定义的字符串!)
将值传递给 PL/pgSQL 触发器函数(触发行的列值除外)的唯一方法是 text
参数,它们可以在函数内部作为 0-based array of text in the special array variable TG_ARGV[]
访问.您可以传递可变数量的参数,但我们之前讨论了表示二维数组的单个字符串文字。
输入来自二维 Python 数组,其中包含 有符号整数 数字,适合 Postgres 类型 integer
。使用 Postgres 类型 bigint
来覆盖无符号整数,
Python 中的文本表示如下所示:
[[1,2],[3,4]]
Postgres 数组文字的语法:
{{1,2},{3,4}}
并且您想使该过程自动化。
全自动化
您可以在客户端连接 CREATE TRIGGER
语句的字符串,或者您可以将逻辑保留在服务器端函数中并只传递参数。
演示一个采用 table 名称和传递给触发器函数的字符串的示例函数。触发函数insaft_function()
is defined in your previous question on dba.SE.
CREATE OR REPLACE FUNCTION f_create_my_trigger(_tbl regclass, _arg0 text)
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format($$
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
CREATE TRIGGER insaft_%1$s_ids
AFTER INSERT ON %1$s
FOR EACH ROW EXECUTE PROCEDURE insaft_function(%2$L)$$
, _tbl
, translate(_arg0, '[]', '{}')
);
END
$func$;
致电:
SELECT f_create_my_trigger('measurements', '[[1,2],[3,4]]');
或者:
SELECT f_create_my_trigger('some_other_table', '{{5,6},{7,8}}');
现在您可以传递 [[1,2],[3,4]]
(带方括号)或 {{1,2},{3,4}}
(带花括号)。两者的工作原理相同。 translate(_arg0, '[]', '{}'
将第一种形式转换为第二种形式。
如果同名触发器存在,此函数会在创建新触发器之前删除它。您可能想要删除或保留此行:
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
这 运行 具有调用数据库角色的权限。如果需要,您可以使它 运行 具有超级用户(或任何其他)权限。参见:
- Is there a way to disable updates/deletes but still allow triggers to perform them?
有很多方法可以实现这一点。这取决于具体要求。
解释 format()
format()
和数据类型 regclass
有助于安全地连接 DDL 命令并使 SQL 注入不可能。参见:
- Table name as a PostgreSQL function parameter
第一个参数是“格式字符串”,后面是要嵌入到字符串中的参数。我使用 dollar-quoting,这对于示例来说并不是绝对必要的,但通常是连接包含单引号的长字符串的好主意:$$DROP TRIGGER ... $$
format()
是沿 C 函数 sprintf
建模的。 %1$s
是 format()
函数的格式说明符。这意味着格式字符串后的第一个 (1$
) 参数被插入为 未加引号的字符串 (%s
),因此:%1$s
。 format 的第一个参数是示例中的 _tbl
- regclass
参数自动呈现为合法标识符,必要时加双引号,因此 format()
不必做更多。因此只有 %s
,而不是 %I
(标识符)。阅读上面的链接答案了解详情。
使用的另一个格式说明符是 %2$L
:第二个参数作为 引用的字符串文字 .
如果您是 format()
的新手,请尝试这些简单的示例来理解:
SELECT format('input -->|%s|<-- here', '[1,2]')
, format('input -->|%s|<-- here', translate('[1,2]', '[]', '{}'))
, format('input -->|%L|<-- here', translate('[1,2]', '[]', '{}'))
, format('input -->|%I|<-- here', translate('[1,2]', '[]', '{}'));