Оценочные параметры таблицы Postgresql JDBC
MSSQL имеет отличную функцию Табличные значения. Он позволяет передавать таблицу пользовательских данных хранимым процедурам и функциям.
Мне было интересно, что такое эквивалент в PostgreSQL, если он существует, используя JDBC?
Я знаю о возможности передачи массивов в качестве параметров функции, но это похоже на типы данных PostgreSQL.
Рассмотрим следующий код PL/pgSQL:
CREATE TYPE number_with_time AS(
_num float,
_date timestamp
);
и этот заголовок функции:
CREATE OR REPLACE FUNCTION myfunc(arr number_with_time[])
Может ли кто-нибудь отправить код Java с помощью драйвера JDBC для вызова этой функции с массивом определенного пользователем типа данных?
Ответы
Ответ 1
Предполагая, что вы хотите передать значения из клиента. Если значения уже существуют в базе данных, существуют другие, более простые способы...
Синтаксис для массива complex_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
.
Я не буду использовать имя "дата" для 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 Fiddle демонстрирует:
- над функцией 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
Ответ 2
Попробуйте что-то вроде этого:
------------------ 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();
}
Полезные ссылки:
Ответ 3
Ваша проблема заключается в том, что PostgreSQL может использовать табличный или сложный тип в качестве функционального параметра или массива "table или complex type" в качестве параметра функции?
postgresql вся поддержка. и когда вы создаете таблицу, она автоматически создает сложный тип с именем так же, как и имя_таблицы.
например:
digoal=# create table tbl123(id int, info text);
CREATE TABLE
digoal=# select typname from pg_type where typname='tbl123';
typname
---------
tbl123
(1 row)
и вы можете использовать этот тип в функции direct.
для 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)