Оценочные параметры таблицы 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)