Postgresql JDBC表值参数
MSSQL有一个很棒的function叫做Table Valued Parameters 。 它允许您将自定义数据表传递给存储过程和函数。
我想知道PostgreSQL中的等价物,如果存在,使用JDBC? 我知道将数组作为函数参数传递的选项,但这似乎仅限于PostgreSQL数据类型。
考虑以下PL / pgSQL代码:
CREATE TYPE number_with_time AS( _num float, _date timestamp );
和这个函数头:
CREATE OR REPLACE FUNCTION myfunc(arr number_with_time[])
任何人都可以使用JDBC驱动程序发布Java代码,使用用户定义数据类型的数组调用该函数吗?
假设您要从客户端传递值。 如果数据库中已存在这些值,还有其他更简单的方法……
composite_type数组的语法
我知道将数组作为函数参数传递的选项,但这似乎仅限于PostgreSQL数据类型。
您可以传递的内容似乎受到Java类型和JDBC类型的限制 ,并且似乎没有规定数组类型,更不用说复合值数组……
但是,您始终可以传递text
表示。 我基于两个基本事实:
1) 每份文件:
可以创建任何内置或用户定义的基类型,枚举类型或复合类型的数组。 尚不支持域的数组。
大胆强调我的。 因此,在创建了问题中定义的类型number_with_time
之后 – 或者定义了具有相同列的表(自动在系统中注册相应的复合类型)之后,您还可以自动使用数组类型number_with_time[]
。
2) 每个值都有一个text
表示。
因此,还有number_with_time[]
的文本表示:
'{"(1,2014-04-20 20:00:00)","(2,2014-04-21 21:00:00)"}'::number_with_time[]
函数调用
实际的函数调用取决于函数中定义的返回值 – 这在您的问题中隐藏。
为避免JDBC中数组处理的复杂性,请传递text
表示。 使用text
参数创建函数。
我不打算使用名称“date”作为timestamp
。 使用此略微调整的类型定义:
CREATE TYPE number_with_time AS( _num float , _ts timestamp );
简单的SQL函数:
CREATE OR REPLACE FUNCTION myfunc_sql(_arr_txt text) RETURNS integer AS -- example $func$ SELECT sum(_num)::int FROM unnest (_arr_txt::number_with_time[]) x WHERE _ts > '2014-04-19 20:00:00'; $func$ LANGUAGE sql;
呼叫:
SELECT myfunc_sql('{"(1,2014-04-20 20:00:00)","(2,2014-04-21 21:00:00)"}');
这个SQL小提琴演示:
- 以上SQL函数
- PL / pgSQL变种
- 复合类型数组的几种语法变体
- 函数调用。
像使用简单text
参数的任何其他函数一样调用函数:
CallableStatement myProc = conn.prepareCall("{ ? = call myfunc_sql( ? ) }"); myProc.registerOutParameter(1, Types.VARCHAR); // you have to escape double quotes in a Java string! myProc.setString(2, "{\"(1,2014-04-20 20:00:00)\",\"(2,2014-04-21 21:00:00)\"}"); myProc.execute(); String mySum = myProc.getInt(1); myProc.close();
Postgres JDBC手册中的详细信息。
通过JDBC返回整个表的示例:
从PL / pgSQL函数返回行
尝试这样的事情:
------------------ your connection V Array inArray = conn.createArrayOf("integer", new Integer[][] {{1,10},{2,20}}); stmt.setArray(1, inArray);
您可以用来构建测试的示例方法:
public void testInsertMultiDimension() throws Exception { Connection c = getConnection(); PreparedStatement stmt = c.prepareStatement("INSERT INTO sal_emp VALUES ('multi_Bill',?,?);"); Array intArray = c.createArrayOf("integer", new Integer[] {1000,1000,1000,1000}); String[][] elements = new String[2][]; elements[0] = new String[] {"meeting_m","lunch_m"}; elements[1] = new String[] {"training_m","presentation_m"}; //Note - although this is a multi-dimensional array, we still supply the base element of the array Array multiArray = c.createArrayOf("text", elements); stmt.setArray(1, intArray); stmt.setArray(2, multiArray); stmt.execute(); //Note - free is not implemented //myArray.free(); stmt.close(); c.close(); }
有用的url:
- 绑定参数为PostgreSQL数组
- JDBC中的Postgres和多维数组
- 将数组从Java传递到Postgres
你的问题是PostgreSQL可以使用表或复杂类型作为函数的参数或“表或复杂类型”的数组作为函数的参数吗? postgresql所有支持。 当你创建一个表时,它会自动创建一个名为tablename的复杂类型。 喜欢 :
digoal=# create table tbl123(id int, info text); CREATE TABLE digoal=# select typname from pg_type where typname='tbl123'; typname --------- tbl123 (1 row)
你可以直接在函数中使用这种类型。 对于exp:
digoal=# create or replace function f_tbl123(i tbl123) returns tbl123 as $$ declare begin return i; end; $$ language plpgsql; CREATE FUNCTION digoal=# insert into tbl123 values (1,'test'),(2,'test2'); INSERT 0 2 digoal=# select f_tbl123(t) from tbl123 t; f_tbl123 ----------- (1,test) (2,test2) (2 rows)
该数组也可用于postgresql函数。 如果你不知道java中的数组构造,我认为这个exp可以帮到你。
digoal=# select (unnest('{"(1,abc)","(2,ww)"}'::tbl123[])).*; id | info ----+------ 1 | abc 2 | ww (2 rows) digoal=# select '{"(1,abc)","(2,ww)"}'::tbl123[]; tbl123 ---------------------- {"(1,abc)","(2,ww)"} (1 row) digoal=# select array['(1,abc)','(2,ww)']; array ---------------------- {"(1,abc)","(2,ww)"} (1 row) digoal=# select array['(1,abc)','(2,ww)']::tbl123[]; array ---------------------- {"(1,abc)","(2,ww)"} (1 row) digoal=# select (unnest(array['(1,abc)','(2,ww)'])::tbl123).*; id | info ----+------ 1 | abc 2 | ww (2 rows)