这是一个后续问题:
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]]);
其中[]应替换为{}并用’if手动包围.
在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的答案
我必须通过从函数中删除表名来简化他的答案以保持足够的重点,这样只需保留一个初始表测量的触发器:
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 previous answer on dba.SE中概述的相同的触发函数来创建触发器(重复?).您需要将值传递给触发器函数以创建具有多个列值的多行,因此创建二维数组. (但我们可以使用任何明确定义的字符串!)
将值传递给PL / pgSQL触发器函数的唯一方法是文本参数,可以在函数内部访问0-based array of text TG_ARGV[]
.您可以传递可变数量的参数,但我们之前讨论过表示2维数组的单个字符串文字.
您想要传递的值来自具有有符号整数的2维Python数组,因此它们将适合Postgres整数类型.你必须使用Postgres类型bigint来确定无符号整数,like I commented.
Python中的文本表示如下所示:
[[1,2],[3,4]]
Postgres数组文字的语法如下所示:
{{1,2},{3,4}}
似乎你想要自动化这个过程.
完全自动化
您可以在客户端中连接CREATE TRIGGER语句的字符串,也可以在服务器端函数中保留逻辑并只传递参数.
演示一个示例函数,我们将表名和用作参数的字符串传递给触发器函数.触发功能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 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$LANGUAGE plpgsql;
呼叫:
SELECT f_create_my_trigger('measurements', '[[1,2],[3,4]]');
要么:
SELECT f_create_my_trigger('some_other_table', '{{5,6},{7,8}}');
SQL Fiddle演示.
现在你可以传递[[1,2],[3,4]](带方括号)或{{1,2},{3,4}}(带花括号).两者都是一样的. translate(_arg0,'[]’,'{}’将第一个转换为第二个形式.
在创建新触发器之前,此函数会自动删除相同名称的触发器(如果存在).您可能想要删除或保留此行:
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
它以调用DB角色的权限运行.如果需要,你可以把它变成run with superuser (or any other) privileges.
还有很多其他方法可以实现这一目标.这完全取决于具体要求.
解释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.格式的第一个参数是示例中的_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]', '[]', '{}'));